diff --git a/libs/libarchopenfpga/src/arch_direct.cpp b/libs/libarchopenfpga/src/arch_direct.cpp index a741dd878..33565deeb 100644 --- a/libs/libarchopenfpga/src/arch_direct.cpp +++ b/libs/libarchopenfpga/src/arch_direct.cpp @@ -1,7 +1,7 @@ -#include "vtr_assert.h" - #include "arch_direct.h" +#include "vtr_assert.h" + /************************************************************************ * Member functions for class ArchDirect ***********************************************************************/ @@ -9,9 +9,7 @@ /************************************************************************ * Constructors ***********************************************************************/ -ArchDirect::ArchDirect() { - return; -} +ArchDirect::ArchDirect() { return; } /************************************************************************ * Public Accessors : aggregates @@ -21,7 +19,7 @@ ArchDirect::arch_direct_range ArchDirect::directs() const { } /************************************************************************ - * Public Accessors + * Public Accessors ***********************************************************************/ ArchDirectId ArchDirect::direct(const std::string& name) const { if (0 < direct_name2ids_.count(name)) { @@ -33,31 +31,31 @@ ArchDirectId ArchDirect::direct(const std::string& name) const { std::string ArchDirect::name(const ArchDirectId& direct_id) const { /* validate the direct_id */ VTR_ASSERT(valid_direct_id(direct_id)); - return names_[direct_id]; + return names_[direct_id]; } CircuitModelId ArchDirect::circuit_model(const ArchDirectId& direct_id) const { /* validate the direct_id */ VTR_ASSERT(valid_direct_id(direct_id)); - return circuit_models_[direct_id]; + return circuit_models_[direct_id]; } e_direct_type ArchDirect::type(const ArchDirectId& direct_id) const { /* validate the direct_id */ VTR_ASSERT(valid_direct_id(direct_id)); - return types_[direct_id]; + return types_[direct_id]; } e_direct_direction ArchDirect::x_dir(const ArchDirectId& direct_id) const { /* validate the direct_id */ VTR_ASSERT(valid_direct_id(direct_id)); - return directions_[direct_id].x(); + return directions_[direct_id].x(); } e_direct_direction ArchDirect::y_dir(const ArchDirectId& direct_id) const { /* validate the direct_id */ VTR_ASSERT(valid_direct_id(direct_id)); - return directions_[direct_id].y(); + return directions_[direct_id].y(); } /************************************************************************ @@ -74,24 +72,27 @@ ArchDirectId ArchDirect::add_direct(const std::string& name) { names_.push_back(name); circuit_models_.push_back(CircuitModelId::INVALID()); types_.emplace_back(NUM_DIRECT_TYPES); - directions_.emplace_back(vtr::Point(NUM_DIRECT_DIRECTIONS, NUM_DIRECT_DIRECTIONS)); + directions_.emplace_back(vtr::Point( + NUM_DIRECT_DIRECTIONS, NUM_DIRECT_DIRECTIONS)); /* Register in the name-to-id map */ direct_name2ids_[name] = direct; - + return direct; } -void ArchDirect::set_circuit_model(const ArchDirectId& direct_id, const CircuitModelId& circuit_model) { +void ArchDirect::set_circuit_model(const ArchDirectId& direct_id, + const CircuitModelId& circuit_model) { /* validate the direct_id */ VTR_ASSERT(valid_direct_id(direct_id)); - circuit_models_[direct_id] = circuit_model; + circuit_models_[direct_id] = circuit_model; } -void ArchDirect::set_type(const ArchDirectId& direct_id, const e_direct_type& type) { +void ArchDirect::set_type(const ArchDirectId& direct_id, + const e_direct_type& type) { /* validate the direct_id */ VTR_ASSERT(valid_direct_id(direct_id)); - types_[direct_id] = type; + types_[direct_id] = type; } void ArchDirect::set_direction(const ArchDirectId& direct_id, @@ -99,14 +100,15 @@ void ArchDirect::set_direction(const ArchDirectId& direct_id, const e_direct_direction& y_dir) { /* validate the direct_id */ VTR_ASSERT(valid_direct_id(direct_id)); - directions_[direct_id].set_x(x_dir); - directions_[direct_id].set_y(y_dir); + directions_[direct_id].set_x(x_dir); + directions_[direct_id].set_y(y_dir); } /************************************************************************ - * Internal invalidators/validators + * Internal invalidators/validators ***********************************************************************/ /* Validators */ bool ArchDirect::valid_direct_id(const ArchDirectId& direct_id) const { - return ( size_t(direct_id) < direct_ids_.size() ) && ( direct_id == direct_ids_[direct_id] ); + return (size_t(direct_id) < direct_ids_.size()) && + (direct_id == direct_ids_[direct_id]); } diff --git a/libs/libarchopenfpga/src/arch_direct.h b/libs/libarchopenfpga/src/arch_direct.h index cbdf4cc8e..5508095eb 100644 --- a/libs/libarchopenfpga/src/arch_direct.h +++ b/libs/libarchopenfpga/src/arch_direct.h @@ -1,17 +1,16 @@ #ifndef ARCH_DIRECT_H #define ARCH_DIRECT_H -#include #include +#include -#include "vtr_vector.h" -#include "vtr_geometry.h" - -#include "circuit_library_fwd.h" #include "arch_direct_fwd.h" +#include "circuit_library_fwd.h" +#include "vtr_geometry.h" +#include "vtr_vector.h" /******************************************************************** - * Define the types of point to point connection between CLBs + * Define the types of point to point connection between CLBs * These types are supplementary to the original VPR direct connections * Here we extend to the cross-row and cross-column connections ********************************************************************/ @@ -22,83 +21,88 @@ enum e_direct_type { INTER_ROW, NUM_DIRECT_TYPES }; -constexpr std::array DIRECT_TYPE_STRING = {{"inner_column", "inner_row", "inter_column", "inter_row"}}; +constexpr std::array DIRECT_TYPE_STRING = { + {"inner_column", "inner_row", "inter_column", "inter_row"}}; -enum e_direct_direction { - POSITIVE_DIR, - NEGATIVE_DIR, - NUM_DIRECT_DIRECTIONS -}; -constexpr std::array DIRECT_DIRECTION_STRING = {{"positive", "negative"}}; +enum e_direct_direction { POSITIVE_DIR, NEGATIVE_DIR, NUM_DIRECT_DIRECTIONS }; +constexpr std::array + DIRECT_DIRECTION_STRING = {{"positive", "negative"}}; /******************************************************************** * A data base to describe the direct connection in OpenFPGA architecture * For each direct connection, it will include - * - name: the identifier to annotate the original direct connection in VPR architecture + * - name: the identifier to annotate the original direct connection in VPR + *architecture * - circuit model: the circuit model to used to implement this connection * - type: if this connection should be cross-column or cross-row - * - x-direction: how this connection is going to be applied to adjacent columns + * - x-direction: how this connection is going to be applied to adjacent columns * a positive x-direction means that column A will be connected * to the column B on the right side of column A - * - y-direction: how this connection is going to be applied to adjacent rows + * - y-direction: how this connection is going to be applied to adjacent rows * a positive y-direction means that row A will be connected * to the row B on the bottom side of row A * - * Note that: this is the data structure to be used when parsing the XML + * Note that: this is the data structure to be used when parsing the XML * this is NOT the data structure to be use in core engine ********************************************************************/ class ArchDirect { - public: /* Types */ - typedef vtr::vector::const_iterator arch_direct_iterator; - /* Create range */ - typedef vtr::Range arch_direct_range; + public: /* Types */ + typedef vtr::vector::const_iterator + arch_direct_iterator; + /* Create range */ + typedef vtr::Range arch_direct_range; - public: /* Constructors */ - ArchDirect(); + public: /* Constructors */ + ArchDirect(); - public: /* Accessors: aggregates */ - arch_direct_range directs() const; + public: /* Accessors: aggregates */ + arch_direct_range directs() const; - public: /* Public Accessors: Basic data query on directs */ - ArchDirectId direct(const std::string& name) const; - std::string name(const ArchDirectId& direct_id) const; - CircuitModelId circuit_model(const ArchDirectId& direct_id) const; - e_direct_type type(const ArchDirectId& direct_id) const; - e_direct_direction x_dir(const ArchDirectId& direct_id) const; - e_direct_direction y_dir(const ArchDirectId& direct_id) const; - public: /* Public Mutators */ - ArchDirectId add_direct(const std::string& name); - void set_circuit_model(const ArchDirectId& direct_id, const CircuitModelId& circuit_model); - void set_type(const ArchDirectId& direct_id, const e_direct_type& type); - void set_direction(const ArchDirectId& direct_id, - const e_direct_direction& x_dir, - const e_direct_direction& y_dir); - public: /* Public invalidators/validators */ - bool valid_direct_id(const ArchDirectId& direct_id) const; - private: /* Internal data */ - vtr::vector direct_ids_; - - /* Unique name: the identifier to annotate the original direct connection in VPR architecture */ - vtr::vector names_; + public: /* Public Accessors: Basic data query on directs */ + ArchDirectId direct(const std::string& name) const; + std::string name(const ArchDirectId& direct_id) const; + CircuitModelId circuit_model(const ArchDirectId& direct_id) const; + e_direct_type type(const ArchDirectId& direct_id) const; + e_direct_direction x_dir(const ArchDirectId& direct_id) const; + e_direct_direction y_dir(const ArchDirectId& direct_id) const; - /* circuit model: the circuit model to used to implement this connection */ - vtr::vector circuit_models_; + public: /* Public Mutators */ + ArchDirectId add_direct(const std::string& name); + void set_circuit_model(const ArchDirectId& direct_id, + const CircuitModelId& circuit_model); + void set_type(const ArchDirectId& direct_id, const e_direct_type& type); + void set_direction(const ArchDirectId& direct_id, + const e_direct_direction& x_dir, + const e_direct_direction& y_dir); - /* type: if this connection should be cross-column or cross-row */ - vtr::vector types_; + public: /* Public invalidators/validators */ + bool valid_direct_id(const ArchDirectId& direct_id) const; - /* - * x-direction: how this connection is going to be applied to adjacent columns - * a positive x-direction means that column A will be connected - * to the column B on the right side of column A - * y-direction: how this connection is going to be applied to adjacent rows - * a positive y-direction means that row A will be connected - * to the row B on the bottom side of row A - */ - vtr::vector> directions_; + private: /* Internal data */ + vtr::vector direct_ids_; - /* Fast look-up */ - std::map direct_name2ids_; + /* Unique name: the identifier to annotate the original direct connection in + * VPR architecture */ + vtr::vector names_; + + /* circuit model: the circuit model to used to implement this connection */ + vtr::vector circuit_models_; + + /* type: if this connection should be cross-column or cross-row */ + vtr::vector types_; + + /* + * x-direction: how this connection is going to be applied to adjacent columns + * a positive x-direction means that column A will be connected + * to the column B on the right side of column A + * y-direction: how this connection is going to be applied to adjacent rows + * a positive y-direction means that row A will be connected + * to the row B on the bottom side of row A + */ + vtr::vector> directions_; + + /* Fast look-up */ + std::map direct_name2ids_; }; #endif diff --git a/libs/libarchopenfpga/src/arch_direct_fwd.h b/libs/libarchopenfpga/src/arch_direct_fwd.h index 8a1f302f3..ba825b33c 100644 --- a/libs/libarchopenfpga/src/arch_direct_fwd.h +++ b/libs/libarchopenfpga/src/arch_direct_fwd.h @@ -1,11 +1,11 @@ /************************************************************************ * A header file for ArchDirect class, including critical data declaration * Please include this file only for using any TechnologyLibrary data structure - * Refer to arch_direct.h for more details + * Refer to arch_direct.h for more details ***********************************************************************/ /************************************************************************ - * Create strong id for ArchDirect to avoid illegal type casting + * Create strong id for ArchDirect to avoid illegal type casting ***********************************************************************/ #ifndef ARCH_DIRECT_FWD_H #define ARCH_DIRECT_FWD_H diff --git a/libs/libarchopenfpga/src/bitstream_setting.cpp b/libs/libarchopenfpga/src/bitstream_setting.cpp index f239a78b3..c04eeba87 100644 --- a/libs/libarchopenfpga/src/bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/bitstream_setting.cpp @@ -1,7 +1,7 @@ -#include "vtr_assert.h" - #include "bitstream_setting.h" +#include "vtr_assert.h" + /* namespace openfpga begins */ namespace openfpga { @@ -12,88 +12,106 @@ namespace openfpga { /************************************************************************ * Public Accessors : aggregates ***********************************************************************/ -BitstreamSetting::bitstream_pb_type_setting_range BitstreamSetting::pb_type_settings() const { - return vtr::make_range(pb_type_setting_ids_.begin(), pb_type_setting_ids_.end()); +BitstreamSetting::bitstream_pb_type_setting_range +BitstreamSetting::pb_type_settings() const { + return vtr::make_range(pb_type_setting_ids_.begin(), + pb_type_setting_ids_.end()); } -BitstreamSetting::bitstream_interconnect_setting_range BitstreamSetting::interconnect_settings() const { - return vtr::make_range(interconnect_setting_ids_.begin(), interconnect_setting_ids_.end()); +BitstreamSetting::bitstream_interconnect_setting_range +BitstreamSetting::interconnect_settings() const { + return vtr::make_range(interconnect_setting_ids_.begin(), + interconnect_setting_ids_.end()); } /************************************************************************ * Constructors ***********************************************************************/ -BitstreamSetting::BitstreamSetting() { - return; -} +BitstreamSetting::BitstreamSetting() { return; } /************************************************************************ * Public Accessors ***********************************************************************/ -std::string BitstreamSetting::pb_type_name(const BitstreamPbTypeSettingId& pb_type_setting_id) const { +std::string BitstreamSetting::pb_type_name( + const BitstreamPbTypeSettingId& pb_type_setting_id) const { VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id)); return pb_type_names_[pb_type_setting_id]; } -std::vector BitstreamSetting::parent_pb_type_names(const BitstreamPbTypeSettingId& pb_type_setting_id) const { +std::vector BitstreamSetting::parent_pb_type_names( + const BitstreamPbTypeSettingId& pb_type_setting_id) const { VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id)); return parent_pb_type_names_[pb_type_setting_id]; } -std::vector BitstreamSetting::parent_mode_names(const BitstreamPbTypeSettingId& pb_type_setting_id) const { +std::vector BitstreamSetting::parent_mode_names( + const BitstreamPbTypeSettingId& pb_type_setting_id) const { VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id)); return parent_mode_names_[pb_type_setting_id]; } -std::string BitstreamSetting::pb_type_bitstream_source(const BitstreamPbTypeSettingId& pb_type_setting_id) const { +std::string BitstreamSetting::pb_type_bitstream_source( + const BitstreamPbTypeSettingId& pb_type_setting_id) const { VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id)); return pb_type_bitstream_sources_[pb_type_setting_id]; } -std::string BitstreamSetting::pb_type_bitstream_content(const BitstreamPbTypeSettingId& pb_type_setting_id) const { +std::string BitstreamSetting::pb_type_bitstream_content( + const BitstreamPbTypeSettingId& pb_type_setting_id) const { VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id)); return pb_type_bitstream_contents_[pb_type_setting_id]; } -bool BitstreamSetting::is_mode_select_bitstream(const BitstreamPbTypeSettingId& pb_type_setting_id) const { +bool BitstreamSetting::is_mode_select_bitstream( + const BitstreamPbTypeSettingId& pb_type_setting_id) const { VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id)); return is_mode_select_bitstreams_[pb_type_setting_id]; } -size_t BitstreamSetting::bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id) const { +size_t BitstreamSetting::bitstream_offset( + const BitstreamPbTypeSettingId& pb_type_setting_id) const { VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id)); return bitstream_offsets_[pb_type_setting_id]; } -std::string BitstreamSetting::interconnect_name(const BitstreamInterconnectSettingId& interconnect_setting_id) const { - VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id)); +std::string BitstreamSetting::interconnect_name( + const BitstreamInterconnectSettingId& interconnect_setting_id) const { + VTR_ASSERT(true == + valid_bitstream_interconnect_setting_id(interconnect_setting_id)); return interconnect_names_[interconnect_setting_id]; } -std::vector BitstreamSetting::parent_pb_type_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const { - VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id)); +std::vector BitstreamSetting::parent_pb_type_names( + const BitstreamInterconnectSettingId& interconnect_setting_id) const { + VTR_ASSERT(true == + valid_bitstream_interconnect_setting_id(interconnect_setting_id)); return interconnect_parent_pb_type_names_[interconnect_setting_id]; } -std::vector BitstreamSetting::parent_mode_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const { - VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id)); +std::vector BitstreamSetting::parent_mode_names( + const BitstreamInterconnectSettingId& interconnect_setting_id) const { + VTR_ASSERT(true == + valid_bitstream_interconnect_setting_id(interconnect_setting_id)); return interconnect_parent_mode_names_[interconnect_setting_id]; } -std::string BitstreamSetting::default_path(const BitstreamInterconnectSettingId& interconnect_setting_id) const { - VTR_ASSERT(true == valid_bitstream_interconnect_setting_id(interconnect_setting_id)); +std::string BitstreamSetting::default_path( + const BitstreamInterconnectSettingId& interconnect_setting_id) const { + VTR_ASSERT(true == + valid_bitstream_interconnect_setting_id(interconnect_setting_id)); return interconnect_default_paths_[interconnect_setting_id]; } /************************************************************************ * Public Mutators ***********************************************************************/ -BitstreamPbTypeSettingId BitstreamSetting::add_bitstream_pb_type_setting(const std::string& pb_type_name, - const std::vector& parent_pb_type_names, - const std::vector& parent_mode_names, - const std::string& bitstream_source, - const std::string& bitstream_content) { - BitstreamPbTypeSettingId pb_type_setting_id = BitstreamPbTypeSettingId(pb_type_setting_ids_.size()); +BitstreamPbTypeSettingId BitstreamSetting::add_bitstream_pb_type_setting( + const std::string& pb_type_name, + const std::vector& parent_pb_type_names, + const std::vector& parent_mode_names, + const std::string& bitstream_source, const std::string& bitstream_content) { + BitstreamPbTypeSettingId pb_type_setting_id = + BitstreamPbTypeSettingId(pb_type_setting_ids_.size()); pb_type_setting_ids_.push_back(pb_type_setting_id); pb_type_names_.push_back(pb_type_name); parent_pb_type_names_.push_back(parent_pb_type_names); @@ -106,23 +124,27 @@ BitstreamPbTypeSettingId BitstreamSetting::add_bitstream_pb_type_setting(const s return pb_type_setting_id; } -void BitstreamSetting::set_mode_select_bitstream(const BitstreamPbTypeSettingId& pb_type_setting_id, - const bool& is_mode_select_bitstream) { +void BitstreamSetting::set_mode_select_bitstream( + const BitstreamPbTypeSettingId& pb_type_setting_id, + const bool& is_mode_select_bitstream) { VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id)); is_mode_select_bitstreams_[pb_type_setting_id] = is_mode_select_bitstream; } -void BitstreamSetting::set_bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id, - const size_t& offset) { +void BitstreamSetting::set_bitstream_offset( + const BitstreamPbTypeSettingId& pb_type_setting_id, const size_t& offset) { VTR_ASSERT(true == valid_bitstream_pb_type_setting_id(pb_type_setting_id)); bitstream_offsets_[pb_type_setting_id] = offset; } -BitstreamInterconnectSettingId BitstreamSetting::add_bitstream_interconnect_setting(const std::string& interconnect_name, - const std::vector& parent_pb_type_names, - const std::vector& parent_mode_names, - const std::string& default_path) { - BitstreamInterconnectSettingId interc_setting_id = BitstreamInterconnectSettingId(interconnect_setting_ids_.size()); +BitstreamInterconnectSettingId +BitstreamSetting::add_bitstream_interconnect_setting( + const std::string& interconnect_name, + const std::vector& parent_pb_type_names, + const std::vector& parent_mode_names, + const std::string& default_path) { + BitstreamInterconnectSettingId interc_setting_id = + BitstreamInterconnectSettingId(interconnect_setting_ids_.size()); interconnect_setting_ids_.push_back(interc_setting_id); interconnect_names_.push_back(interconnect_name); interconnect_parent_pb_type_names_.push_back(parent_pb_type_names); @@ -135,12 +157,17 @@ BitstreamInterconnectSettingId BitstreamSetting::add_bitstream_interconnect_sett /************************************************************************ * Public Validators ***********************************************************************/ -bool BitstreamSetting::valid_bitstream_pb_type_setting_id(const BitstreamPbTypeSettingId& pb_type_setting_id) const { - return ( size_t(pb_type_setting_id) < pb_type_setting_ids_.size() ) && ( pb_type_setting_id == pb_type_setting_ids_[pb_type_setting_id] ); +bool BitstreamSetting::valid_bitstream_pb_type_setting_id( + const BitstreamPbTypeSettingId& pb_type_setting_id) const { + return (size_t(pb_type_setting_id) < pb_type_setting_ids_.size()) && + (pb_type_setting_id == pb_type_setting_ids_[pb_type_setting_id]); } -bool BitstreamSetting::valid_bitstream_interconnect_setting_id(const BitstreamInterconnectSettingId& interconnect_setting_id) const { - return ( size_t(interconnect_setting_id) < interconnect_setting_ids_.size() ) && ( interconnect_setting_id == interconnect_setting_ids_[interconnect_setting_id] ); +bool BitstreamSetting::valid_bitstream_interconnect_setting_id( + const BitstreamInterconnectSettingId& interconnect_setting_id) const { + return (size_t(interconnect_setting_id) < interconnect_setting_ids_.size()) && + (interconnect_setting_id == + interconnect_setting_ids_[interconnect_setting_id]); } -} /* namespace openfpga ends */ +} // namespace openfpga diff --git a/libs/libarchopenfpga/src/bitstream_setting.h b/libs/libarchopenfpga/src/bitstream_setting.h index 63cb9092b..7963942a0 100644 --- a/libs/libarchopenfpga/src/bitstream_setting.h +++ b/libs/libarchopenfpga/src/bitstream_setting.h @@ -3,23 +3,24 @@ /******************************************************************** * This file include the declaration of simulation settings - * which are used by OpenFPGA + * which are used by OpenFPGA *******************************************************************/ #include -#include "vtr_vector.h" - -#include "bitstream_setting_fwd.h" +#include "bitstream_setting_fwd.h" +#include "vtr_vector.h" /* namespace openfpga begins */ namespace openfpga { /******************************************************************** * A data structure to describe bitstream settings - * + * * This data structure includes following types of settings: - * - Pb type: include definiting hard coded bitstream for pb_types (LUT or configurable pb_type for mode selection) - * - Interconnect: include defining default paths for routing multiplexers in pb_types + * - Pb type: include definiting hard coded bitstream for pb_types (LUT or + *configurable pb_type for mode selection) + * - Interconnect: include defining default paths for routing multiplexers in + *pb_types * * Typical usage: * -------------- @@ -29,74 +30,111 @@ namespace openfpga { * *******************************************************************/ class BitstreamSetting { - public: /* Types */ - typedef vtr::vector::const_iterator bitstream_pb_type_setting_iterator; - typedef vtr::vector::const_iterator bitstream_interconnect_setting_iterator; - /* Create range */ - typedef vtr::Range bitstream_pb_type_setting_range; - typedef vtr::Range bitstream_interconnect_setting_range; - public: /* Constructors */ - BitstreamSetting(); - public: /* Accessors: aggregates */ - bitstream_pb_type_setting_range pb_type_settings() const; - bitstream_interconnect_setting_range interconnect_settings() const; - public: /* Public Accessors */ - std::string pb_type_name(const BitstreamPbTypeSettingId& pb_type_setting_id) const; - std::vector parent_pb_type_names(const BitstreamPbTypeSettingId& pb_type_setting_id) const; - std::vector parent_mode_names(const BitstreamPbTypeSettingId& pb_type_setting_id) const; - std::string pb_type_bitstream_source(const BitstreamPbTypeSettingId& pb_type_setting_id) const; - std::string pb_type_bitstream_content(const BitstreamPbTypeSettingId& pb_type_setting_id) const; - bool is_mode_select_bitstream(const BitstreamPbTypeSettingId& pb_type_setting_id) const; - size_t bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id) const; - std::string interconnect_name(const BitstreamInterconnectSettingId& interconnect_setting_id) const; - std::vector parent_pb_type_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const; - std::vector parent_mode_names(const BitstreamInterconnectSettingId& interconnect_setting_id) const; - std::string default_path(const BitstreamInterconnectSettingId& interconnect_setting_id) const; - public: /* Public Mutators */ - BitstreamPbTypeSettingId add_bitstream_pb_type_setting(const std::string& pb_type_name, - const std::vector& parent_pb_type_names, - const std::vector& parent_mode_names, - const std::string& bitstream_source, - const std::string& bitstream_content); - void set_mode_select_bitstream(const BitstreamPbTypeSettingId& pb_type_setting_id, - const bool& is_mode_select_bitstream); - void set_bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id, - const size_t& offset); + public: /* Types */ + typedef vtr::vector::const_iterator + bitstream_pb_type_setting_iterator; + typedef vtr::vector::const_iterator + bitstream_interconnect_setting_iterator; + /* Create range */ + typedef vtr::Range + bitstream_pb_type_setting_range; + typedef vtr::Range + bitstream_interconnect_setting_range; - BitstreamInterconnectSettingId add_bitstream_interconnect_setting(const std::string& interconnect_name, - const std::vector& parent_pb_type_names, - const std::vector& parent_mode_names, - const std::string& default_path); - public: /* Public Validators */ - bool valid_bitstream_pb_type_setting_id(const BitstreamPbTypeSettingId& pb_type_setting_id) const; - bool valid_bitstream_interconnect_setting_id(const BitstreamInterconnectSettingId& interconnect_setting_id) const; - private: /* Internal data */ - /* Pb type -related settings - * - Paths to a pb_type in the pb_graph - * - Bitstream source, data_type, offsets etc. - */ - vtr::vector pb_type_setting_ids_; - vtr::vector pb_type_names_; - vtr::vector> parent_pb_type_names_; - vtr::vector> parent_mode_names_; - vtr::vector pb_type_bitstream_sources_; - vtr::vector pb_type_bitstream_contents_; - /* Indicate if the bitstream is applied to mode selection bits of a pb_type */ - vtr::vector is_mode_select_bitstreams_; - /* The offset that the bitstream is applied to the original bitstream of a pb_type */ - vtr::vector bitstream_offsets_; + public: /* Constructors */ + BitstreamSetting(); - /* Interconnect-related settings: - * - Name of interconnect under a given pb_type - * - The default path to be considered for a given interconnect during bitstream generation - */ - vtr::vector interconnect_setting_ids_; - vtr::vector interconnect_names_; - vtr::vector> interconnect_parent_pb_type_names_; - vtr::vector> interconnect_parent_mode_names_; - vtr::vector interconnect_default_paths_; + public: /* Accessors: aggregates */ + bitstream_pb_type_setting_range pb_type_settings() const; + bitstream_interconnect_setting_range interconnect_settings() const; + + public: /* Public Accessors */ + std::string pb_type_name( + const BitstreamPbTypeSettingId& pb_type_setting_id) const; + std::vector parent_pb_type_names( + const BitstreamPbTypeSettingId& pb_type_setting_id) const; + std::vector parent_mode_names( + const BitstreamPbTypeSettingId& pb_type_setting_id) const; + std::string pb_type_bitstream_source( + const BitstreamPbTypeSettingId& pb_type_setting_id) const; + std::string pb_type_bitstream_content( + const BitstreamPbTypeSettingId& pb_type_setting_id) const; + bool is_mode_select_bitstream( + const BitstreamPbTypeSettingId& pb_type_setting_id) const; + size_t bitstream_offset( + const BitstreamPbTypeSettingId& pb_type_setting_id) const; + std::string interconnect_name( + const BitstreamInterconnectSettingId& interconnect_setting_id) const; + std::vector parent_pb_type_names( + const BitstreamInterconnectSettingId& interconnect_setting_id) const; + std::vector parent_mode_names( + const BitstreamInterconnectSettingId& interconnect_setting_id) const; + std::string default_path( + const BitstreamInterconnectSettingId& interconnect_setting_id) const; + + public: /* Public Mutators */ + BitstreamPbTypeSettingId add_bitstream_pb_type_setting( + const std::string& pb_type_name, + const std::vector& parent_pb_type_names, + const std::vector& parent_mode_names, + const std::string& bitstream_source, const std::string& bitstream_content); + void set_mode_select_bitstream( + const BitstreamPbTypeSettingId& pb_type_setting_id, + const bool& is_mode_select_bitstream); + void set_bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id, + const size_t& offset); + + BitstreamInterconnectSettingId add_bitstream_interconnect_setting( + const std::string& interconnect_name, + const std::vector& parent_pb_type_names, + const std::vector& parent_mode_names, + const std::string& default_path); + + public: /* Public Validators */ + bool valid_bitstream_pb_type_setting_id( + const BitstreamPbTypeSettingId& pb_type_setting_id) const; + bool valid_bitstream_interconnect_setting_id( + const BitstreamInterconnectSettingId& interconnect_setting_id) const; + + private: /* Internal data */ + /* Pb type -related settings + * - Paths to a pb_type in the pb_graph + * - Bitstream source, data_type, offsets etc. + */ + vtr::vector + pb_type_setting_ids_; + vtr::vector pb_type_names_; + vtr::vector> + parent_pb_type_names_; + vtr::vector> + parent_mode_names_; + vtr::vector pb_type_bitstream_sources_; + vtr::vector + pb_type_bitstream_contents_; + /* Indicate if the bitstream is applied to mode selection bits of a pb_type */ + vtr::vector is_mode_select_bitstreams_; + /* The offset that the bitstream is applied to the original bitstream of a + * pb_type */ + vtr::vector bitstream_offsets_; + + /* Interconnect-related settings: + * - Name of interconnect under a given pb_type + * - The default path to be considered for a given interconnect during + * bitstream generation + */ + vtr::vector + interconnect_setting_ids_; + vtr::vector interconnect_names_; + vtr::vector> + interconnect_parent_pb_type_names_; + vtr::vector> + interconnect_parent_mode_names_; + vtr::vector + interconnect_default_paths_; }; -} /* namespace openfpga ends */ +} // namespace openfpga #endif diff --git a/libs/libarchopenfpga/src/bitstream_setting_fwd.h b/libs/libarchopenfpga/src/bitstream_setting_fwd.h index d5bb618e1..bc5c2ab88 100644 --- a/libs/libarchopenfpga/src/bitstream_setting_fwd.h +++ b/libs/libarchopenfpga/src/bitstream_setting_fwd.h @@ -1,11 +1,12 @@ /************************************************************************ * A header file for BitstreamSetting class, including critical data declaration * Please include this file only for using any BitstreamSetting data structure - * Refer to bitstream_setting.h for more details + * Refer to bitstream_setting.h for more details ***********************************************************************/ /************************************************************************ - * Create strong id for the pb_type annotation in Bitstream setting to avoid illegal type casting + * Create strong id for the pb_type annotation in Bitstream setting to avoid + *illegal type casting ***********************************************************************/ #ifndef BITSTREAM_SETTING_FWD_H #define BITSTREAM_SETTING_FWD_H @@ -15,8 +16,10 @@ struct bitstream_pb_type_setting_id_tag; struct bitstream_interconnect_setting_id_tag; -typedef vtr::StrongId BitstreamPbTypeSettingId; -typedef vtr::StrongId BitstreamInterconnectSettingId; +typedef vtr::StrongId + BitstreamPbTypeSettingId; +typedef vtr::StrongId + BitstreamInterconnectSettingId; /* Short declaration of class */ class BitstreamSetting; diff --git a/libs/libarchopenfpga/src/check_circuit_library.cpp b/libs/libarchopenfpga/src/check_circuit_library.cpp index 0964cc10a..62a71a3a1 100644 --- a/libs/libarchopenfpga/src/check_circuit_library.cpp +++ b/libs/libarchopenfpga/src/check_circuit_library.cpp @@ -1,24 +1,24 @@ /************************************************************************ - * Function to perform fundamental checking for the circuit library - * such as - * 1. if default circuit models are defined - * 2. if any circuit models shared the same name or prefix - * 3. if nay circuit model miss mandatory ports + * Function to perform fundamental checking for the circuit library + * such as + * 1. if default circuit models are defined + * 2. if any circuit models shared the same name or prefix + * 3. if nay circuit model miss mandatory ports ***********************************************************************/ /* Headers from vtrutil library */ +#include "check_circuit_library.h" + #include "vtr_assert.h" #include "vtr_log.h" #include "vtr_time.h" -#include "check_circuit_library.h" - /************************************************************************ - * Circuit models have unique names, return the number of errors + * Circuit models have unique names, return the number of errors * If not found, we give an error ***********************************************************************/ -static -size_t check_circuit_library_unique_names(const CircuitLibrary& circuit_lib) { +static size_t check_circuit_library_unique_names( + const CircuitLibrary& circuit_lib) { size_t num_err = 0; for (size_t i = 0; i < circuit_lib.num_models(); ++i) { @@ -35,8 +35,10 @@ size_t check_circuit_library_unique_names(const CircuitLibrary& circuit_lib) { if (0 != i_name.compare(j_name)) { continue; } - VTR_LOG_ERROR("Circuit model(index=%d) and (index=%d) share the same name, which is invalid!\n", - i , j, i_name.c_str()); + VTR_LOG_ERROR( + "Circuit model(index=%d) and (index=%d) share the same name, which is " + "invalid!\n", + i, j, i_name.c_str()); /* Incremental the counter for errors */ num_err++; } @@ -45,13 +47,12 @@ size_t check_circuit_library_unique_names(const CircuitLibrary& circuit_lib) { return num_err; } - /************************************************************************ - * Circuit models have unique names, return the number of errors + * Circuit models have unique names, return the number of errors * If not found, we give an error ***********************************************************************/ -static -size_t check_circuit_library_unique_prefix(const CircuitLibrary& circuit_lib) { +static size_t check_circuit_library_unique_prefix( + const CircuitLibrary& circuit_lib) { size_t num_err = 0; for (size_t i = 0; i < circuit_lib.num_models(); ++i) { @@ -68,10 +69,11 @@ size_t check_circuit_library_unique_prefix(const CircuitLibrary& circuit_lib) { if (0 != i_prefix.compare(j_prefix)) { continue; } - VTR_LOG_ERROR("Circuit model(name=%s) and (name=%s) share the same prefix, which is invalid!\n", - circuit_lib.model_name(CircuitModelId(i)).c_str(), - circuit_lib.model_name(CircuitModelId(j)).c_str(), - i_prefix.c_str()); + VTR_LOG_ERROR( + "Circuit model(name=%s) and (name=%s) share the same prefix, which is " + "invalid!\n", + circuit_lib.model_name(CircuitModelId(i)).c_str(), + circuit_lib.model_name(CircuitModelId(j)).c_str(), i_prefix.c_str()); /* Incremental the counter for errors */ num_err++; } @@ -84,15 +86,16 @@ size_t check_circuit_library_unique_prefix(const CircuitLibrary& circuit_lib) { * A generic function to check the port list of a circuit model in a given type * If not found, we give an error ***********************************************************************/ -static -size_t check_circuit_model_required(const CircuitLibrary& circuit_lib, - const enum e_circuit_model_type& circuit_model_type_to_check) { +static size_t check_circuit_model_required( + const CircuitLibrary& circuit_lib, + const enum e_circuit_model_type& circuit_model_type_to_check) { size_t num_err = 0; /* We must have an IOPAD*/ - if ( 0 == circuit_lib.models_by_type(circuit_model_type_to_check).size()) { - VTR_LOG_ERROR("At least one %s circuit model is required!\n", - CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_model_type_to_check)]); + if (0 == circuit_lib.models_by_type(circuit_model_type_to_check).size()) { + VTR_LOG_ERROR( + "At least one %s circuit model is required!\n", + CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_model_type_to_check)]); /* Incremental the counter for errors */ num_err++; } @@ -101,19 +104,20 @@ size_t check_circuit_model_required(const CircuitLibrary& circuit_lib, } /************************************************************************ - * A generic function to check the port list of a circuit model in a given type + * A generic function to check the port list of a circuit model in a given type * If not found, we give an error ***********************************************************************/ -size_t check_one_circuit_model_port_required(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const std::vector& port_types_to_check) { +size_t check_one_circuit_model_port_required( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const std::vector& port_types_to_check) { size_t num_err = 0; - for (const auto& port_type: port_types_to_check) { + for (const auto& port_type : port_types_to_check) { if (0 == circuit_lib.model_ports_by_type(circuit_model, port_type).size()) { VTR_LOG_ERROR("%s circuit model(name=%s) does not have %s port\n", - CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_lib.model_type(circuit_model))], - circuit_lib.model_name(circuit_model).c_str(), + CIRCUIT_MODEL_TYPE_STRING[size_t( + circuit_lib.model_type(circuit_model))], + circuit_lib.model_name(circuit_model).c_str(), CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(port_type)]); /* Incremental the counter for errors */ num_err++; @@ -125,21 +129,20 @@ size_t check_one_circuit_model_port_required(const CircuitLibrary& circuit_lib, /************************************************************************ * A generic function to check the port size of a given circuit model - * if the port size does not match, we give an error + * if the port size does not match, we give an error ***********************************************************************/ -size_t check_one_circuit_model_port_size_required(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const CircuitPortId& circuit_port, - const size_t& port_size_to_check) { - +size_t check_one_circuit_model_port_size_required( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const CircuitPortId& circuit_port, const size_t& port_size_to_check) { size_t num_err = 0; if (port_size_to_check != circuit_lib.port_size(circuit_port)) { - VTR_LOG_ERROR("Expect circuit model %s to have %d %s ports but only see %d!\n", - circuit_lib.model_name(circuit_model).c_str(), - port_size_to_check, - CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(circuit_port))], - circuit_lib.port_size(circuit_port)); + VTR_LOG_ERROR( + "Expect circuit model %s to have %d %s ports but only see %d!\n", + circuit_lib.model_name(circuit_model).c_str(), port_size_to_check, + CIRCUIT_MODEL_PORT_TYPE_STRING[size_t( + circuit_lib.port_type(circuit_port))], + circuit_lib.port_size(circuit_port)); /* Incremental the counter for errors */ num_err++; } @@ -149,68 +152,69 @@ size_t check_one_circuit_model_port_size_required(const CircuitLibrary& circuit_ /************************************************************************ * A generic function to check the port size of a given circuit model - * if the number of ports in the given type does not match, we give an error - * for each port, if the port size does not match, we give an error + * if the number of ports in the given type does not match, we give an error + * for each port, if the port size does not match, we give an error ***********************************************************************/ -size_t check_one_circuit_model_port_type_and_size_required(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const enum e_circuit_model_port_type& port_type_to_check, - const size_t& num_ports_to_check, - const size_t& port_size_to_check, - const bool& include_global_ports) { - +size_t check_one_circuit_model_port_type_and_size_required( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const enum e_circuit_model_port_type& port_type_to_check, + const size_t& num_ports_to_check, const size_t& port_size_to_check, + const bool& include_global_ports) { size_t num_err = 0; - std::vector ports = circuit_lib.model_ports_by_type(circuit_model, port_type_to_check, false == include_global_ports); + std::vector ports = circuit_lib.model_ports_by_type( + circuit_model, port_type_to_check, false == include_global_ports); if (num_ports_to_check != ports.size()) { - VTR_LOG_ERROR("Expect %d %s ports for a %s circuit model, but only have %d %s ports!\n", - num_ports_to_check, - CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(port_type_to_check)], - CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_lib.model_type(circuit_model))], - ports.size(), - CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(port_type_to_check)]); + VTR_LOG_ERROR( + "Expect %d %s ports for a %s circuit model, but only have %d %s ports!\n", + num_ports_to_check, + CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(port_type_to_check)], + CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_lib.model_type(circuit_model))], + ports.size(), CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(port_type_to_check)]); num_err++; - } - for (const auto& port : ports) { - num_err += check_one_circuit_model_port_size_required(circuit_lib, - circuit_model, - port, port_size_to_check); + } + for (const auto& port : ports) { + num_err += check_one_circuit_model_port_size_required( + circuit_lib, circuit_model, port, port_size_to_check); } return num_err; } /************************************************************************ - * A generic function to check the port list of circuit models in a given type + * A generic function to check the port list of circuit models in a given type * If not found, we give an error ***********************************************************************/ -static -size_t check_circuit_model_port_required(const CircuitLibrary& circuit_lib, - const enum e_circuit_model_type& circuit_model_type_to_check, - const std::vector& port_types_to_check) { +static size_t check_circuit_model_port_required( + const CircuitLibrary& circuit_lib, + const enum e_circuit_model_type& circuit_model_type_to_check, + const std::vector& port_types_to_check) { size_t num_err = 0; - for (const auto& id : circuit_lib.models_by_type(circuit_model_type_to_check)) { - num_err += check_one_circuit_model_port_required(circuit_lib, id, port_types_to_check); + for (const auto& id : + circuit_lib.models_by_type(circuit_model_type_to_check)) { + num_err += check_one_circuit_model_port_required(circuit_lib, id, + port_types_to_check); } return num_err; } /************************************************************************ - * A generic function to search each default circuit model by types + * A generic function to search each default circuit model by types * that have been defined by users. - * If a type of circuit model is defined, we expect there is a default model + * If a type of circuit model is defined, we expect there is a default model * to be specified ***********************************************************************/ -static -size_t check_default_circuit_model_by_types(const CircuitLibrary& circuit_lib) { +static size_t check_default_circuit_model_by_types( + const CircuitLibrary& circuit_lib) { size_t num_err = 0; for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_TYPES; ++itype) { - std::vector curr_models = circuit_lib.models_by_type(e_circuit_model_type(itype)); + std::vector curr_models = + circuit_lib.models_by_type(e_circuit_model_type(itype)); if (0 == curr_models.size()) { - continue; + continue; } /* Go through the models and try to find a default one */ size_t found_default_counter = 0; @@ -220,13 +224,16 @@ size_t check_default_circuit_model_by_types(const CircuitLibrary& circuit_lib) { } } if (0 == found_default_counter) { - VTR_LOG_ERROR("Miss a default circuit model for the type %s! Try to define it in your architecture file!\n", - CIRCUIT_MODEL_TYPE_STRING[itype]); + VTR_LOG_ERROR( + "Miss a default circuit model for the type %s! Try to define it in " + "your architecture file!\n", + CIRCUIT_MODEL_TYPE_STRING[itype]); num_err++; } if (1 < found_default_counter) { - VTR_LOG_ERROR("Found >1 default circuit models for the type %s! Expect only one!\n", - CIRCUIT_MODEL_TYPE_STRING[itype]); + VTR_LOG_ERROR( + "Found >1 default circuit models for the type %s! Expect only one!\n", + CIRCUIT_MODEL_TYPE_STRING[itype]); num_err++; } } @@ -238,14 +245,17 @@ size_t check_default_circuit_model_by_types(const CircuitLibrary& circuit_lib) { * A generic function to find the default circuit model with a given type * If not found, we give an error ***********************************************************************/ -static -size_t check_required_default_circuit_model(const CircuitLibrary& circuit_lib, - const enum e_circuit_model_type& circuit_model_type) { +static size_t check_required_default_circuit_model( + const CircuitLibrary& circuit_lib, + const enum e_circuit_model_type& circuit_model_type) { size_t num_err = 0; - if (CircuitModelId::INVALID() == circuit_lib.default_model(circuit_model_type)) { - VTR_LOG_ERROR("Miss a default circuit model for the type %s! Try to define it in your architecture file!\n", - CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_model_type)]); + if (CircuitModelId::INVALID() == + circuit_lib.default_model(circuit_model_type)) { + VTR_LOG_ERROR( + "Miss a default circuit model for the type %s! Try to define it in your " + "architecture file!\n", + CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_model_type)]); num_err++; } @@ -262,19 +272,15 @@ size_t check_ff_circuit_model_ports(const CircuitLibrary& circuit_lib, /* Check the type of circuit model */ VTR_ASSERT(CIRCUIT_MODEL_FF == circuit_lib.model_type(circuit_model)); /* Check if we have D, Set and Reset */ - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_INPUT, - 3, 1, false); + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_INPUT, 3, 1, false); /* Check if we have a clock */ - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_CLOCK, - 1, 1, false); - + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_CLOCK, 1, 1, false); /* Check if we have output */ - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_OUTPUT, - 1, 1, false); + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, 1, 1, false); return num_err; } @@ -290,38 +296,52 @@ size_t check_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib, VTR_ASSERT(CIRCUIT_MODEL_CCFF == circuit_lib.model_type(circuit_model)); /* Check if we have D, Set and Reset */ - /* We can have either 1 input which is D or 2 inputs which are D and scan input */ - size_t num_input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true).size(); + /* We can have either 1 input which is D or 2 inputs which are D and scan + * input */ + size_t num_input_ports = + circuit_lib + .model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true) + .size(); if ((1 != num_input_ports) && (2 != num_input_ports)) { - VTR_LOG_ERROR("Configuration flip-flop '%s' must have either 1 or 2 %s ports!\n\tAmong which:\n\t\tthe first input is a regular input (e.g., D)\n\t\tand the other could be scan-chain input (e.g., SI)\n", - circuit_lib.model_name(circuit_model).c_str(), - CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(CIRCUIT_MODEL_PORT_INPUT)]); + VTR_LOG_ERROR( + "Configuration flip-flop '%s' must have either 1 or 2 %s ports!\n\tAmong " + "which:\n\t\tthe first input is a regular input (e.g., D)\n\t\tand the " + "other could be scan-chain input (e.g., SI)\n", + circuit_lib.model_name(circuit_model).c_str(), + CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(CIRCUIT_MODEL_PORT_INPUT)]); num_err++; } - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_INPUT, - num_input_ports, 1, false); + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_INPUT, num_input_ports, 1, + false); /* Check if we have a clock */ - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_CLOCK, - 1, 1, true); - + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_CLOCK, 1, 1, true); /* Check if we have 1 or 2 or 3 outputs */ - size_t num_output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true).size(); - if ((1 != num_output_ports) - && (2 != num_output_ports) - && (3 != num_output_ports)) { - VTR_LOG_ERROR("Configuration flip-flop '%s' must have either 1 or 2 or 3 %s ports!\n\tAmong which:\n\t\tthe first port is the manadatory regular data output (e.g., Q) and \n\t\tthe second port could be the inverted data output which can optionally be enabled by configure-enable signal (e.g., QN or cgf_en_QN) and \n\t\tthe third port could be the data output which can optionally be enabled by configure-enable signal (e.g., cgf_en_Q)\n", - circuit_lib.model_name(circuit_model).c_str(), - CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(CIRCUIT_MODEL_PORT_OUTPUT)]); + size_t num_output_ports = + circuit_lib + .model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true) + .size(); + if ((1 != num_output_ports) && (2 != num_output_ports) && + (3 != num_output_ports)) { + VTR_LOG_ERROR( + "Configuration flip-flop '%s' must have either 1 or 2 or 3 %s " + "ports!\n\tAmong which:\n\t\tthe first port is the manadatory regular " + "data output (e.g., Q) and \n\t\tthe second port could be the inverted " + "data output which can optionally be enabled by configure-enable signal " + "(e.g., QN or cgf_en_QN) and \n\t\tthe third port could be the data " + "output which can optionally be enabled by configure-enable signal " + "(e.g., cgf_en_Q)\n", + circuit_lib.model_name(circuit_model).c_str(), + CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(CIRCUIT_MODEL_PORT_OUTPUT)]); num_err++; } - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_OUTPUT, - num_output_ports, 1, false); + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, num_output_ports, 1, + false); return num_err; } @@ -329,8 +349,8 @@ size_t check_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib, /************************************************************************ * A function to check the port map of CCFF circuit model used to control BLs * - Require 1 clock port - * - Require 1 input port as data input (to be driven by other CCFF in a chain) - * - Require 1 output port as data output (to drive other CCFF in a chain) + * - Require 1 input port as data input (to be driven by other CCFF in a chain) + * - Require 1 output port as data output (to drive other CCFF in a chain) * - Require 1 BL port as data output / inout (to drive/driven by BLs) ***********************************************************************/ size_t check_bl_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib, @@ -341,33 +361,35 @@ size_t check_bl_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib, VTR_ASSERT(CIRCUIT_MODEL_CCFF == circuit_lib.model_type(circuit_model)); /* Check if we have D, Set and Reset */ - /* We can have either 1 input which is D or 2 inputs which are D and scan input */ - size_t num_input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true).size(); + /* We can have either 1 input which is D or 2 inputs which are D and scan + * input */ + size_t num_input_ports = + circuit_lib + .model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true) + .size(); if (1 != num_input_ports) { - VTR_LOG_ERROR("Configuration flip-flop for BL shift register '%s' must have 1 %s port!\n", - circuit_lib.model_name(circuit_model).c_str(), - CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(CIRCUIT_MODEL_PORT_INPUT)]); + VTR_LOG_ERROR( + "Configuration flip-flop for BL shift register '%s' must have 1 %s " + "port!\n", + circuit_lib.model_name(circuit_model).c_str(), + CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(CIRCUIT_MODEL_PORT_INPUT)]); num_err++; } - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_INPUT, - num_input_ports, 1, false); + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_INPUT, num_input_ports, 1, + false); /* Check if we have a clock */ - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_CLOCK, - 1, 1, true); - + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_CLOCK, 1, 1, true); /* Check if we have 1 output*/ - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_OUTPUT, - 1, 1, false); + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, 1, 1, false); /* Check if we have 1 bl port */ - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_BL, - 1, 1, false); + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_BL, 1, 1, false); return num_err; } @@ -375,8 +397,8 @@ size_t check_bl_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib, /************************************************************************ * A function to check the port map of CCFF circuit model used to control WLs * - Require 1 clock port - * - Require 1 input port as data input (to be driven by other CCFF in a chain) - * - Require 1 output port as data output (to drive other CCFF in a chain) + * - Require 1 input port as data input (to be driven by other CCFF in a chain) + * - Require 1 output port as data output (to drive other CCFF in a chain) * - Require 1 WL port as data output (to drive WLs) * - Optionally require 1 WLR port as data output (to drive WLRs) ***********************************************************************/ @@ -388,40 +410,43 @@ size_t check_wl_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib, VTR_ASSERT(CIRCUIT_MODEL_CCFF == circuit_lib.model_type(circuit_model)); /* Check if we have D, Set and Reset */ - /* We can have either 1 input which is D or 2 inputs which are D and scan input */ - size_t num_input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true).size(); + /* We can have either 1 input which is D or 2 inputs which are D and scan + * input */ + size_t num_input_ports = + circuit_lib + .model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true) + .size(); if (1 != num_input_ports) { - VTR_LOG_ERROR("Configuration flip-flop for WL shift register '%s' must have 1 %s port!\n", - circuit_lib.model_name(circuit_model).c_str(), - CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(CIRCUIT_MODEL_PORT_INPUT)]); + VTR_LOG_ERROR( + "Configuration flip-flop for WL shift register '%s' must have 1 %s " + "port!\n", + circuit_lib.model_name(circuit_model).c_str(), + CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(CIRCUIT_MODEL_PORT_INPUT)]); num_err++; } - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_INPUT, - num_input_ports, 1, false); + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_INPUT, num_input_ports, 1, + false); /* Check if we have two clock: 1 for write-enable, 1 for shift register */ - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_CLOCK, - 2, 1, true); - + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_CLOCK, 2, 1, true); /* Check if we have 1 output*/ - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_OUTPUT, - 1, 1, false); + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, 1, 1, false); /* Check if we have 1 wl port */ - if (0 < circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_WLR, true).size()) { - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_WLR, - 1, 1, false); + if (0 < circuit_lib + .model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_WLR, true) + .size()) { + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_WLR, 1, 1, false); } return num_err; } - /************************************************************************ * A function to check the port map of SRAM circuit model ***********************************************************************/ @@ -434,66 +459,67 @@ size_t check_sram_circuit_model_ports(const CircuitLibrary& circuit_lib, VTR_ASSERT(CIRCUIT_MODEL_SRAM == circuit_lib.model_type(circuit_model)); /* Check if we has 1 output with size 2 */ - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_OUTPUT, - 2, 1, false); + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, 2, 1, false); /* basic check finished here */ if (false == check_blwl) { return num_err; } /* If bl and wl are required, check their existence */ - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_BL, - 1, 1, false); + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_BL, 1, 1, false); - num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, - CIRCUIT_MODEL_PORT_WL, - 1, 1, false); + num_err += check_one_circuit_model_port_type_and_size_required( + circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_WL, 1, 1, false); return num_err; } /************************************************************************ - * Check all the ports make sure, they satisfy the restriction + * Check all the ports make sure, they satisfy the restriction ***********************************************************************/ -static -size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) { +static size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) { size_t num_err = 0; - + /* Check global ports: make sure all the global ports are input ports */ for (const auto& port : circuit_lib.ports()) { - if ( (circuit_lib.port_is_global(port)) - && (!circuit_lib.is_input_port(port)) - && (!circuit_lib.is_output_port(port)) ) { - VTR_LOG_ERROR("Circuit port (type=%s) of model (name=%s) is defined as global but not an input/output port!\n", - CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(port))], - circuit_lib.model_name(port).c_str()); + if ((circuit_lib.port_is_global(port)) && + (!circuit_lib.is_input_port(port)) && + (!circuit_lib.is_output_port(port))) { + VTR_LOG_ERROR( + "Circuit port (type=%s) of model (name=%s) is defined as global but " + "not an input/output port!\n", + CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(port))], + circuit_lib.model_name(port).c_str()); num_err++; } } /* Check global output ports: make sure they are all I/Os */ for (const auto& port : circuit_lib.ports()) { - if ( (circuit_lib.port_is_global(port)) - && (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port)) - && (false == circuit_lib.port_is_io(port)) ) { - VTR_LOG_ERROR("Circuit port (type=%s) of model (name=%s) is defined as global output port but not an I/O!\n", - CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(port))], - circuit_lib.model_name(port).c_str()); + if ((circuit_lib.port_is_global(port)) && + (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port)) && + (false == circuit_lib.port_is_io(port))) { + VTR_LOG_ERROR( + "Circuit port (type=%s) of model (name=%s) is defined as global output " + "port but not an I/O!\n", + CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(port))], + circuit_lib.model_name(port).c_str()); num_err++; } } /* Check set/reset/config_enable ports: make sure they are all global ports */ for (const auto& port : circuit_lib.ports()) { - if ( ( (circuit_lib.port_is_set(port)) - || (circuit_lib.port_is_reset(port)) - || (circuit_lib.port_is_config_enable(port)) ) - && (!circuit_lib.port_is_global(port)) ) { - VTR_LOG_ERROR("Circuit port (type=%s) of model (name=%s) is defined as a set/reset/config_enable port but it is not global!\n", - CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(port))], - circuit_lib.model_name(port).c_str()); + if (((circuit_lib.port_is_set(port)) || (circuit_lib.port_is_reset(port)) || + (circuit_lib.port_is_config_enable(port))) && + (!circuit_lib.port_is_global(port))) { + VTR_LOG_ERROR( + "Circuit port (type=%s) of model (name=%s) is defined as a " + "set/reset/config_enable port but it is not global!\n", + CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(port))], + circuit_lib.model_name(port).c_str()); num_err++; } } @@ -503,20 +529,23 @@ size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) { if (circuit_lib.port_tri_state_map(port).empty()) { continue; /* No tri-state map is found, go to the next */ } - if (circuit_lib.port_tri_state_map(port).length() == circuit_lib.port_size(port)) { + if (circuit_lib.port_tri_state_map(port).length() == + circuit_lib.port_size(port)) { continue; /* Sizes match, go to the next */ } - /* We have a problem here, sizes do not match, leave a message and raise the error flag */ - VTR_LOG_ERROR("Tri-state map (=%s) of circuit port (type=%s) of model (name=%s) does not match the port size (=%lu)!\n", - circuit_lib.port_tri_state_map(port).c_str(), - CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(port))], - circuit_lib.model_name(port).c_str(), - circuit_lib.port_size(port)); + /* We have a problem here, sizes do not match, leave a message and raise the + * error flag */ + VTR_LOG_ERROR( + "Tri-state map (=%s) of circuit port (type=%s) of model (name=%s) does " + "not match the port size (=%lu)!\n", + circuit_lib.port_tri_state_map(port).c_str(), + CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(port))], + circuit_lib.model_name(port).c_str(), circuit_lib.port_size(port)); num_err++; } - /* Check all the global ports which sare the same name also share the same attributes: - * default_value, is_config, is_reset, is_set etc. + /* Check all the global ports which sare the same name also share the same + * attributes: default_value, is_config, is_reset, is_set etc. */ std::vector global_ports; @@ -532,55 +561,68 @@ size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) { for (size_t iport = 0; iport < global_ports.size() - 1; ++iport) { for (size_t jport = iport + 1; jport < global_ports.size(); ++jport) { /* Bypass those do not share the same name */ - if (0 != circuit_lib.port_prefix(global_ports[iport]).compare(circuit_lib.port_prefix(global_ports[jport]))) { + if (0 != circuit_lib.port_prefix(global_ports[iport]) + .compare(circuit_lib.port_prefix(global_ports[jport]))) { continue; } /* Check if a same port share the same attributes */ - CircuitModelId iport_parent_model = circuit_lib.port_parent_model(global_ports[iport]); - CircuitModelId jport_parent_model = circuit_lib.port_parent_model(global_ports[jport]); + CircuitModelId iport_parent_model = + circuit_lib.port_parent_model(global_ports[iport]); + CircuitModelId jport_parent_model = + circuit_lib.port_parent_model(global_ports[jport]); - if (circuit_lib.port_default_value(global_ports[iport]) != circuit_lib.port_default_value(global_ports[jport])) { - VTR_LOG_ERROR("Global ports %s from circuit model %s and %s share the same name but have different dfefault values(%lu and %lu)!\n", - circuit_lib.port_prefix(global_ports[iport]).c_str(), - circuit_lib.model_name(iport_parent_model).c_str(), - circuit_lib.model_name(jport_parent_model).c_str(), - circuit_lib.port_default_value(global_ports[iport]), - circuit_lib.port_default_value(global_ports[jport]) - ); + if (circuit_lib.port_default_value(global_ports[iport]) != + circuit_lib.port_default_value(global_ports[jport])) { + VTR_LOG_ERROR( + "Global ports %s from circuit model %s and %s share the same name " + "but have different dfefault values(%lu and %lu)!\n", + circuit_lib.port_prefix(global_ports[iport]).c_str(), + circuit_lib.model_name(iport_parent_model).c_str(), + circuit_lib.model_name(jport_parent_model).c_str(), + circuit_lib.port_default_value(global_ports[iport]), + circuit_lib.port_default_value(global_ports[jport])); num_err++; } - if (circuit_lib.port_is_reset(global_ports[iport]) != circuit_lib.port_is_reset(global_ports[jport])) { - VTR_LOG_ERROR("Global ports %s from circuit model %s and %s share the same name but have different is_reset attributes!\n", - circuit_lib.port_prefix(global_ports[iport]).c_str(), - circuit_lib.model_name(iport_parent_model).c_str(), - circuit_lib.model_name(jport_parent_model).c_str() - ); + if (circuit_lib.port_is_reset(global_ports[iport]) != + circuit_lib.port_is_reset(global_ports[jport])) { + VTR_LOG_ERROR( + "Global ports %s from circuit model %s and %s share the same name " + "but have different is_reset attributes!\n", + circuit_lib.port_prefix(global_ports[iport]).c_str(), + circuit_lib.model_name(iport_parent_model).c_str(), + circuit_lib.model_name(jport_parent_model).c_str()); num_err++; } - if (circuit_lib.port_is_set(global_ports[iport]) != circuit_lib.port_is_set(global_ports[jport])) { - VTR_LOG_ERROR("Global ports %s from circuit model %s and %s share the same name but have different is_set attributes!\n", - circuit_lib.port_prefix(global_ports[iport]).c_str(), - circuit_lib.model_name(iport_parent_model).c_str(), - circuit_lib.model_name(jport_parent_model).c_str() - ); + if (circuit_lib.port_is_set(global_ports[iport]) != + circuit_lib.port_is_set(global_ports[jport])) { + VTR_LOG_ERROR( + "Global ports %s from circuit model %s and %s share the same name " + "but have different is_set attributes!\n", + circuit_lib.port_prefix(global_ports[iport]).c_str(), + circuit_lib.model_name(iport_parent_model).c_str(), + circuit_lib.model_name(jport_parent_model).c_str()); num_err++; } - if (circuit_lib.port_is_config_enable(global_ports[iport]) != circuit_lib.port_is_config_enable(global_ports[jport])) { - VTR_LOG_ERROR("Global ports %s from circuit model %s and %s share the same name but have different is_config_enable attributes!\n", - circuit_lib.port_prefix(global_ports[iport]).c_str(), - circuit_lib.model_name(iport_parent_model).c_str(), - circuit_lib.model_name(jport_parent_model).c_str() - ); + if (circuit_lib.port_is_config_enable(global_ports[iport]) != + circuit_lib.port_is_config_enable(global_ports[jport])) { + VTR_LOG_ERROR( + "Global ports %s from circuit model %s and %s share the same name " + "but have different is_config_enable attributes!\n", + circuit_lib.port_prefix(global_ports[iport]).c_str(), + circuit_lib.model_name(iport_parent_model).c_str(), + circuit_lib.model_name(jport_parent_model).c_str()); num_err++; } - if (circuit_lib.port_is_prog(global_ports[iport]) != circuit_lib.port_is_prog(global_ports[jport])) { - VTR_LOG_ERROR("Global ports %s from circuit model %s and %s share the same name but have different is_prog attributes!\n", - circuit_lib.port_prefix(global_ports[iport]).c_str(), - circuit_lib.model_name(iport_parent_model).c_str(), - circuit_lib.model_name(jport_parent_model).c_str() - ); + if (circuit_lib.port_is_prog(global_ports[iport]) != + circuit_lib.port_is_prog(global_ports[jport])) { + VTR_LOG_ERROR( + "Global ports %s from circuit model %s and %s share the same name " + "but have different is_prog attributes!\n", + circuit_lib.port_prefix(global_ports[iport]).c_str(), + circuit_lib.model_name(iport_parent_model).c_str(), + circuit_lib.model_name(jport_parent_model).c_str()); num_err++; } } @@ -590,26 +632,29 @@ size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) { } /************************************************************************ - * Check the port requirements for a power-gated circuit model + * Check the port requirements for a power-gated circuit model * - It must have at least 2 global ports and which are config enable signals - * - It must have an Enable port which control power gating - * - It must have an EnableB port which control power gating + * - It must have an Enable port which control power gating + * - It must have an EnableB port which control power gating ***********************************************************************/ -static -int check_power_gated_circuit_model(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model) { +static int check_power_gated_circuit_model( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model) { int num_err = 0; - std::vector global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector global_ports = + circuit_lib.model_global_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); - /* If the circuit model is power-gated, we need to find at least one global config_enable signals */ + /* If the circuit model is power-gated, we need to find at least one global + * config_enable signals */ VTR_ASSERT(true == circuit_lib.is_power_gated(circuit_model)); /* Check all the ports we have are good for a power-gated circuit model */ /* We need at least one global port */ - if (2 > global_ports.size()) { + if (2 > global_ports.size()) { VTR_LOGF_ERROR(__FILE__, __LINE__, - "Expect at least two global ports (a pair of EN/Enb) for circuit model '%s' which is power-gated!\n", - circuit_lib.model_name(circuit_model).c_str()); + "Expect at least two global ports (a pair of EN/Enb) for " + "circuit model '%s' which is power-gated!\n", + circuit_lib.model_name(circuit_model).c_str()); num_err++; } /* All the global ports should be config_enable */ @@ -622,8 +667,9 @@ int check_power_gated_circuit_model(const CircuitLibrary& circuit_lib, if (2 != num_config_enable_ports) { VTR_LOGF_ERROR(__FILE__, __LINE__, - "Circuit model '%s' is power-gated. Two config-enable global ports are required!\n", - circuit_lib.model_name(circuit_model).c_str()); + "Circuit model '%s' is power-gated. Two config-enable " + "global ports are required!\n", + circuit_lib.model_name(circuit_model).c_str()); num_err++; } /* Report errors if there are any */ @@ -649,23 +695,24 @@ int check_power_gated_circuit_model(const CircuitLibrary& circuit_lib, /* We must have valid EN/ENb ports */ if (false == circuit_lib.valid_circuit_port_id(en_port)) { VTR_LOGF_ERROR(__FILE__, __LINE__, - "Fail to find an enable port for the circuit model '%s' is power-gated!\n", - circuit_lib.model_name(circuit_model).c_str()); + "Fail to find an enable port for the circuit model '%s' is " + "power-gated!\n", + circuit_lib.model_name(circuit_model).c_str()); } if (false == circuit_lib.valid_circuit_port_id(enb_port)) { VTR_LOGF_ERROR(__FILE__, __LINE__, - "Fail to find an inverted enable port for the circuit model '%s' is power-gated!\n", - circuit_lib.model_name(circuit_model).c_str()); + "Fail to find an inverted enable port for the circuit model " + "'%s' is power-gated!\n", + circuit_lib.model_name(circuit_model).c_str()); } return num_err; } /************************************************************************ - * Check the port requirements for each power-gated circuit model + * Check the port requirements for each power-gated circuit model ***********************************************************************/ -static -int check_power_gated_circuit_models(const CircuitLibrary& circuit_lib) { +static int check_power_gated_circuit_models(const CircuitLibrary& circuit_lib) { int num_err = 0; for (const CircuitModelId& circuit_model : circuit_lib.models()) { @@ -678,19 +725,19 @@ int check_power_gated_circuit_models(const CircuitLibrary& circuit_lib) { } /************************************************************************ - * Check io has been defined and has input and output ports + * Check io has been defined and has input and output ports * - We must have global I/O port, either its type is inout, input or output - * - For each IOPAD, we must have at least an input an output + * - For each IOPAD, we must have at least an input an output ***********************************************************************/ -static -size_t check_io_circuit_model(const CircuitLibrary& circuit_lib) { +static size_t check_io_circuit_model(const CircuitLibrary& circuit_lib) { size_t num_err = 0; - /* Each I/O cell must have + /* Each I/O cell must have * - One of the following ports - * - At least 1 ASIC-to-FPGA (A2F) port that is defined as global data I/O + * - At least 1 ASIC-to-FPGA (A2F) port that is defined as global data I/O * - At least 1 FPGA-to-ASIC (F2A) port that is defined as global data I/O! - * - At least 1 regular port that is non-global which is connected to global routing architecture + * - At least 1 regular port that is non-global which is connected to global + * routing architecture */ for (const auto& io_model : circuit_lib.models_by_type(CIRCUIT_MODEL_IOPAD)) { bool has_data_io = false; @@ -699,52 +746,53 @@ size_t check_io_circuit_model(const CircuitLibrary& circuit_lib) { bool has_internal_connection = false; for (const auto& port : circuit_lib.model_ports(io_model)) { - if ( (true == circuit_lib.port_is_io(port)) - && (true == circuit_lib.port_is_data_io(port)) - && (CIRCUIT_MODEL_PORT_INOUT == circuit_lib.port_type(port)) - && (true == circuit_lib.port_is_global(port))) { + if ((true == circuit_lib.port_is_io(port)) && + (true == circuit_lib.port_is_data_io(port)) && + (CIRCUIT_MODEL_PORT_INOUT == circuit_lib.port_type(port)) && + (true == circuit_lib.port_is_global(port))) { has_data_io = true; continue; /* Go to next */ } - if ( (true == circuit_lib.port_is_io(port)) - && (true == circuit_lib.port_is_data_io(port)) - && (CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(port)) - && (true == circuit_lib.port_is_global(port))) { + if ((true == circuit_lib.port_is_io(port)) && + (true == circuit_lib.port_is_data_io(port)) && + (CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(port)) && + (true == circuit_lib.port_is_global(port))) { has_data_input_only_io = true; continue; /* Go to next */ } - if ( (true == circuit_lib.port_is_io(port)) - && (true == circuit_lib.port_is_data_io(port)) - && (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port)) - && (true == circuit_lib.port_is_global(port))) { + if ((true == circuit_lib.port_is_io(port)) && + (true == circuit_lib.port_is_data_io(port)) && + (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port)) && + (true == circuit_lib.port_is_global(port))) { has_data_output_only_io = true; continue; /* Go to next */ } - if ( (false == circuit_lib.port_is_io(port) - && (false == circuit_lib.port_is_global(port))) - && (CIRCUIT_MODEL_PORT_SRAM != circuit_lib.port_type(port))) { + if ((false == circuit_lib.port_is_io(port) && + (false == circuit_lib.port_is_global(port))) && + (CIRCUIT_MODEL_PORT_SRAM != circuit_lib.port_type(port))) { has_internal_connection = true; continue; /* Go to next */ } } - + /* Error out when * - there is no data io, data input-only io and data output-only io */ - if ( (false == has_data_io) - && (false == has_data_input_only_io) - && (false == has_data_output_only_io)) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "I/O circuit model '%s' does not have any data I/O port defined!\n", - circuit_lib.model_name(io_model).c_str()); + if ((false == has_data_io) && (false == has_data_input_only_io) && + (false == has_data_output_only_io)) { + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "I/O circuit model '%s' does not have any data I/O port defined!\n", + circuit_lib.model_name(io_model).c_str()); num_err++; } if (false == has_internal_connection) { VTR_LOGF_ERROR(__FILE__, __LINE__, - "I/O circuit model '%s' does not have any port connected to FPGA core!\n", - circuit_lib.model_name(io_model).c_str()); + "I/O circuit model '%s' does not have any port connected " + "to FPGA core!\n", + circuit_lib.model_name(io_model).c_str()); num_err++; } } @@ -754,17 +802,18 @@ size_t check_io_circuit_model(const CircuitLibrary& circuit_lib) { /************************************************************************ * Check points to make sure we have a valid circuit library - * Detailed checkpoints: - * 1. Circuit models have unique names + * Detailed checkpoints: + * 1. Circuit models have unique names * 2. Circuit models have unique prefix * 3. Check IOPADs have input and output ports * 4. Check MUXes has been defined and has input and output ports - * 5. We must have at least one SRAM or CCFF + * 5. We must have at least one SRAM or CCFF * 6. SRAM must have at least an input and an output ports * 7. CCFF must have at least a clock, an input and an output ports * 8. FF must have at least a clock, an input and an output ports * 9. LUT must have at least an input, an output and a SRAM ports - * 10. We must have default circuit models for these types: MUX, channel wires and wires + * 10. We must have default circuit models for these types: MUX, channel wires + *and wires * * Note: * - NO modification on the circuit library is allowed! @@ -775,29 +824,32 @@ bool check_circuit_library(const CircuitLibrary& circuit_lib) { vtr::ScopedStartFinishTimer timer("Check circuit library"); - /* 1. Circuit models have unique names - * For each circuit model, we always make sure it does not share any name with any circuit model locating after it + /* 1. Circuit models have unique names + * For each circuit model, we always make sure it does not share any name with + * any circuit model locating after it */ num_err += check_circuit_library_unique_names(circuit_lib); /* 2. Circuit models have unique prefix - * For each circuit model, we always make sure it does not share any prefix with any circuit model locating after it + * For each circuit model, we always make sure it does not share any prefix + * with any circuit model locating after it */ num_err += check_circuit_library_unique_prefix(circuit_lib); /* Check global ports */ num_err += check_circuit_library_ports(circuit_lib); - /* 3. Check io has been defined and has input and output ports + /* 3. Check io has been defined and has input and output ports * [a] We must have global I/O port, either its type is inout, input or output - * [b] For each IOPAD, we must have at least an input an output + * [b] For each IOPAD, we must have at least an input an output */ num_err += check_circuit_model_required(circuit_lib, CIRCUIT_MODEL_IOPAD); num_err += check_io_circuit_model(circuit_lib); /* 4. Check mux has been defined and has input and output ports - * [a] We must have a MUX! - * [b] For each MUX, we must have at least an input, an output, and an SRAM port + * [a] We must have a MUX! + * [b] For each MUX, we must have at least an input, an output, and an SRAM + * port */ num_err += check_circuit_model_required(circuit_lib, CIRCUIT_MODEL_MUX); @@ -806,13 +858,14 @@ bool check_circuit_library(const CircuitLibrary& circuit_lib) { mux_port_types_required.push_back(CIRCUIT_MODEL_PORT_OUTPUT); mux_port_types_required.push_back(CIRCUIT_MODEL_PORT_SRAM); - num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_MODEL_MUX, mux_port_types_required); + num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_MODEL_MUX, + mux_port_types_required); /* 5. We must have at least one SRAM or CCFF */ - if ( ( 0 == circuit_lib.models_by_type(CIRCUIT_MODEL_SRAM).size()) - && ( 0 == circuit_lib.models_by_type(CIRCUIT_MODEL_CCFF).size()) ) { + if ((0 == circuit_lib.models_by_type(CIRCUIT_MODEL_SRAM).size()) && + (0 == circuit_lib.models_by_type(CIRCUIT_MODEL_CCFF).size())) { VTR_LOG_ERROR("At least one %s or %s circuit model is required!\n", - CIRCUIT_MODEL_TYPE_STRING[size_t(CIRCUIT_MODEL_SRAM)], + CIRCUIT_MODEL_TYPE_STRING[size_t(CIRCUIT_MODEL_SRAM)], CIRCUIT_MODEL_TYPE_STRING[size_t(CIRCUIT_MODEL_CCFF)]); /* Incremental the counter for errors */ num_err++; @@ -822,7 +875,8 @@ bool check_circuit_library(const CircuitLibrary& circuit_lib) { std::vector sram_port_types_required; sram_port_types_required.push_back(CIRCUIT_MODEL_PORT_OUTPUT); - num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_MODEL_SRAM, sram_port_types_required); + num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_MODEL_SRAM, + sram_port_types_required); /* 7. CCFF must have at least a clock, an input and an output ports*/ std::vector ccff_port_types_required; @@ -830,7 +884,8 @@ bool check_circuit_library(const CircuitLibrary& circuit_lib) { ccff_port_types_required.push_back(CIRCUIT_MODEL_PORT_INPUT); ccff_port_types_required.push_back(CIRCUIT_MODEL_PORT_OUTPUT); - num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_MODEL_CCFF, ccff_port_types_required); + num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_MODEL_CCFF, + ccff_port_types_required); /* 8. FF must have at least a clock, an input and an output ports*/ std::vector ff_port_types_required; @@ -838,7 +893,8 @@ bool check_circuit_library(const CircuitLibrary& circuit_lib) { ff_port_types_required.push_back(CIRCUIT_MODEL_PORT_INPUT); ff_port_types_required.push_back(CIRCUIT_MODEL_PORT_OUTPUT); - num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_MODEL_FF, ff_port_types_required); + num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_MODEL_FF, + ff_port_types_required); /* 9. LUT must have at least an input, an output and a SRAM ports*/ std::vector lut_port_types_required; @@ -846,15 +902,20 @@ bool check_circuit_library(const CircuitLibrary& circuit_lib) { lut_port_types_required.push_back(CIRCUIT_MODEL_PORT_INPUT); lut_port_types_required.push_back(CIRCUIT_MODEL_PORT_OUTPUT); - num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_MODEL_LUT, lut_port_types_required); + num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_MODEL_LUT, + lut_port_types_required); - /* 10. For each type of circuit models that are define, we must have 1 default model - * We must have default circuit models for these types: MUX, channel wires and wires + /* 10. For each type of circuit models that are define, we must have 1 default + * model We must have default circuit models for these types: MUX, channel + * wires and wires */ num_err += check_default_circuit_model_by_types(circuit_lib); - num_err += check_required_default_circuit_model(circuit_lib, CIRCUIT_MODEL_MUX); - num_err += check_required_default_circuit_model(circuit_lib, CIRCUIT_MODEL_CHAN_WIRE); - num_err += check_required_default_circuit_model(circuit_lib, CIRCUIT_MODEL_WIRE); + num_err += + check_required_default_circuit_model(circuit_lib, CIRCUIT_MODEL_MUX); + num_err += + check_required_default_circuit_model(circuit_lib, CIRCUIT_MODEL_CHAN_WIRE); + num_err += + check_required_default_circuit_model(circuit_lib, CIRCUIT_MODEL_WIRE); /* 11. Check power-gated inverter/buffer models */ num_err += check_power_gated_circuit_models(circuit_lib); @@ -862,8 +923,7 @@ bool check_circuit_library(const CircuitLibrary& circuit_lib) { /* If we have any errors, exit */ if (0 < num_err) { - VTR_LOG("Finished checking circuit library with %d errors!\n", - num_err); + VTR_LOG("Finished checking circuit library with %d errors!\n", num_err); return false; } @@ -871,4 +931,3 @@ bool check_circuit_library(const CircuitLibrary& circuit_lib) { return true; } - diff --git a/libs/libarchopenfpga/src/check_circuit_library.h b/libs/libarchopenfpga/src/check_circuit_library.h index 3d196d7c9..7ac09e967 100644 --- a/libs/libarchopenfpga/src/check_circuit_library.h +++ b/libs/libarchopenfpga/src/check_circuit_library.h @@ -1,37 +1,36 @@ /* IMPORTANT: - * The following preprocessing flags are added to - * avoid compilation error when this headers are included in more than 1 times + * The following preprocessing flags are added to + * avoid compilation error when this headers are included in more than 1 times */ #ifndef CHECK_CIRCUIT_LIBRARY_H #define CHECK_CIRCUIT_LIBRARY_H /* - * Notes in include header files in a head file - * Only include the neccessary header files + * Notes in include header files in a head file + * Only include the neccessary header files * that is required by the data types in the function/class declarations! */ /* Header files should be included in a sequence */ /* Standard header files required go first */ #include -#include "circuit_types.h" + #include "circuit_library.h" +#include "circuit_types.h" /* Check points to make sure we have a valid circuit library */ -size_t check_one_circuit_model_port_required(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const std::vector& port_types_to_check); +size_t check_one_circuit_model_port_required( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const std::vector& port_types_to_check); -size_t check_one_circuit_model_port_size_required(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const CircuitPortId& circuit_port, - const size_t& port_size_to_check); +size_t check_one_circuit_model_port_size_required( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const CircuitPortId& circuit_port, const size_t& port_size_to_check); -size_t check_one_circuit_model_port_type_and_size_required(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const enum e_circuit_model_port_type& port_type_to_check, - const size_t& num_ports_to_check, - const size_t& port_size_to_check, - const bool& include_global_ports); +size_t check_one_circuit_model_port_type_and_size_required( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const enum e_circuit_model_port_type& port_type_to_check, + const size_t& num_ports_to_check, const size_t& port_size_to_check, + const bool& include_global_ports); size_t check_ff_circuit_model_ports(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model); diff --git a/libs/libarchopenfpga/src/circuit_library.cpp b/libs/libarchopenfpga/src/circuit_library.cpp index e6b1f248e..241f63c7a 100644 --- a/libs/libarchopenfpga/src/circuit_library.cpp +++ b/libs/libarchopenfpga/src/circuit_library.cpp @@ -1,11 +1,11 @@ -#include -#include +#include "circuit_library.h" -#include "vtr_assert.h" -#include "vtr_log.h" +#include +#include #include "openfpga_port_parser.h" -#include "circuit_library.h" +#include "vtr_assert.h" +#include "vtr_log.h" /************************************************************************ * Member functions for class CircuitLibrary @@ -14,9 +14,7 @@ /************************************************************************ * Constructors ***********************************************************************/ -CircuitLibrary::CircuitLibrary() { - return; -} +CircuitLibrary::CircuitLibrary() { return; } /************************************************************************ * Public Accessors : aggregates @@ -29,8 +27,10 @@ CircuitLibrary::circuit_port_range CircuitLibrary::ports() const { return vtr::make_range(port_ids_.begin(), port_ids_.end()); } -/* Find circuit models in the same type (defined by users) and return a list of ids */ -std::vector CircuitLibrary::models_by_type(const enum e_circuit_model_type& type) const { +/* Find circuit models in the same type (defined by users) and return a list of + * ids */ +std::vector CircuitLibrary::models_by_type( + const enum e_circuit_model_type& type) const { std::vector type_ids; for (auto id : models()) { /* Skip unmatched types */ @@ -47,110 +47,118 @@ std::vector CircuitLibrary::models_by_type(const enum e_circuit_ * Public Accessors : Basic data query on Circuit Models ***********************************************************************/ /* Get the number of circuit models */ -size_t CircuitLibrary::num_models() const { - return model_ids_.size(); -} +size_t CircuitLibrary::num_models() const { return model_ids_.size(); } /* Access the type of a circuit model */ -enum e_circuit_model_type CircuitLibrary::model_type(const CircuitModelId& model_id) const { +enum e_circuit_model_type CircuitLibrary::model_type( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return model_types_[model_id]; + return model_types_[model_id]; } /* Access the name of a circuit model */ std::string CircuitLibrary::model_name(const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return model_names_[model_id]; + return model_names_[model_id]; } /* Access the prefix of a circuit model */ std::string CircuitLibrary::model_prefix(const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return model_prefix_[model_id]; + return model_prefix_[model_id]; } /* Access the path + file of user-defined verilog netlist of a circuit model */ -std::string CircuitLibrary::model_verilog_netlist(const CircuitModelId& model_id) const { +std::string CircuitLibrary::model_verilog_netlist( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return model_verilog_netlists_[model_id]; + return model_verilog_netlists_[model_id]; } /* Access the path + file of user-defined spice netlist of a circuit model */ -std::string CircuitLibrary::model_spice_netlist(const CircuitModelId& model_id) const { +std::string CircuitLibrary::model_spice_netlist( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return model_spice_netlists_[model_id]; + return model_spice_netlists_[model_id]; } -/* Access the is_default flag (check if this is the default circuit model in the type) of a circuit model */ +/* Access the is_default flag (check if this is the default circuit model in the + * type) of a circuit model */ bool CircuitLibrary::model_is_default(const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return model_is_default_[model_id]; + return model_is_default_[model_id]; } /* Access the dump_structural_verilog flag of a circuit model */ -bool CircuitLibrary::dump_structural_verilog(const CircuitModelId& model_id) const { +bool CircuitLibrary::dump_structural_verilog( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return dump_structural_verilog_[model_id]; + return dump_structural_verilog_[model_id]; } /* Access the dump_explicit_port_map flag of a circuit model */ -bool CircuitLibrary::dump_explicit_port_map(const CircuitModelId& model_id) const { +bool CircuitLibrary::dump_explicit_port_map( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return dump_explicit_port_map_[model_id]; + return dump_explicit_port_map_[model_id]; } /* Access the design technology type of a circuit model */ -enum e_circuit_model_design_tech CircuitLibrary::design_tech_type(const CircuitModelId& model_id) const { +enum e_circuit_model_design_tech CircuitLibrary::design_tech_type( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return design_tech_types_[model_id]; + return design_tech_types_[model_id]; } /* Access the is_power_gated flag of a circuit model */ bool CircuitLibrary::is_power_gated(const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return is_power_gated_[model_id]; + return is_power_gated_[model_id]; } /* Access the device model name that is binded to a circuit model */ -std::string CircuitLibrary::device_model_name(const CircuitModelId& model_id) const { +std::string CircuitLibrary::device_model_name( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return device_model_names_[model_id]; + return device_model_names_[model_id]; } /* Return a flag showing if inputs are buffered for a circuit model */ bool CircuitLibrary::is_input_buffered(const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return buffer_existence_[model_id][INPUT]; + return buffer_existence_[model_id][INPUT]; } /* Return a flag showing if outputs are buffered for a circuit model */ bool CircuitLibrary::is_output_buffered(const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return buffer_existence_[model_id][OUTPUT]; + return buffer_existence_[model_id][OUTPUT]; } -/* Return a flag showing if intermediate stages of a LUT are buffered for a circuit model */ -bool CircuitLibrary::is_lut_intermediate_buffered(const CircuitModelId& model_id) const { +/* Return a flag showing if intermediate stages of a LUT are buffered for a + * circuit model */ +bool CircuitLibrary::is_lut_intermediate_buffered( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is LUT */ VTR_ASSERT(CIRCUIT_MODEL_LUT == model_type(model_id)); /* LUT inter buffer may not always exist */ if (LUT_INTER_BUFFER < buffer_existence_[model_id].size()) { - return buffer_existence_[model_id][LUT_INTER_BUFFER]; + return buffer_existence_[model_id][LUT_INTER_BUFFER]; } else { return false; } @@ -162,44 +170,48 @@ bool CircuitLibrary::is_lut_fracturable(const CircuitModelId& model_id) const { VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is LUT */ VTR_ASSERT(CIRCUIT_MODEL_LUT == model_type(model_id)); - return lut_is_fracturable_[model_id]; + return lut_is_fracturable_[model_id]; } /* Return the circuit model of input buffers * that are inserted between multiplexing structure and LUT inputs */ -CircuitModelId CircuitLibrary::lut_input_inverter_model(const CircuitModelId& model_id) const { +CircuitModelId CircuitLibrary::lut_input_inverter_model( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is BUF */ VTR_ASSERT(CIRCUIT_MODEL_LUT == model_type(model_id)); /* We MUST have an input inverter */ - VTR_ASSERT(true == buffer_existence_[model_id][LUT_INPUT_INVERTER]); + VTR_ASSERT(true == buffer_existence_[model_id][LUT_INPUT_INVERTER]); return buffer_model_ids_[model_id][LUT_INPUT_INVERTER]; } /* Return the circuit model of input buffers * that are inserted between multiplexing structure and LUT inputs */ -CircuitModelId CircuitLibrary::lut_input_buffer_model(const CircuitModelId& model_id) const { +CircuitModelId CircuitLibrary::lut_input_buffer_model( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is BUF */ VTR_ASSERT(CIRCUIT_MODEL_LUT == model_type(model_id)); /* We MUST have an input buffer */ - VTR_ASSERT(true == buffer_existence_[model_id][LUT_INPUT_BUFFER]); + VTR_ASSERT(true == buffer_existence_[model_id][LUT_INPUT_BUFFER]); return buffer_model_ids_[model_id][LUT_INPUT_BUFFER]; } /* Return the circuit model of intermediate buffers * that are inserted inside LUT multiplexing structures */ -CircuitModelId CircuitLibrary::lut_intermediate_buffer_model(const CircuitModelId& model_id) const { +CircuitModelId CircuitLibrary::lut_intermediate_buffer_model( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is BUF */ VTR_ASSERT(CIRCUIT_MODEL_LUT == model_type(model_id)); - /* if we have an intermediate buffer, we return something, otherwise return an invalid id */ + /* if we have an intermediate buffer, we return something, otherwise return an + * invalid id */ if (true == is_lut_intermediate_buffered(model_id)) { return buffer_model_ids_[model_id][LUT_INTER_BUFFER]; } else { @@ -210,12 +222,14 @@ CircuitModelId CircuitLibrary::lut_intermediate_buffer_model(const CircuitModelI /* Return the location map of intermediate buffers * that are inserted inside LUT multiplexing structures */ -std::string CircuitLibrary::lut_intermediate_buffer_location_map(const CircuitModelId& model_id) const { +std::string CircuitLibrary::lut_intermediate_buffer_location_map( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is BUF */ VTR_ASSERT(CIRCUIT_MODEL_LUT == model_type(model_id)); - /* if we have an intermediate buffer, we return something, otherwise return an empty map */ + /* if we have an intermediate buffer, we return something, otherwise return an + * empty map */ if (true == is_lut_intermediate_buffered(model_id)) { return buffer_location_maps_[model_id][LUT_INTER_BUFFER]; } else { @@ -223,15 +237,17 @@ std::string CircuitLibrary::lut_intermediate_buffer_location_map(const CircuitMo } } -/* Find the id of pass-gate circuit model +/* Find the id of pass-gate circuit model * Two cases to be considered: * 1. this is a pass-gate circuit model, just find the data and return - * 2. this circuit model includes a pass-gate, find the link to pass-gate circuit model and go recursively + * 2. this circuit model includes a pass-gate, find the link to pass-gate + * circuit model and go recursively */ -CircuitModelId CircuitLibrary::pass_gate_logic_model(const CircuitModelId& model_id) const { +CircuitModelId CircuitLibrary::pass_gate_logic_model( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - + /* Return the data if this is a pass-gate circuit model */ if (CIRCUIT_MODEL_PASSGATE == model_type(model_id)) { return model_ids_[model_id]; @@ -239,19 +255,21 @@ CircuitModelId CircuitLibrary::pass_gate_logic_model(const CircuitModelId& model /* Otherwise, we need to make sure this circuit model contains a pass-gate */ CircuitModelId pgl_model_id = pass_gate_logic_model_ids_[model_id]; - VTR_ASSERT( CircuitModelId::INVALID() != pgl_model_id ); + VTR_ASSERT(CircuitModelId::INVALID() != pgl_model_id); return pgl_model_id; } -/* Find the name of pass-gate circuit model +/* Find the name of pass-gate circuit model * Two cases to be considered: * 1. this is a pass-gate circuit model, just find the data and return - * 2. this circuit model includes a pass-gate, find the link to pass-gate circuit model and go recursively + * 2. this circuit model includes a pass-gate, find the link to pass-gate + * circuit model and go recursively */ -std::string CircuitLibrary::pass_gate_logic_model_name(const CircuitModelId& model_id) const { +std::string CircuitLibrary::pass_gate_logic_model_name( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - + /* Return the data if this is a pass-gate circuit model */ if (CIRCUIT_MODEL_PASSGATE == model_type(model_id)) { return model_names_[model_id]; @@ -261,8 +279,10 @@ std::string CircuitLibrary::pass_gate_logic_model_name(const CircuitModelId& mod return pass_gate_logic_model_names_[model_id]; } -/* Return the type of pass gate logic module, only applicable to circuit model whose type is pass-gate logic */ -enum e_circuit_model_pass_gate_logic_type CircuitLibrary::pass_gate_logic_type(const CircuitModelId& model_id) const { +/* Return the type of pass gate logic module, only applicable to circuit model + * whose type is pass-gate logic */ +enum e_circuit_model_pass_gate_logic_type CircuitLibrary::pass_gate_logic_type( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is PASSGATE */ @@ -270,32 +290,37 @@ enum e_circuit_model_pass_gate_logic_type CircuitLibrary::pass_gate_logic_type(c return pass_gate_logic_types_[model_id]; } -/* Return the pmos size of a pass gate logic module, only applicable to circuit model whose type is pass-gate logic */ -float CircuitLibrary::pass_gate_logic_pmos_size(const CircuitModelId& model_id) const { +/* Return the pmos size of a pass gate logic module, only applicable to circuit + * model whose type is pass-gate logic */ +float CircuitLibrary::pass_gate_logic_pmos_size( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be PASSGATE */ VTR_ASSERT(CIRCUIT_MODEL_PASSGATE == model_type(model_id)); - return pass_gate_logic_sizes_[model_id].y(); + return pass_gate_logic_sizes_[model_id].y(); } -/* Return the nmos size of a pass gate logic module, only applicable to circuit model whose type is pass-gate logic */ -float CircuitLibrary::pass_gate_logic_nmos_size(const CircuitModelId& model_id) const { +/* Return the nmos size of a pass gate logic module, only applicable to circuit + * model whose type is pass-gate logic */ +float CircuitLibrary::pass_gate_logic_nmos_size( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be PASSGATE */ VTR_ASSERT(CIRCUIT_MODEL_PASSGATE == model_type(model_id)); - return pass_gate_logic_sizes_[model_id].x(); + return pass_gate_logic_sizes_[model_id].x(); } /* Return the type of multiplexing structure of a circuit model */ -enum e_circuit_model_structure CircuitLibrary::mux_structure(const CircuitModelId& model_id) const { +enum e_circuit_model_structure CircuitLibrary::mux_structure( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is MUX */ - VTR_ASSERT( (CIRCUIT_MODEL_MUX == model_type(model_id)) - || (CIRCUIT_MODEL_LUT == model_type(model_id)) ); - return mux_structure_[model_id]; + VTR_ASSERT((CIRCUIT_MODEL_MUX == model_type(model_id)) || + (CIRCUIT_MODEL_LUT == model_type(model_id))); + return mux_structure_[model_id]; } /* Return the number of levels of multiplexing structure of a circuit model */ @@ -303,68 +328,72 @@ size_t CircuitLibrary::mux_num_levels(const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is MUX */ - VTR_ASSERT( (CIRCUIT_MODEL_MUX == model_type(model_id)) - || (CIRCUIT_MODEL_LUT == model_type(model_id)) ); + VTR_ASSERT((CIRCUIT_MODEL_MUX == model_type(model_id)) || + (CIRCUIT_MODEL_LUT == model_type(model_id))); return mux_num_levels_[model_id]; } -/* Return if additional constant inputs are required for a circuit model - * Only applicable for MUX/LUT circuit model +/* Return if additional constant inputs are required for a circuit model + * Only applicable for MUX/LUT circuit model */ bool CircuitLibrary::mux_add_const_input(const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is MUX */ - VTR_ASSERT( (CIRCUIT_MODEL_MUX == model_type(model_id)) - || (CIRCUIT_MODEL_LUT == model_type(model_id)) ); + VTR_ASSERT((CIRCUIT_MODEL_MUX == model_type(model_id)) || + (CIRCUIT_MODEL_LUT == model_type(model_id))); /* A -1 value for the const values means there is no const inputs */ - return ( size_t(-1) != mux_const_input_values_[model_id] ); + return (size_t(-1) != mux_const_input_values_[model_id]); } -/* Return if additional constant inputs are required for a circuit model - * Only applicable for MUX/LUT circuit model +/* Return if additional constant inputs are required for a circuit model + * Only applicable for MUX/LUT circuit model */ -size_t CircuitLibrary::mux_const_input_value(const CircuitModelId& model_id) const { +size_t CircuitLibrary::mux_const_input_value( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is MUX */ - VTR_ASSERT( (CIRCUIT_MODEL_MUX == model_type(model_id)) - || (CIRCUIT_MODEL_LUT == model_type(model_id)) ); + VTR_ASSERT((CIRCUIT_MODEL_MUX == model_type(model_id)) || + (CIRCUIT_MODEL_LUT == model_type(model_id))); /* A -1 value for the const values means there is no const inputs */ /* A 0 value for the const values means it is logic 0 */ /* A 1 value for the const values means it is logic 1 */ return mux_const_input_values_[model_id]; } -/* Return if local encoders are used for a circuit model - * Only applicable for MUX/LUT circuit model +/* Return if local encoders are used for a circuit model + * Only applicable for MUX/LUT circuit model */ -bool CircuitLibrary::mux_use_local_encoder(const CircuitModelId& model_id) const { +bool CircuitLibrary::mux_use_local_encoder( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is MUX */ - VTR_ASSERT( (CIRCUIT_MODEL_MUX == model_type(model_id)) - || (CIRCUIT_MODEL_LUT == model_type(model_id)) ); + VTR_ASSERT((CIRCUIT_MODEL_MUX == model_type(model_id)) || + (CIRCUIT_MODEL_LUT == model_type(model_id))); return mux_use_local_encoder_[model_id]; } /* Return if circuit model uses advanced RRAM design - * Only applicable for MUX/LUT circuit model + * Only applicable for MUX/LUT circuit model */ -bool CircuitLibrary::mux_use_advanced_rram_design(const CircuitModelId& model_id) const { +bool CircuitLibrary::mux_use_advanced_rram_design( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is MUX */ - VTR_ASSERT( (CIRCUIT_MODEL_MUX == model_type(model_id)) - || (CIRCUIT_MODEL_LUT == model_type(model_id)) ); + VTR_ASSERT((CIRCUIT_MODEL_MUX == model_type(model_id)) || + (CIRCUIT_MODEL_LUT == model_type(model_id))); return mux_use_advanced_rram_design_[model_id]; } -/* Return the type of gate for a circuit model - * Only applicable for GATE circuit model +/* Return the type of gate for a circuit model + * Only applicable for GATE circuit model */ -enum e_circuit_model_gate_type CircuitLibrary::gate_type(const CircuitModelId& model_id) const { +enum e_circuit_model_gate_type CircuitLibrary::gate_type( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is MUX */ @@ -372,10 +401,11 @@ enum e_circuit_model_gate_type CircuitLibrary::gate_type(const CircuitModelId& m return gate_types_[model_id]; } -/* Return the type of buffer for a circuit model - * Only applicable for BUF/INV circuit model +/* Return the type of buffer for a circuit model + * Only applicable for BUF/INV circuit model */ -enum e_circuit_model_buffer_type CircuitLibrary::buffer_type(const CircuitModelId& model_id) const { +enum e_circuit_model_buffer_type CircuitLibrary::buffer_type( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is MUX */ @@ -383,8 +413,8 @@ enum e_circuit_model_buffer_type CircuitLibrary::buffer_type(const CircuitModelI return buffer_types_[model_id]; } -/* Return the size of buffer for a circuit model - * Only applicable for BUF/INV circuit model +/* Return the size of buffer for a circuit model + * Only applicable for BUF/INV circuit model */ size_t CircuitLibrary::buffer_size(const CircuitModelId& model_id) const { /* validate the model_id */ @@ -394,8 +424,8 @@ size_t CircuitLibrary::buffer_size(const CircuitModelId& model_id) const { return buffer_sizes_[model_id]; } -/* Return the number of levels of buffer for a circuit model - * Only applicable for BUF/INV circuit model +/* Return the number of levels of buffer for a circuit model + * Only applicable for BUF/INV circuit model */ size_t CircuitLibrary::buffer_num_levels(const CircuitModelId& model_id) const { /* validate the model_id */ @@ -405,10 +435,11 @@ size_t CircuitLibrary::buffer_num_levels(const CircuitModelId& model_id) const { return buffer_num_levels_[model_id]; } -/* Return the driving strength per level of buffer for a circuit model - * Only applicable for BUF/INV circuit model +/* Return the driving strength per level of buffer for a circuit model + * Only applicable for BUF/INV circuit model */ -size_t CircuitLibrary::buffer_f_per_stage(const CircuitModelId& model_id) const { +size_t CircuitLibrary::buffer_f_per_stage( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate the circuit model type is BUF */ @@ -417,24 +448,26 @@ size_t CircuitLibrary::buffer_f_per_stage(const CircuitModelId& model_id) const } /* Find the circuit model id of the input buffer of a circuit model */ -CircuitModelId CircuitLibrary::input_buffer_model(const CircuitModelId& model_id) const { +CircuitModelId CircuitLibrary::input_buffer_model( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* INPUT buffer may not always exist */ if (INPUT < buffer_existence_[model_id].size()) { - return buffer_model_ids_[model_id][INPUT]; + return buffer_model_ids_[model_id][INPUT]; } else { return CircuitModelId::INVALID(); } } /* Find the circuit model id of the output buffer of a circuit model */ -CircuitModelId CircuitLibrary::output_buffer_model(const CircuitModelId& model_id) const { +CircuitModelId CircuitLibrary::output_buffer_model( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* OUTPUT buffer may not always exist */ if (OUTPUT < buffer_existence_[model_id].size()) { - return buffer_model_ids_[model_id][OUTPUT]; + return buffer_model_ids_[model_id][OUTPUT]; } else { return CircuitModelId::INVALID(); } @@ -447,43 +480,45 @@ size_t CircuitLibrary::num_delay_info(const CircuitModelId& model_id) const { return delay_types_[model_id].size(); } -/* Return the type of a wire model, this is ONLY applicable to wires and channel wires */ -e_wire_model_type CircuitLibrary::wire_type(const CircuitModelId& model_id) const { +/* Return the type of a wire model, this is ONLY applicable to wires and channel + * wires */ +e_wire_model_type CircuitLibrary::wire_type( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - VTR_ASSERT( (CIRCUIT_MODEL_WIRE == model_type(model_id)) - || (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id)) ); + VTR_ASSERT((CIRCUIT_MODEL_WIRE == model_type(model_id)) || + (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id))); return wire_types_[model_id]; } -/* Return the resistance value of a wire model, - * this is ONLY applicable to wires and channel wires +/* Return the resistance value of a wire model, + * this is ONLY applicable to wires and channel wires */ float CircuitLibrary::wire_r(const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be WIRE or CHAN_WIRE */ - VTR_ASSERT( (CIRCUIT_MODEL_WIRE == model_type(model_id)) - || (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id)) ); - return wire_rc_[model_id].x(); + VTR_ASSERT((CIRCUIT_MODEL_WIRE == model_type(model_id)) || + (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id))); + return wire_rc_[model_id].x(); } float CircuitLibrary::wire_c(const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be WIRE or CHAN_WIRE */ - VTR_ASSERT( (CIRCUIT_MODEL_WIRE == model_type(model_id)) - || (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id)) ); - return wire_rc_[model_id].y(); + VTR_ASSERT((CIRCUIT_MODEL_WIRE == model_type(model_id)) || + (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id))); + return wire_rc_[model_id].y(); } size_t CircuitLibrary::wire_num_level(const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be WIRE or CHAN_WIRE */ - VTR_ASSERT( (CIRCUIT_MODEL_WIRE == model_type(model_id)) - || (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id)) ); - return wire_num_levels_[model_id]; + VTR_ASSERT((CIRCUIT_MODEL_WIRE == model_type(model_id)) || + (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id))); + return wire_num_levels_[model_id]; } /* Return the Low Resistance State Resistance of a RRAM model */ @@ -492,7 +527,7 @@ float CircuitLibrary::rram_rlrs(const CircuitModelId& model_id) const { VTR_ASSERT(valid_model_id(model_id)); /* validate that the design_tech of this model should be RRAM */ VTR_ASSERT(CIRCUIT_MODEL_DESIGN_RRAM == design_tech_type(model_id)); - return rram_res_[model_id].x(); + return rram_res_[model_id].x(); } /* Return the High Resistance State Resistance of a RRAM model */ @@ -501,40 +536,44 @@ float CircuitLibrary::rram_rhrs(const CircuitModelId& model_id) const { VTR_ASSERT(valid_model_id(model_id)); /* validate that the design_tech of this model should be RRAM */ VTR_ASSERT(CIRCUIT_MODEL_DESIGN_RRAM == design_tech_type(model_id)); - return rram_res_[model_id].y(); + return rram_res_[model_id].y(); } /* Return the size of PMOS transistor to set a RRAM model */ -float CircuitLibrary::rram_wprog_set_pmos(const CircuitModelId& model_id) const { +float CircuitLibrary::rram_wprog_set_pmos( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the design_tech of this model should be RRAM */ VTR_ASSERT(CIRCUIT_MODEL_DESIGN_RRAM == design_tech_type(model_id)); - return wprog_set_[model_id].y(); + return wprog_set_[model_id].y(); } -float CircuitLibrary::rram_wprog_set_nmos(const CircuitModelId& model_id) const { +float CircuitLibrary::rram_wprog_set_nmos( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the design_tech of this model should be RRAM */ VTR_ASSERT(CIRCUIT_MODEL_DESIGN_RRAM == design_tech_type(model_id)); - return wprog_set_[model_id].x(); + return wprog_set_[model_id].x(); } -float CircuitLibrary::rram_wprog_reset_pmos(const CircuitModelId& model_id) const { +float CircuitLibrary::rram_wprog_reset_pmos( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the design_tech of this model should be RRAM */ VTR_ASSERT(CIRCUIT_MODEL_DESIGN_RRAM == design_tech_type(model_id)); - return wprog_reset_[model_id].y(); + return wprog_reset_[model_id].y(); } -float CircuitLibrary::rram_wprog_reset_nmos(const CircuitModelId& model_id) const { +float CircuitLibrary::rram_wprog_reset_nmos( + const CircuitModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the design_tech of this model should be RRAM */ VTR_ASSERT(CIRCUIT_MODEL_DESIGN_RRAM == design_tech_type(model_id)); - return wprog_reset_[model_id].x(); + return wprog_reset_[model_id].x(); } /************************************************************************ @@ -542,7 +581,8 @@ float CircuitLibrary::rram_wprog_reset_nmos(const CircuitModelId& model_id) cons ***********************************************************************/ /* Given a name and return the port id */ -CircuitPortId CircuitLibrary::model_port(const CircuitModelId& model_id, const std::string& name) const { +CircuitPortId CircuitLibrary::model_port(const CircuitModelId& model_id, + const std::string& name) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* Walk through the ports and try to find a matched name */ @@ -558,7 +598,7 @@ CircuitPortId CircuitLibrary::model_port(const CircuitModelId& model_id, const s } } /* Make sure we will not find two ports with the same name */ - VTR_ASSERT( (0 == num_found) || (1 == num_found) ); + VTR_ASSERT((0 == num_found) || (1 == num_found)); return ret; } @@ -574,13 +614,14 @@ size_t CircuitLibrary::num_model_ports(const CircuitModelId& model_id) const { return num_of_ports; } -/* Access the type of a port of a circuit model - * with an option to include/exclude global ports - * when counting +/* Access the type of a port of a circuit model + * with an option to include/exclude global ports + * when counting */ -size_t CircuitLibrary::num_model_ports_by_type(const CircuitModelId& model_id, - const enum e_circuit_model_port_type& port_type, - const bool& include_global_port) const { +size_t CircuitLibrary::num_model_ports_by_type( + const CircuitModelId& model_id, + const enum e_circuit_model_port_type& port_type, + const bool& include_global_port) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* Search the port look up */ @@ -588,18 +629,18 @@ size_t CircuitLibrary::num_model_ports_by_type(const CircuitModelId& model_id, size_t num_ports = 0; for (auto port : model_port_lookup_[model_id][port_type]) { /* By pass non-global ports if required by user */ - if ( (false == include_global_port) - && (true == port_is_global(port)) ) { + if ((false == include_global_port) && (true == port_is_global(port))) { continue; } num_ports++; - } + } return num_ports; } /* Find all the ports belong to a circuit model */ -std::vector CircuitLibrary::model_ports(const CircuitModelId& model_id) const { +std::vector CircuitLibrary::model_ports( + const CircuitModelId& model_id) const { /* validate the circuit_model_id */ VTR_ASSERT(valid_model_id(model_id)); /* Search the port look up and return a list */ @@ -612,9 +653,10 @@ std::vector CircuitLibrary::model_ports(const CircuitModelId& mod return port_ids; } -/* Recursively find all the global ports in the circuit model / sub circuit_model */ -std::vector CircuitLibrary::model_global_ports(const CircuitModelId& model_id, - const bool& recursive) const { +/* Recursively find all the global ports in the circuit model / sub + * circuit_model */ +std::vector CircuitLibrary::model_global_ports( + const CircuitModelId& model_id, const bool& recursive) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); @@ -627,7 +669,7 @@ std::vector CircuitLibrary::model_global_ports(const CircuitModel continue; } /* This is a global port, update global_ports */ - global_ports.push_back(port); + global_ports.push_back(port); } /* Finish, if we do not need to go recursively */ @@ -638,12 +680,14 @@ std::vector CircuitLibrary::model_global_ports(const CircuitModel /* If go recursively, we search all the buffer/pass-gate circuit model ids */ /* Go search every sub circuit model included the current circuit model */ for (const auto& sub_model : sub_models_[model_id]) { - std::vector sub_global_ports = model_global_ports(sub_model, recursive); + std::vector sub_global_ports = + model_global_ports(sub_model, recursive); for (const auto& sub_global_port : sub_global_ports) { /* Add to global_ports, if it is not already found in the list */ bool add_to_list = true; for (const auto& global_port : global_ports) { - if (0 == port_prefix(sub_global_port).compare(port_prefix(global_port))) { + if (0 == + port_prefix(sub_global_port).compare(port_prefix(global_port))) { /* Same name, skip list update */ add_to_list = false; break; @@ -659,11 +703,12 @@ std::vector CircuitLibrary::model_global_ports(const CircuitModel return global_ports; } -/* Recursively find all the global ports in the circuit model / sub circuit_model */ -std::vector CircuitLibrary::model_global_ports_by_type(const CircuitModelId& model_id, - const enum e_circuit_model_port_type& type, - const bool& recursive, - const std::vector& ignore_model_types) const { +/* Recursively find all the global ports in the circuit model / sub + * circuit_model */ +std::vector CircuitLibrary::model_global_ports_by_type( + const CircuitModelId& model_id, const enum e_circuit_model_port_type& type, + const bool& recursive, + const std::vector& ignore_model_types) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); @@ -675,11 +720,11 @@ std::vector CircuitLibrary::model_global_ports_by_type(const Circ continue; } /* We skip unmatched ports */ - if ( type != port_type(port) ) { - continue; + if (type != port_type(port)) { + continue; } /* This is a global port, update global_ports */ - global_ports.push_back(port); + global_ports.push_back(port); } /* Finish, if we do not need to go recursively */ @@ -692,7 +737,7 @@ std::vector CircuitLibrary::model_global_ports_by_type(const Circ for (const auto& sub_model : sub_models_[model_id]) { /* Bypass this sub model if user specified an ignore list */ bool ignore = false; - for (const auto& ignore_model_type : ignore_model_types) { + for (const auto& ignore_model_type : ignore_model_types) { if (ignore_model_type != model_type(sub_model)) { continue; } @@ -702,14 +747,16 @@ std::vector CircuitLibrary::model_global_ports_by_type(const Circ if (true == ignore) { continue; } - + /* Now we can add global ports */ - std::vector sub_global_ports = model_global_ports_by_type(sub_model, type, recursive, ignore_model_types); + std::vector sub_global_ports = model_global_ports_by_type( + sub_model, type, recursive, ignore_model_types); for (const auto& sub_global_port : sub_global_ports) { /* Add to global_ports, if it is not already found in the list */ bool add_to_list = true; for (const auto& global_port : global_ports) { - if (0 == port_prefix(sub_global_port).compare(port_prefix(global_port))) { + if (0 == + port_prefix(sub_global_port).compare(port_prefix(global_port))) { /* Same name, skip list update */ add_to_list = false; break; @@ -725,32 +772,33 @@ std::vector CircuitLibrary::model_global_ports_by_type(const Circ return global_ports; } - -/* Recursively find all the global ports in the circuit model / sub circuit_model - * whose port type matches users' specification +/* Recursively find all the global ports in the circuit model / sub + * circuit_model whose port type matches users' specification */ -std::vector CircuitLibrary::model_global_ports_by_type(const CircuitModelId& model_id, - const std::vector& types, - const bool& recursive, - const bool& ignore_config_memories) const { +std::vector CircuitLibrary::model_global_ports_by_type( + const CircuitModelId& model_id, + const std::vector& types, + const bool& recursive, const bool& ignore_config_memories) const { std::vector global_ports; std::vector ignore_list; for (const auto& port_type : types) { - std::vector global_port_by_type = model_global_ports_by_type(model_id, port_type, recursive, ignore_config_memories); + std::vector global_port_by_type = model_global_ports_by_type( + model_id, port_type, recursive, ignore_config_memories); /* Insert the vector to the final global_ports */ - global_ports.insert(global_ports.begin(), global_port_by_type.begin(), global_port_by_type.end()); + global_ports.insert(global_ports.begin(), global_port_by_type.begin(), + global_port_by_type.end()); } return global_ports; } -/* Recursively find all the global ports in the circuit model / sub circuit_model - * but ignore all the SRAM and CCFF, which are configuration memories +/* Recursively find all the global ports in the circuit model / sub + * circuit_model but ignore all the SRAM and CCFF, which are configuration + * memories */ -std::vector CircuitLibrary::model_global_ports_by_type(const CircuitModelId& model_id, - const enum e_circuit_model_port_type& type, - const bool& recursive, - const bool& ignore_config_memories) const { +std::vector CircuitLibrary::model_global_ports_by_type( + const CircuitModelId& model_id, const enum e_circuit_model_port_type& type, + const bool& recursive, const bool& ignore_config_memories) const { std::vector ignore_list; if (true == ignore_config_memories) { ignore_list.push_back(CIRCUIT_MODEL_SRAM); @@ -759,83 +807,86 @@ std::vector CircuitLibrary::model_global_ports_by_type(const Circ return model_global_ports_by_type(model_id, type, recursive, ignore_list); } -/* Find the ports of a circuit model by a given type, return a list of qualified ports */ -std::vector CircuitLibrary::model_ports_by_type(const CircuitModelId& model_id, - const enum e_circuit_model_port_type& type) const { +/* Find the ports of a circuit model by a given type, return a list of qualified + * ports */ +std::vector CircuitLibrary::model_ports_by_type( + const CircuitModelId& model_id, + const enum e_circuit_model_port_type& type) const { std::vector port_ids; for (const auto& port_id : model_ports(model_id)) { /* We skip unmatched ports */ - if ( type != port_type(port_id) ) { - continue; + if (type != port_type(port_id)) { + continue; } port_ids.push_back(port_id); - } + } return port_ids; } -/* Find the ports of a circuit model by a given type, return a list of qualified ports - * with an option to include/exclude global ports +/* Find the ports of a circuit model by a given type, return a list of qualified + * ports with an option to include/exclude global ports */ -std::vector CircuitLibrary::model_ports_by_type(const CircuitModelId& model_id, - const enum e_circuit_model_port_type& type, - const bool& ignore_global_port) const { +std::vector CircuitLibrary::model_ports_by_type( + const CircuitModelId& model_id, const enum e_circuit_model_port_type& type, + const bool& ignore_global_port) const { std::vector port_ids; for (const auto& port_id : model_port_lookup_[model_id][type]) { /* We skip unmatched ports */ - if ( type != port_type(port_id) ) { - continue; + if (type != port_type(port_id)) { + continue; } /* We skip global ports if specified. Note: I/O port should be kept */ - if ( (true == ignore_global_port) - && (true == port_is_global(port_id)) ) { - continue; + if ((true == ignore_global_port) && (true == port_is_global(port_id))) { + continue; } port_ids.push_back(port_id); - } + } return port_ids; } /* Create a vector for all the ports whose directionality is input - * This includes all the ports other than whose types are OUPUT or INOUT + * This includes all the ports other than whose types are OUPUT or INOUT */ -std::vector CircuitLibrary::model_input_ports(const CircuitModelId& model_id) const { +std::vector CircuitLibrary::model_input_ports( + const CircuitModelId& model_id) const { std::vector input_ports; for (const auto& port_id : model_ports(model_id)) { /* We skip output ports */ - if ( false == is_input_port(port_id) ) { - continue; + if (false == is_input_port(port_id)) { + continue; } input_ports.push_back(port_id); - } + } return input_ports; } /* Create a vector for all the ports whose directionality is output - * This includes all the ports whose types are OUPUT or INOUT + * This includes all the ports whose types are OUPUT or INOUT */ -std::vector CircuitLibrary::model_output_ports(const CircuitModelId& model_id) const { +std::vector CircuitLibrary::model_output_ports( + const CircuitModelId& model_id) const { std::vector output_ports; for (const auto& port_id : model_ports(model_id)) { /* We skip input ports */ - if ( false == is_output_port(port_id) ) { - continue; + if (false == is_output_port(port_id)) { + continue; } output_ports.push_back(port_id); - } + } return output_ports; } /* Create a vector for the pin indices, which is bounded by the size of a port * Start from 0 and end to port_size - 1 */ -std::vector CircuitLibrary::pins(const CircuitPortId& circuit_port_id) const { +std::vector CircuitLibrary::pins( + const CircuitPortId& circuit_port_id) const { std::vector pin_range(port_size(circuit_port_id)); /* Create a vector, with sequentially increasing numbers */ std::iota(pin_range.begin(), pin_range.end(), 0); return pin_range; } - /************************************************************************ * Public Accessors : Basic data query on Circuit Port ***********************************************************************/ @@ -845,21 +896,23 @@ bool CircuitLibrary::is_input_port(const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); /* Only CIRCUIT_MODEL_OUTPUT AND INOUT are considered as outputs */ - return ( (CIRCUIT_MODEL_PORT_OUTPUT != port_type(circuit_port_id)) - && (CIRCUIT_MODEL_PORT_INOUT != port_type(circuit_port_id)) ); + return ((CIRCUIT_MODEL_PORT_OUTPUT != port_type(circuit_port_id)) && + (CIRCUIT_MODEL_PORT_INOUT != port_type(circuit_port_id))); } /* identify if this port is an output port */ -bool CircuitLibrary::is_output_port(const CircuitPortId& circuit_port_id) const { +bool CircuitLibrary::is_output_port( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); /* Only CIRCUIT_MODEL_OUTPUT AND INOUT are considered as outputs */ - return ( (CIRCUIT_MODEL_PORT_OUTPUT == port_type(circuit_port_id)) - || (CIRCUIT_MODEL_PORT_INOUT == port_type(circuit_port_id)) ); + return ((CIRCUIT_MODEL_PORT_OUTPUT == port_type(circuit_port_id)) || + (CIRCUIT_MODEL_PORT_INOUT == port_type(circuit_port_id))); } /* Access the type of a port of a circuit model */ -enum e_circuit_model_port_type CircuitLibrary::port_type(const CircuitPortId& circuit_port_id) const { +enum e_circuit_model_port_type CircuitLibrary::port_type( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_types_[circuit_port_id]; @@ -873,56 +926,66 @@ size_t CircuitLibrary::port_size(const CircuitPortId& circuit_port_id) const { } /* Access the prefix of a port of a circuit model */ -std::string CircuitLibrary::port_prefix(const CircuitPortId& circuit_port_id) const { +std::string CircuitLibrary::port_prefix( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_prefix_[circuit_port_id]; } /* Access the lib_name of a port of a circuit model */ -std::string CircuitLibrary::port_lib_name(const CircuitPortId& circuit_port_id) const { +std::string CircuitLibrary::port_lib_name( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_lib_names_[circuit_port_id]; } /* Access the inv_prefix of a port of a circuit model */ -std::string CircuitLibrary::port_inv_prefix(const CircuitPortId& circuit_port_id) const { +std::string CircuitLibrary::port_inv_prefix( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_inv_prefix_[circuit_port_id]; } /* Return the default value of a port of a circuit model */ -size_t CircuitLibrary::port_default_value(const CircuitPortId& circuit_port_id) const { +size_t CircuitLibrary::port_default_value( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_default_values_[circuit_port_id]; } -/* Return a flag if the port is used in mode-selection purpuse of a circuit model */ +/* Return a flag if the port is used in mode-selection purpuse of a circuit + * model */ bool CircuitLibrary::port_is_io(const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_is_io_[circuit_port_id]; } -/* Return a flag if the port is used in mode-selection purpuse of a circuit model */ -bool CircuitLibrary::port_is_data_io(const CircuitPortId& circuit_port_id) const { +/* Return a flag if the port is used in mode-selection purpuse of a circuit + * model */ +bool CircuitLibrary::port_is_data_io( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_is_data_io_[circuit_port_id]; } -/* Return a flag if the port is used in mode-selection purpuse of a circuit model */ -bool CircuitLibrary::port_is_mode_select(const CircuitPortId& circuit_port_id) const { +/* Return a flag if the port is used in mode-selection purpuse of a circuit + * model */ +bool CircuitLibrary::port_is_mode_select( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_is_mode_select_[circuit_port_id]; } /* Return a flag if the port is a global one of a circuit model */ -bool CircuitLibrary::port_is_global(const CircuitPortId& circuit_port_id) const { +bool CircuitLibrary::port_is_global( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_is_global_[circuit_port_id]; @@ -943,13 +1006,15 @@ bool CircuitLibrary::port_is_set(const CircuitPortId& circuit_port_id) const { } /* Return a flag if the port enables a configuration in a circuit model */ -bool CircuitLibrary::port_is_config_enable(const CircuitPortId& circuit_port_id) const { +bool CircuitLibrary::port_is_config_enable( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_is_config_enable_[circuit_port_id]; } -/* Return a flag if the port is used during programming a FPGA in a circuit model */ +/* Return a flag if the port is used during programming a FPGA in a circuit + * model */ bool CircuitLibrary::port_is_prog(const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); @@ -957,56 +1022,65 @@ bool CircuitLibrary::port_is_prog(const CircuitPortId& circuit_port_id) const { } /* Return a flag if the port is used by shift register in a circuit model */ -bool CircuitLibrary::port_is_shift_register(const CircuitPortId& circuit_port_id) const { +bool CircuitLibrary::port_is_shift_register( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_is_shift_register_[circuit_port_id]; } /* Return which level the output port locates at a LUT multiplexing structure */ -size_t CircuitLibrary::port_lut_frac_level(const CircuitPortId& circuit_port_id) const { +size_t CircuitLibrary::port_lut_frac_level( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_lut_frac_level_[circuit_port_id]; } /* Return if the port drives or is driven by a harden logic inside a LUT */ -bool CircuitLibrary::port_is_harden_lut_port(const CircuitPortId& circuit_port_id) const { +bool CircuitLibrary::port_is_harden_lut_port( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_is_harden_lut_port_[circuit_port_id]; } -/* Return indices of internal nodes in a LUT multiplexing structure to which the output port is wired to */ -std::vector CircuitLibrary::port_lut_output_mask(const CircuitPortId& circuit_port_id) const { +/* Return indices of internal nodes in a LUT multiplexing structure to which the + * output port is wired to */ +std::vector CircuitLibrary::port_lut_output_mask( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_lut_output_masks_[circuit_port_id]; } /* Return tri-state map of a port */ -std::string CircuitLibrary::port_tri_state_map(const CircuitPortId& circuit_port_id) const { +std::string CircuitLibrary::port_tri_state_map( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_tri_state_maps_[circuit_port_id]; } /* Return circuit model id which is used to tri-state a port */ -CircuitModelId CircuitLibrary::port_tri_state_model(const CircuitPortId& circuit_port_id) const { +CircuitModelId CircuitLibrary::port_tri_state_model( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_tri_state_model_ids_[circuit_port_id]; } /* Return circuit model name which is used to tri-state a port */ -std::string CircuitLibrary::port_tri_state_model_name(const CircuitPortId& circuit_port_id) const { +std::string CircuitLibrary::port_tri_state_model_name( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_tri_state_model_names_[circuit_port_id]; } /* Return the id of parent circuit model for a circuit port */ -CircuitModelId CircuitLibrary::port_parent_model(const CircuitPortId& circuit_port_id) const { +CircuitModelId CircuitLibrary::port_parent_model( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_model_ids_[circuit_port_id]; @@ -1020,17 +1094,19 @@ std::string CircuitLibrary::model_name(const CircuitPortId& port_id) const { } /* Return the name of inverter circuit model linked to a circuit port */ -std::string CircuitLibrary::port_inv_model_name(const CircuitPortId& circuit_port_id) const { +std::string CircuitLibrary::port_inv_model_name( + const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); return port_inv_model_names_[circuit_port_id]; } /************************************************************************ - * Public Accessors : Methods to visit timing graphs + * Public Accessors : Methods to visit timing graphs ***********************************************************************/ /* Find all the edges belonging to a circuit model */ -std::vector CircuitLibrary::timing_edges_by_model(const CircuitModelId& model_id) const { +std::vector CircuitLibrary::timing_edges_by_model( + const CircuitModelId& model_id) const { /* Validate the model id */ VTR_ASSERT_SAFE(valid_model_id(model_id)); @@ -1047,19 +1123,21 @@ std::vector CircuitLibrary::timing_edges_by_model(const CircuitMo } /* Get source/sink nodes and delay of edges */ -CircuitPortId CircuitLibrary::timing_edge_src_port(const CircuitEdgeId& edge) const { +CircuitPortId CircuitLibrary::timing_edge_src_port( + const CircuitEdgeId& edge) const { /* Validate the edge id */ VTR_ASSERT_SAFE(valid_edge_id(edge)); return edge_src_port_ids_[edge]; } -size_t CircuitLibrary::timing_edge_src_pin(const CircuitEdgeId& edge) const { +size_t CircuitLibrary::timing_edge_src_pin(const CircuitEdgeId& edge) const { /* Validate the edge id */ VTR_ASSERT_SAFE(valid_edge_id(edge)); return edge_src_pin_ids_[edge]; } -CircuitPortId CircuitLibrary::timing_edge_sink_port(const CircuitEdgeId& edge) const { +CircuitPortId CircuitLibrary::timing_edge_sink_port( + const CircuitEdgeId& edge) const { /* Validate the edge id */ VTR_ASSERT_SAFE(valid_edge_id(edge)); return edge_sink_port_ids_[edge]; @@ -1071,14 +1149,16 @@ size_t CircuitLibrary::timing_edge_sink_pin(const CircuitEdgeId& edge) const { return edge_sink_pin_ids_[edge]; } -float CircuitLibrary::timing_edge_delay(const CircuitEdgeId& edge, const enum e_circuit_model_delay_type& delay_type) const { +float CircuitLibrary::timing_edge_delay( + const CircuitEdgeId& edge, + const enum e_circuit_model_delay_type& delay_type) const { /* Validate the edge id */ VTR_ASSERT_SAFE(valid_edge_id(edge)); return edge_timing_info_[edge][delay_type]; } /************************************************************************ - * Public Accessors : Methods to find circuit model + * Public Accessors : Methods to find circuit model ***********************************************************************/ /* Find a circuit model by a given name and return its id */ CircuitModelId CircuitLibrary::model(const char* name) const { @@ -1087,20 +1167,19 @@ CircuitModelId CircuitLibrary::model(const char* name) const { } /* Find a circuit model by a given name and return its id */ -CircuitModelId CircuitLibrary::model(const std::string& name) const { +CircuitModelId CircuitLibrary::model(const std::string& name) const { CircuitModelId ret = CircuitModelId::INVALID(); size_t num_found = 0; for (circuit_model_string_iterator it = model_names_.begin(); - it != model_names_.end(); - it++) { + it != model_names_.end(); it++) { /* Bypass unmatched names */ - if ( 0 != name.compare(*it) ) { + if (0 != name.compare(*it)) { continue; } - /* Find one and record it + /* Find one and record it * FIXME: I feel that we may have a better way in getting the CircuitModelId */ - ret = CircuitModelId(it - model_names_.begin()); + ret = CircuitModelId(it - model_names_.begin()); num_found++; } VTR_ASSERT((0 == num_found) || (1 == num_found)); @@ -1108,28 +1187,33 @@ CircuitModelId CircuitLibrary::model(const std::string& name) const { } /* Get the CircuitModelId of a default circuit model with a given type */ -CircuitModelId CircuitLibrary::default_model(const enum e_circuit_model_type& type) const { - /* Default circuit model id is the first element by type in the fast look-up */ +CircuitModelId CircuitLibrary::default_model( + const enum e_circuit_model_type& type) const { + /* Default circuit model id is the first element by type in the fast look-up + */ CircuitModelId default_id = model_lookup_[size_t(type)].front(); VTR_ASSERT(true == model_is_default(default_id)); return default_id; } /************************************************************************ - * Public Accessors: Timing graph + * Public Accessors: Timing graph ***********************************************************************/ -/* Given the source and sink port information, find the edge connecting the two ports */ -CircuitEdgeId CircuitLibrary::edge(const CircuitPortId& from_port, const size_t from_pin, - const CircuitPortId& to_port, const size_t to_pin) { +/* Given the source and sink port information, find the edge connecting the two + * ports */ +CircuitEdgeId CircuitLibrary::edge(const CircuitPortId& from_port, + const size_t from_pin, + const CircuitPortId& to_port, + const size_t to_pin) { /* validate the circuit_pin_id */ VTR_ASSERT(valid_circuit_pin_id(from_port, from_pin)); VTR_ASSERT(valid_circuit_pin_id(to_port, to_pin)); /* Walk through the edge list until we find the one */ - for (auto edge : edge_ids_) { - if ( (from_port == edge_src_port_ids_[edge]) - && (from_pin == edge_src_pin_ids_[edge]) - && (to_port == edge_sink_port_ids_[edge]) - && (to_pin == edge_sink_pin_ids_[edge]) ) { + for (auto edge : edge_ids_) { + if ((from_port == edge_src_port_ids_[edge]) && + (from_pin == edge_src_pin_ids_[edge]) && + (to_port == edge_sink_port_ids_[edge]) && + (to_pin == edge_sink_pin_ids_[edge])) { return edge; } } @@ -1138,15 +1222,16 @@ CircuitEdgeId CircuitLibrary::edge(const CircuitPortId& from_port, const size_t } /************************************************************************ - * Public Mutators + * Public Mutators ***********************************************************************/ /* Add a circuit model to the library, and return it Id */ -CircuitModelId CircuitLibrary::add_model(const enum e_circuit_model_type& type) { +CircuitModelId CircuitLibrary::add_model( + const enum e_circuit_model_type& type) { /* Create a new id*/ CircuitModelId model_id = CircuitModelId(model_ids_.size()); /* Update the id list */ model_ids_.push_back(model_id); - + /* Initialize other attributes */ /* Fundamental information */ model_types_.push_back(type); @@ -1157,17 +1242,17 @@ CircuitModelId CircuitLibrary::add_model(const enum e_circuit_model_type& type) model_is_default_.push_back(false); sub_models_.emplace_back(); - /* Verilog generator options */ + /* Verilog generator options */ dump_structural_verilog_.push_back(false); dump_explicit_port_map_.push_back(false); - - /* Design technology information */ + + /* Design technology information */ design_tech_types_.push_back(NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES); is_power_gated_.push_back(false); - /* Device technology information */ + /* Device technology information */ device_model_names_.emplace_back(); - + /* Buffer existence */ buffer_existence_.emplace_back(); buffer_model_names_.emplace_back(); @@ -1222,10 +1307,10 @@ CircuitModelId CircuitLibrary::add_model(const enum e_circuit_model_type& type) /* Add a placeholder in the fast look-up for model port * This is to avoid memory holes when a circuit model - * does not have any ports. + * does not have any ports. * As a result, the fast look-up may not even create an entry * for this model id, which cause fast look-up abort when there is - * a query on the model + * a query on the model */ model_port_lookup_.resize(model_ids_.size()); model_port_lookup_[model_id].resize(NUM_CIRCUIT_MODEL_PORT_TYPES); @@ -1234,7 +1319,8 @@ CircuitModelId CircuitLibrary::add_model(const enum e_circuit_model_type& type) } /* Set the name of a Circuit Model */ -void CircuitLibrary::set_model_name(const CircuitModelId& model_id, const std::string& name) { +void CircuitLibrary::set_model_name(const CircuitModelId& model_id, + const std::string& name) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); model_names_[model_id] = name; @@ -1242,7 +1328,8 @@ void CircuitLibrary::set_model_name(const CircuitModelId& model_id, const std::s } /* Set the prefix of a Circuit Model */ -void CircuitLibrary::set_model_prefix(const CircuitModelId& model_id, const std::string& prefix) { +void CircuitLibrary::set_model_prefix(const CircuitModelId& model_id, + const std::string& prefix) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); model_prefix_[model_id] = prefix; @@ -1250,7 +1337,8 @@ void CircuitLibrary::set_model_prefix(const CircuitModelId& model_id, const std: } /* Set the verilog_netlist of a Circuit Model */ -void CircuitLibrary::set_model_verilog_netlist(const CircuitModelId& model_id, const std::string& verilog_netlist) { +void CircuitLibrary::set_model_verilog_netlist( + const CircuitModelId& model_id, const std::string& verilog_netlist) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); model_verilog_netlists_[model_id] = verilog_netlist; @@ -1258,7 +1346,8 @@ void CircuitLibrary::set_model_verilog_netlist(const CircuitModelId& model_id, c } /* Set the spice_netlist of a Circuit Model */ -void CircuitLibrary::set_model_spice_netlist(const CircuitModelId& model_id, const std::string& spice_netlist) { +void CircuitLibrary::set_model_spice_netlist(const CircuitModelId& model_id, + const std::string& spice_netlist) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); model_spice_netlists_[model_id] = spice_netlist; @@ -1266,7 +1355,8 @@ void CircuitLibrary::set_model_spice_netlist(const CircuitModelId& model_id, con } /* Set the is_default of a Circuit Model */ -void CircuitLibrary::set_model_is_default(const CircuitModelId& model_id, const bool& is_default) { +void CircuitLibrary::set_model_is_default(const CircuitModelId& model_id, + const bool& is_default) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); model_is_default_[model_id] = is_default; @@ -1274,7 +1364,8 @@ void CircuitLibrary::set_model_is_default(const CircuitModelId& model_id, const } /* Set the dump_structural_verilog of a Circuit Model */ -void CircuitLibrary::set_model_dump_structural_verilog(const CircuitModelId& model_id, const bool& dump_structural_verilog) { +void CircuitLibrary::set_model_dump_structural_verilog( + const CircuitModelId& model_id, const bool& dump_structural_verilog) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); dump_structural_verilog_[model_id] = dump_structural_verilog; @@ -1282,7 +1373,8 @@ void CircuitLibrary::set_model_dump_structural_verilog(const CircuitModelId& mod } /* Set the dump_explicit_port_map of a Circuit Model */ -void CircuitLibrary::set_model_dump_explicit_port_map(const CircuitModelId& model_id, const bool& dump_explicit_port_map) { +void CircuitLibrary::set_model_dump_explicit_port_map( + const CircuitModelId& model_id, const bool& dump_explicit_port_map) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); dump_explicit_port_map_[model_id] = dump_explicit_port_map; @@ -1290,7 +1382,9 @@ void CircuitLibrary::set_model_dump_explicit_port_map(const CircuitModelId& mode } /* Set the type of design technology of a Circuit Model */ -void CircuitLibrary::set_model_design_tech_type(const CircuitModelId& model_id, const enum e_circuit_model_design_tech& design_tech_type) { +void CircuitLibrary::set_model_design_tech_type( + const CircuitModelId& model_id, + const enum e_circuit_model_design_tech& design_tech_type) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); design_tech_types_[model_id] = design_tech_type; @@ -1298,7 +1392,8 @@ void CircuitLibrary::set_model_design_tech_type(const CircuitModelId& model_id, } /* Set the power-gated flag of a Circuit Model */ -void CircuitLibrary::set_model_is_power_gated(const CircuitModelId& model_id, const bool& is_power_gated) { +void CircuitLibrary::set_model_is_power_gated(const CircuitModelId& model_id, + const bool& is_power_gated) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); is_power_gated_[model_id] = is_power_gated; @@ -1306,31 +1401,36 @@ void CircuitLibrary::set_model_is_power_gated(const CircuitModelId& model_id, co } /* Set the device model name that is binded to a Circuit Model */ -void CircuitLibrary::set_device_model_name(const CircuitModelId& model_id, const std::string& name) { +void CircuitLibrary::set_device_model_name(const CircuitModelId& model_id, + const std::string& name) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); device_model_names_[model_id] = name; } /* Set input buffer information for the circuit model */ -void CircuitLibrary::set_model_input_buffer(const CircuitModelId& model_id, - const bool& existence, const std::string& model_name) { +void CircuitLibrary::set_model_input_buffer(const CircuitModelId& model_id, + const bool& existence, + const std::string& model_name) { /* Just call the base function and give the proper type */ set_model_buffer(model_id, INPUT, existence, model_name); return; } /* Set output buffer information for the circuit model */ -void CircuitLibrary::set_model_output_buffer(const CircuitModelId& model_id, - const bool& existence, const std::string& model_name) { +void CircuitLibrary::set_model_output_buffer(const CircuitModelId& model_id, + const bool& existence, + const std::string& model_name) { /* Just call the base function and give the proper type */ set_model_buffer(model_id, OUTPUT, existence, model_name); return; } -/* Set input buffer information for the circuit model, only applicable to LUTs! */ -void CircuitLibrary::set_model_lut_input_buffer(const CircuitModelId& model_id, - const bool& existence, const std::string& model_name) { +/* Set input buffer information for the circuit model, only applicable to LUTs! + */ +void CircuitLibrary::set_model_lut_input_buffer(const CircuitModelId& model_id, + const bool& existence, + const std::string& model_name) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* Make sure the circuit model is a LUT! */ @@ -1340,9 +1440,11 @@ void CircuitLibrary::set_model_lut_input_buffer(const CircuitModelId& model_id, return; } -/* Set input inverter information for the circuit model, only applicable to LUTs! */ -void CircuitLibrary::set_model_lut_input_inverter(const CircuitModelId& model_id, - const bool& existence, const std::string& model_name) { +/* Set input inverter information for the circuit model, only applicable to + * LUTs! */ +void CircuitLibrary::set_model_lut_input_inverter( + const CircuitModelId& model_id, const bool& existence, + const std::string& model_name) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* Make sure the circuit model is a LUT! */ @@ -1352,9 +1454,11 @@ void CircuitLibrary::set_model_lut_input_inverter(const CircuitModelId& model_id return; } -/* Set intermediate buffer information for the circuit model, only applicable to LUTs! */ -void CircuitLibrary::set_model_lut_intermediate_buffer(const CircuitModelId& model_id, - const bool& existence, const std::string& model_name) { +/* Set intermediate buffer information for the circuit model, only applicable to + * LUTs! */ +void CircuitLibrary::set_model_lut_intermediate_buffer( + const CircuitModelId& model_id, const bool& existence, + const std::string& model_name) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* Make sure the circuit model is a LUT! */ @@ -1364,17 +1468,17 @@ void CircuitLibrary::set_model_lut_intermediate_buffer(const CircuitModelId& mod return; } -void CircuitLibrary::set_model_lut_intermediate_buffer_location_map(const CircuitModelId& model_id, - const std::string& location_map) { +void CircuitLibrary::set_model_lut_intermediate_buffer_location_map( + const CircuitModelId& model_id, const std::string& location_map) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - buffer_location_maps_[model_id][LUT_INTER_BUFFER] = location_map; + buffer_location_maps_[model_id][LUT_INTER_BUFFER] = location_map; return; } - /* Set pass-gate logic information of a circuit model */ -void CircuitLibrary::set_model_pass_gate_logic(const CircuitModelId& model_id, const std::string& model_name) { +void CircuitLibrary::set_model_pass_gate_logic(const CircuitModelId& model_id, + const std::string& model_name) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); pass_gate_logic_model_names_[model_id] = model_name; @@ -1382,15 +1486,16 @@ void CircuitLibrary::set_model_pass_gate_logic(const CircuitModelId& model_id, c } /* Add a port to a circuit model */ -CircuitPortId CircuitLibrary::add_model_port(const CircuitModelId& model_id, - const enum e_circuit_model_port_type& port_type) { +CircuitPortId CircuitLibrary::add_model_port( + const CircuitModelId& model_id, + const enum e_circuit_model_port_type& port_type) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* Create a port id */ - CircuitPortId circuit_port_id = CircuitPortId(port_ids_.size()); + CircuitPortId circuit_port_id = CircuitPortId(port_ids_.size()); /* Update the id list */ port_ids_.push_back(circuit_port_id); - + /* Initialize other attributes */ port_model_ids_.push_back(model_id); port_types_.push_back(port_type); @@ -1421,7 +1526,7 @@ CircuitPortId CircuitLibrary::add_model_port(const CircuitModelId& model_id, /* For timing graphs */ port_in_edge_ids_.emplace_back(); port_out_edge_ids_.emplace_back(); - + /* Build the fast look-up for circuit model ports */ build_model_port_lookup(); @@ -1429,7 +1534,7 @@ CircuitPortId CircuitLibrary::add_model_port(const CircuitModelId& model_id, } /* Set the size for a port of a circuit model */ -void CircuitLibrary::set_port_size(const CircuitPortId& circuit_port_id, +void CircuitLibrary::set_port_size(const CircuitPortId& circuit_port_id, const size_t& port_size) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); @@ -1438,7 +1543,7 @@ void CircuitLibrary::set_port_size(const CircuitPortId& circuit_port_id, } /* Set the prefix for a port of a circuit model */ -void CircuitLibrary::set_port_prefix(const CircuitPortId& circuit_port_id, +void CircuitLibrary::set_port_prefix(const CircuitPortId& circuit_port_id, const std::string& port_prefix) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); @@ -1447,7 +1552,7 @@ void CircuitLibrary::set_port_prefix(const CircuitPortId& circuit_port_id, } /* Set the lib_name for a port of a circuit model */ -void CircuitLibrary::set_port_lib_name(const CircuitPortId& circuit_port_id, +void CircuitLibrary::set_port_lib_name(const CircuitPortId& circuit_port_id, const std::string& lib_name) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); @@ -1456,7 +1561,7 @@ void CircuitLibrary::set_port_lib_name(const CircuitPortId& circuit_port_id, } /* Set the inv_prefix for a port of a circuit model */ -void CircuitLibrary::set_port_inv_prefix(const CircuitPortId& circuit_port_id, +void CircuitLibrary::set_port_inv_prefix(const CircuitPortId& circuit_port_id, const std::string& inv_prefix) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); @@ -1465,8 +1570,8 @@ void CircuitLibrary::set_port_inv_prefix(const CircuitPortId& circuit_port_id, } /* Set the default value for a port of a circuit model */ -void CircuitLibrary::set_port_default_value(const CircuitPortId& circuit_port_id, - const size_t& default_value) { +void CircuitLibrary::set_port_default_value( + const CircuitPortId& circuit_port_id, const size_t& default_value) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); port_default_values_[circuit_port_id] = default_value; @@ -1474,7 +1579,7 @@ void CircuitLibrary::set_port_default_value(const CircuitPortId& circuit_port_id } /* Set the is_mode_select for a port of a circuit model */ -void CircuitLibrary::set_port_is_io(const CircuitPortId& circuit_port_id, +void CircuitLibrary::set_port_is_io(const CircuitPortId& circuit_port_id, const bool& is_io) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); @@ -1483,7 +1588,7 @@ void CircuitLibrary::set_port_is_io(const CircuitPortId& circuit_port_id, } /* Set the is_mode_select for a port of a circuit model */ -void CircuitLibrary::set_port_is_data_io(const CircuitPortId& circuit_port_id, +void CircuitLibrary::set_port_is_data_io(const CircuitPortId& circuit_port_id, const bool& is_data_io) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); @@ -1492,8 +1597,8 @@ void CircuitLibrary::set_port_is_data_io(const CircuitPortId& circuit_port_id, } /* Set the is_mode_select for a port of a circuit model */ -void CircuitLibrary::set_port_is_mode_select(const CircuitPortId& circuit_port_id, - const bool& is_mode_select) { +void CircuitLibrary::set_port_is_mode_select( + const CircuitPortId& circuit_port_id, const bool& is_mode_select) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); port_is_mode_select_[circuit_port_id] = is_mode_select; @@ -1501,7 +1606,7 @@ void CircuitLibrary::set_port_is_mode_select(const CircuitPortId& circuit_port_i } /* Set the is_global for a port of a circuit model */ -void CircuitLibrary::set_port_is_global(const CircuitPortId& circuit_port_id, +void CircuitLibrary::set_port_is_global(const CircuitPortId& circuit_port_id, const bool& is_global) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); @@ -1510,7 +1615,7 @@ void CircuitLibrary::set_port_is_global(const CircuitPortId& circuit_port_id, } /* Set the is_reset for a port of a circuit model */ -void CircuitLibrary::set_port_is_reset(const CircuitPortId& circuit_port_id, +void CircuitLibrary::set_port_is_reset(const CircuitPortId& circuit_port_id, const bool& is_reset) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); @@ -1519,7 +1624,7 @@ void CircuitLibrary::set_port_is_reset(const CircuitPortId& circuit_port_id, } /* Set the is_set for a port of a circuit model */ -void CircuitLibrary::set_port_is_set(const CircuitPortId& circuit_port_id, +void CircuitLibrary::set_port_is_set(const CircuitPortId& circuit_port_id, const bool& is_set) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); @@ -1528,8 +1633,8 @@ void CircuitLibrary::set_port_is_set(const CircuitPortId& circuit_port_id, } /* Set the is_config_enable for a port of a circuit model */ -void CircuitLibrary::set_port_is_config_enable(const CircuitPortId& circuit_port_id, - const bool& is_config_enable) { +void CircuitLibrary::set_port_is_config_enable( + const CircuitPortId& circuit_port_id, const bool& is_config_enable) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); port_is_config_enable_[circuit_port_id] = is_config_enable; @@ -1537,7 +1642,7 @@ void CircuitLibrary::set_port_is_config_enable(const CircuitPortId& circuit_port } /* Set the is_prog for a port of a circuit model */ -void CircuitLibrary::set_port_is_prog(const CircuitPortId& circuit_port_id, +void CircuitLibrary::set_port_is_prog(const CircuitPortId& circuit_port_id, const bool& is_prog) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); @@ -1546,8 +1651,8 @@ void CircuitLibrary::set_port_is_prog(const CircuitPortId& circuit_port_id, } /* Set the is_prog for a port of a circuit model */ -void CircuitLibrary::set_port_is_shift_register(const CircuitPortId& circuit_port_id, - const bool& is_shift_register) { +void CircuitLibrary::set_port_is_shift_register( + const CircuitPortId& circuit_port_id, const bool& is_shift_register) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); port_is_shift_register_[circuit_port_id] = is_shift_register; @@ -1555,8 +1660,8 @@ void CircuitLibrary::set_port_is_shift_register(const CircuitPortId& circuit_por } /* Set the model_name for a port of a circuit model */ -void CircuitLibrary::set_port_tri_state_model_name(const CircuitPortId& circuit_port_id, - const std::string& model_name) { +void CircuitLibrary::set_port_tri_state_model_name( + const CircuitPortId& circuit_port_id, const std::string& model_name) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); port_tri_state_model_names_[circuit_port_id] = model_name; @@ -1564,8 +1669,8 @@ void CircuitLibrary::set_port_tri_state_model_name(const CircuitPortId& circuit_ } /* Set the model_id for a port of a circuit model */ -void CircuitLibrary::set_port_tri_state_model_id(const CircuitPortId& circuit_port_id, - const CircuitModelId& port_model_id) { +void CircuitLibrary::set_port_tri_state_model_id( + const CircuitPortId& circuit_port_id, const CircuitModelId& port_model_id) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); port_tri_state_model_ids_[circuit_port_id] = port_model_id; @@ -1573,8 +1678,8 @@ void CircuitLibrary::set_port_tri_state_model_id(const CircuitPortId& circuit_po } /* Set the inv_model_name for a port of a circuit model */ -void CircuitLibrary::set_port_inv_model_name(const CircuitPortId& circuit_port_id, - const std::string& inv_model_name) { +void CircuitLibrary::set_port_inv_model_name( + const CircuitPortId& circuit_port_id, const std::string& inv_model_name) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); port_inv_model_names_[circuit_port_id] = inv_model_name; @@ -1582,7 +1687,7 @@ void CircuitLibrary::set_port_inv_model_name(const CircuitPortId& circuit_port_i } /* Set the inv_model_id for a port of a circuit model */ -void CircuitLibrary::set_port_inv_model_id(const CircuitPortId& circuit_port_id, +void CircuitLibrary::set_port_inv_model_id(const CircuitPortId& circuit_port_id, const CircuitModelId& inv_model_id) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); @@ -1591,17 +1696,18 @@ void CircuitLibrary::set_port_inv_model_id(const CircuitPortId& circuit_port_id, } /* Set the tri-state map for a port of a circuit model */ -void CircuitLibrary::set_port_tri_state_map(const CircuitPortId& circuit_port_id, - const std::string& tri_state_map) { +void CircuitLibrary::set_port_tri_state_map( + const CircuitPortId& circuit_port_id, const std::string& tri_state_map) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); port_tri_state_maps_[circuit_port_id] = tri_state_map; return; } -/* Set the LUT fracturable level for a port of a circuit model, only applicable to LUTs */ -void CircuitLibrary::set_port_lut_frac_level(const CircuitPortId& circuit_port_id, - const size_t& lut_frac_level) { +/* Set the LUT fracturable level for a port of a circuit model, only applicable + * to LUTs */ +void CircuitLibrary::set_port_lut_frac_level( + const CircuitPortId& circuit_port_id, const size_t& lut_frac_level) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); /* Make sure this is a LUT */ @@ -1610,9 +1716,10 @@ void CircuitLibrary::set_port_lut_frac_level(const CircuitPortId& circuit_port_i return; } -/* Set the LUT fracturable level for a port of a circuit model, only applicable to LUTs */ -void CircuitLibrary::set_port_is_harden_lut_port(const CircuitPortId& circuit_port_id, - const bool& is_harden_lut_port) { +/* Set the LUT fracturable level for a port of a circuit model, only applicable + * to LUTs */ +void CircuitLibrary::set_port_is_harden_lut_port( + const CircuitPortId& circuit_port_id, const bool& is_harden_lut_port) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); /* Make sure this is a LUT */ @@ -1621,9 +1728,11 @@ void CircuitLibrary::set_port_is_harden_lut_port(const CircuitPortId& circuit_po return; } -/* Set the LUT fracturable level for a port of a circuit model, only applicable to LUTs */ -void CircuitLibrary::set_port_lut_output_mask(const CircuitPortId& circuit_port_id, - const std::vector& lut_output_masks) { +/* Set the LUT fracturable level for a port of a circuit model, only applicable + * to LUTs */ +void CircuitLibrary::set_port_lut_output_mask( + const CircuitPortId& circuit_port_id, + const std::vector& lut_output_masks) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); /* Make sure this is a LUT */ @@ -1632,9 +1741,11 @@ void CircuitLibrary::set_port_lut_output_mask(const CircuitPortId& circuit_port_ return; } -/* Set the SRAM organization for a port of a circuit model, only applicable to SRAM ports */ -void CircuitLibrary::set_port_sram_orgz(const CircuitPortId& circuit_port_id, - const enum e_config_protocol_type& sram_orgz) { +/* Set the SRAM organization for a port of a circuit model, only applicable to + * SRAM ports */ +void CircuitLibrary::set_port_sram_orgz( + const CircuitPortId& circuit_port_id, + const enum e_config_protocol_type& sram_orgz) { /* validate the circuit_port_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); /* Make sure this is a SRAM port */ @@ -1646,66 +1757,71 @@ void CircuitLibrary::set_port_sram_orgz(const CircuitPortId& circuit_port_id, /* Delay information */ /* Add a delay info: * Check if the delay type is in the range of vector - * if yes, assign values + * if yes, assign values * if no, resize and assign values */ -void CircuitLibrary::add_delay_info(const CircuitModelId& model_id, - const enum e_circuit_model_delay_type& delay_type) { +void CircuitLibrary::add_delay_info( + const CircuitModelId& model_id, + const enum e_circuit_model_delay_type& delay_type) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* Check the range of vector */ if (size_t(delay_type) >= delay_types_[model_id].size()) { /* Resize */ - delay_types_[model_id].resize(size_t(delay_type) + 1); - delay_in_port_names_[model_id].resize(size_t(delay_type) + 1); - delay_out_port_names_[model_id].resize(size_t(delay_type) + 1); - delay_values_[model_id].resize(size_t(delay_type) + 1); + delay_types_[model_id].resize(size_t(delay_type) + 1); + delay_in_port_names_[model_id].resize(size_t(delay_type) + 1); + delay_out_port_names_[model_id].resize(size_t(delay_type) + 1); + delay_values_[model_id].resize(size_t(delay_type) + 1); } - delay_types_[model_id][size_t(delay_type)] = delay_type; + delay_types_[model_id][size_t(delay_type)] = delay_type; return; } -void CircuitLibrary::set_delay_in_port_names(const CircuitModelId& model_id, - const enum e_circuit_model_delay_type& delay_type, - const std::string& in_port_names) { +void CircuitLibrary::set_delay_in_port_names( + const CircuitModelId& model_id, + const enum e_circuit_model_delay_type& delay_type, + const std::string& in_port_names) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* Validate delay_type */ VTR_ASSERT(valid_delay_type(model_id, delay_type)); - delay_in_port_names_[model_id][size_t(delay_type)] = in_port_names; - return; + delay_in_port_names_[model_id][size_t(delay_type)] = in_port_names; + return; } -void CircuitLibrary::set_delay_out_port_names(const CircuitModelId& model_id, - const enum e_circuit_model_delay_type& delay_type, - const std::string& out_port_names) { +void CircuitLibrary::set_delay_out_port_names( + const CircuitModelId& model_id, + const enum e_circuit_model_delay_type& delay_type, + const std::string& out_port_names) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* Validate delay_type */ VTR_ASSERT(valid_delay_type(model_id, delay_type)); - delay_out_port_names_[model_id][size_t(delay_type)] = out_port_names; - return; + delay_out_port_names_[model_id][size_t(delay_type)] = out_port_names; + return; } -void CircuitLibrary::set_delay_values(const CircuitModelId& model_id, - const enum e_circuit_model_delay_type& delay_type, - const std::string& delay_values) { +void CircuitLibrary::set_delay_values( + const CircuitModelId& model_id, + const enum e_circuit_model_delay_type& delay_type, + const std::string& delay_values) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* Validate delay_type */ VTR_ASSERT(valid_delay_type(model_id, delay_type)); - delay_values_[model_id][size_t(delay_type)] = delay_values; - return; + delay_values_[model_id][size_t(delay_type)] = delay_values; + return; } /* Buffer/Inverter-related parameters */ -void CircuitLibrary::set_buffer_type(const CircuitModelId& model_id, - const enum e_circuit_model_buffer_type& buffer_type) { +void CircuitLibrary::set_buffer_type( + const CircuitModelId& model_id, + const enum e_circuit_model_buffer_type& buffer_type) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be BUFFER or INVERTER */ VTR_ASSERT(CIRCUIT_MODEL_INVBUF == model_type(model_id)); - buffer_types_[model_id] = buffer_type; + buffer_types_[model_id] = buffer_type; return; } @@ -1715,7 +1831,7 @@ void CircuitLibrary::set_buffer_size(const CircuitModelId& model_id, VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be BUFFER or INVERTER */ VTR_ASSERT(CIRCUIT_MODEL_INVBUF == model_type(model_id)); - buffer_sizes_[model_id] = buffer_size; + buffer_sizes_[model_id] = buffer_size; return; } @@ -1725,7 +1841,7 @@ void CircuitLibrary::set_buffer_num_levels(const CircuitModelId& model_id, VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be BUFFER or INVERTER */ VTR_ASSERT(CIRCUIT_MODEL_INVBUF == model_type(model_id)); - buffer_num_levels_[model_id] = num_levels; + buffer_num_levels_[model_id] = num_levels; return; } @@ -1735,50 +1851,52 @@ void CircuitLibrary::set_buffer_f_per_stage(const CircuitModelId& model_id, VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be BUFFER or INVERTER */ VTR_ASSERT(CIRCUIT_MODEL_INVBUF == model_type(model_id)); - buffer_f_per_stage_[model_id] = f_per_stage; + buffer_f_per_stage_[model_id] = f_per_stage; return; } /* Pass-gate-related parameters */ -void CircuitLibrary::set_pass_gate_logic_type(const CircuitModelId& model_id, - const enum e_circuit_model_pass_gate_logic_type& pass_gate_logic_type) { +void CircuitLibrary::set_pass_gate_logic_type( + const CircuitModelId& model_id, + const enum e_circuit_model_pass_gate_logic_type& pass_gate_logic_type) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be BUFFER or INVERTER */ VTR_ASSERT(CIRCUIT_MODEL_PASSGATE == model_type(model_id)); - pass_gate_logic_types_[model_id] = pass_gate_logic_type; + pass_gate_logic_types_[model_id] = pass_gate_logic_type; return; } -void CircuitLibrary::set_pass_gate_logic_nmos_size(const CircuitModelId& model_id, - const float& nmos_size) { +void CircuitLibrary::set_pass_gate_logic_nmos_size( + const CircuitModelId& model_id, const float& nmos_size) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be BUFFER or INVERTER */ VTR_ASSERT(CIRCUIT_MODEL_PASSGATE == model_type(model_id)); - pass_gate_logic_sizes_[model_id].set_x(nmos_size); + pass_gate_logic_sizes_[model_id].set_x(nmos_size); return; } -void CircuitLibrary::set_pass_gate_logic_pmos_size(const CircuitModelId& model_id, - const float& pmos_size) { +void CircuitLibrary::set_pass_gate_logic_pmos_size( + const CircuitModelId& model_id, const float& pmos_size) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be BUFFER or INVERTER */ VTR_ASSERT(CIRCUIT_MODEL_PASSGATE == model_type(model_id)); - pass_gate_logic_sizes_[model_id].set_y(pmos_size); + pass_gate_logic_sizes_[model_id].set_y(pmos_size); return; } /* Multiplexer-related parameters */ -void CircuitLibrary::set_mux_structure(const CircuitModelId& model_id, - const enum e_circuit_model_structure& mux_structure) { +void CircuitLibrary::set_mux_structure( + const CircuitModelId& model_id, + const enum e_circuit_model_structure& mux_structure) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be MUX or LUT */ - VTR_ASSERT( (CIRCUIT_MODEL_MUX == model_type(model_id)) - || (CIRCUIT_MODEL_LUT == model_type(model_id)) ); - mux_structure_[model_id] = mux_structure; + VTR_ASSERT((CIRCUIT_MODEL_MUX == model_type(model_id)) || + (CIRCUIT_MODEL_LUT == model_type(model_id))); + mux_structure_[model_id] = mux_structure; return; } @@ -1787,22 +1905,22 @@ void CircuitLibrary::set_mux_num_levels(const CircuitModelId& model_id, /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be MUX or LUT */ - VTR_ASSERT( (CIRCUIT_MODEL_MUX == model_type(model_id)) - || (CIRCUIT_MODEL_LUT == model_type(model_id)) ); - mux_num_levels_[model_id] = num_levels; + VTR_ASSERT((CIRCUIT_MODEL_MUX == model_type(model_id)) || + (CIRCUIT_MODEL_LUT == model_type(model_id))); + mux_num_levels_[model_id] = num_levels; return; } -void CircuitLibrary::set_mux_const_input_value(const CircuitModelId& model_id, - const size_t& const_input_value) { +void CircuitLibrary::set_mux_const_input_value( + const CircuitModelId& model_id, const size_t& const_input_value) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be MUX or LUT */ - VTR_ASSERT( (CIRCUIT_MODEL_MUX == model_type(model_id)) - || (CIRCUIT_MODEL_LUT == model_type(model_id)) ); + VTR_ASSERT((CIRCUIT_MODEL_MUX == model_type(model_id)) || + (CIRCUIT_MODEL_LUT == model_type(model_id))); /* validate the const input values */ - VTR_ASSERT( valid_mux_const_input_value(const_input_value) ); - mux_const_input_values_[model_id] = const_input_value; + VTR_ASSERT(valid_mux_const_input_value(const_input_value)); + mux_const_input_values_[model_id] = const_input_value; return; } @@ -1811,20 +1929,20 @@ void CircuitLibrary::set_mux_use_local_encoder(const CircuitModelId& model_id, /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be MUX or LUT */ - VTR_ASSERT( (CIRCUIT_MODEL_MUX == model_type(model_id)) - || (CIRCUIT_MODEL_LUT == model_type(model_id)) ); - mux_use_local_encoder_[model_id] = use_local_encoder; + VTR_ASSERT((CIRCUIT_MODEL_MUX == model_type(model_id)) || + (CIRCUIT_MODEL_LUT == model_type(model_id))); + mux_use_local_encoder_[model_id] = use_local_encoder; return; } -void CircuitLibrary::set_mux_use_advanced_rram_design(const CircuitModelId& model_id, - const bool& use_advanced_rram_design) { +void CircuitLibrary::set_mux_use_advanced_rram_design( + const CircuitModelId& model_id, const bool& use_advanced_rram_design) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be MUX or LUT */ - VTR_ASSERT( (CIRCUIT_MODEL_MUX == model_type(model_id)) - || (CIRCUIT_MODEL_LUT == model_type(model_id)) ); - mux_use_advanced_rram_design_[model_id] = use_advanced_rram_design; + VTR_ASSERT((CIRCUIT_MODEL_MUX == model_type(model_id)) || + (CIRCUIT_MODEL_LUT == model_type(model_id))); + mux_use_advanced_rram_design_[model_id] = use_advanced_rram_design; return; } @@ -1835,22 +1953,22 @@ void CircuitLibrary::set_lut_is_fracturable(const CircuitModelId& model_id, VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be LUT */ VTR_ASSERT(CIRCUIT_MODEL_LUT == model_type(model_id)); - lut_is_fracturable_[model_id] = is_fracturable; + lut_is_fracturable_[model_id] = is_fracturable; return; } /* Gate-related parameters */ -void CircuitLibrary::set_gate_type(const CircuitModelId& model_id, - const enum e_circuit_model_gate_type& gate_type) { +void CircuitLibrary::set_gate_type( + const CircuitModelId& model_id, + const enum e_circuit_model_gate_type& gate_type) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be GATE */ VTR_ASSERT(CIRCUIT_MODEL_GATE == model_type(model_id)); - gate_types_[model_id] = gate_type; + gate_types_[model_id] = gate_type; return; } - /* RRAM-related design technology information */ void CircuitLibrary::set_rram_rlrs(const CircuitModelId& model_id, const float& rlrs) { @@ -1858,7 +1976,7 @@ void CircuitLibrary::set_rram_rlrs(const CircuitModelId& model_id, VTR_ASSERT(valid_model_id(model_id)); /* validate that the design_tech of this model should be RRAM */ VTR_ASSERT(CIRCUIT_MODEL_DESIGN_RRAM == design_tech_type(model_id)); - rram_res_[model_id].set_x(rlrs); + rram_res_[model_id].set_x(rlrs); return; } @@ -1868,7 +1986,7 @@ void CircuitLibrary::set_rram_rhrs(const CircuitModelId& model_id, VTR_ASSERT(valid_model_id(model_id)); /* validate that the design_tech of this model should be RRAM */ VTR_ASSERT(CIRCUIT_MODEL_DESIGN_RRAM == design_tech_type(model_id)); - rram_res_[model_id].set_y(rhrs); + rram_res_[model_id].set_y(rhrs); return; } @@ -1878,7 +1996,7 @@ void CircuitLibrary::set_rram_wprog_set_nmos(const CircuitModelId& model_id, VTR_ASSERT(valid_model_id(model_id)); /* validate that the design_tech of this model should be RRAM */ VTR_ASSERT(CIRCUIT_MODEL_DESIGN_RRAM == design_tech_type(model_id)); - wprog_set_[model_id].set_x(wprog_set_nmos); + wprog_set_[model_id].set_x(wprog_set_nmos); return; } @@ -1888,7 +2006,7 @@ void CircuitLibrary::set_rram_wprog_set_pmos(const CircuitModelId& model_id, VTR_ASSERT(valid_model_id(model_id)); /* validate that the design_tech of this model should be RRAM */ VTR_ASSERT(CIRCUIT_MODEL_DESIGN_RRAM == design_tech_type(model_id)); - wprog_set_[model_id].set_y(wprog_set_pmos); + wprog_set_[model_id].set_y(wprog_set_pmos); return; } @@ -1898,7 +2016,7 @@ void CircuitLibrary::set_rram_wprog_reset_nmos(const CircuitModelId& model_id, VTR_ASSERT(valid_model_id(model_id)); /* validate that the design_tech of this model should be RRAM */ VTR_ASSERT(CIRCUIT_MODEL_DESIGN_RRAM == design_tech_type(model_id)); - wprog_reset_[model_id].set_x(wprog_reset_nmos); + wprog_reset_[model_id].set_x(wprog_reset_nmos); return; } @@ -1908,7 +2026,7 @@ void CircuitLibrary::set_rram_wprog_reset_pmos(const CircuitModelId& model_id, VTR_ASSERT(valid_model_id(model_id)); /* validate that the design_tech of this model should be RRAM */ VTR_ASSERT(CIRCUIT_MODEL_DESIGN_RRAM == design_tech_type(model_id)); - wprog_reset_[model_id].set_y(wprog_reset_pmos); + wprog_reset_[model_id].set_y(wprog_reset_pmos); return; } @@ -1918,9 +2036,9 @@ void CircuitLibrary::set_wire_type(const CircuitModelId& model_id, /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be WIRE or CHAN_WIRE */ - VTR_ASSERT( (CIRCUIT_MODEL_WIRE == model_type(model_id)) - || (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id)) ); - wire_types_[model_id] = wire_type; + VTR_ASSERT((CIRCUIT_MODEL_WIRE == model_type(model_id)) || + (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id))); + wire_types_[model_id] = wire_type; return; } @@ -1929,9 +2047,9 @@ void CircuitLibrary::set_wire_r(const CircuitModelId& model_id, /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be WIRE or CHAN_WIRE */ - VTR_ASSERT( (CIRCUIT_MODEL_WIRE == model_type(model_id)) - || (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id)) ); - wire_rc_[model_id].set_x(r_val); + VTR_ASSERT((CIRCUIT_MODEL_WIRE == model_type(model_id)) || + (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id))); + wire_rc_[model_id].set_x(r_val); return; } @@ -1940,9 +2058,9 @@ void CircuitLibrary::set_wire_c(const CircuitModelId& model_id, /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be WIRE or CHAN_WIRE */ - VTR_ASSERT( (CIRCUIT_MODEL_WIRE == model_type(model_id)) - || (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id)) ); - wire_rc_[model_id].set_y(c_val); + VTR_ASSERT((CIRCUIT_MODEL_WIRE == model_type(model_id)) || + (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id))); + wire_rc_[model_id].set_y(c_val); return; } @@ -1951,61 +2069,68 @@ void CircuitLibrary::set_wire_num_level(const CircuitModelId& model_id, /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be WIRE or CHAN_WIRE */ - VTR_ASSERT( (CIRCUIT_MODEL_WIRE == model_type(model_id)) - || (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id)) ); - wire_num_levels_[model_id] = num_level; + VTR_ASSERT((CIRCUIT_MODEL_WIRE == model_type(model_id)) || + (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id))); + wire_num_levels_[model_id] = num_level; return; } /************************************************************************ - * Internal Mutators: builders and linkers + * Internal Mutators: builders and linkers ***********************************************************************/ -/* Set the information for a buffer +/* Set the information for a buffer * For a buffer type, we check if it is in the range of vector * If yes, just assign values - * If no, resize the vector and then assign values + * If no, resize the vector and then assign values */ -void CircuitLibrary::set_model_buffer(const CircuitModelId& model_id, const enum e_buffer_type buffer_type, - const bool& existence, const std::string& model_name) { +void CircuitLibrary::set_model_buffer(const CircuitModelId& model_id, + const enum e_buffer_type buffer_type, + const bool& existence, + const std::string& model_name) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* Check the range of vector */ if (size_t(buffer_type) >= buffer_existence_[model_id].size()) { /* Resize and assign values */ - buffer_existence_[model_id].resize(size_t(buffer_type) + 1); - buffer_model_names_[model_id].resize(size_t(buffer_type) + 1); - buffer_model_ids_[model_id].resize(size_t(buffer_type) + 1); - buffer_location_maps_[model_id].resize(size_t(buffer_type) + 1); + buffer_existence_[model_id].resize(size_t(buffer_type) + 1); + buffer_model_names_[model_id].resize(size_t(buffer_type) + 1); + buffer_model_ids_[model_id].resize(size_t(buffer_type) + 1); + buffer_location_maps_[model_id].resize(size_t(buffer_type) + 1); } /* Now we are in the range, assign values */ buffer_existence_[model_id][size_t(buffer_type)] = existence; buffer_model_names_[model_id][size_t(buffer_type)] = model_name; - buffer_model_ids_[model_id][size_t(buffer_type)] = CircuitModelId::INVALID(); /* Set an OPEN id here, which will be linked later */ + buffer_model_ids_[model_id][size_t(buffer_type)] = + CircuitModelId::INVALID(); /* Set an OPEN id here, which will be linked + later */ return; } /* Link the model_id for each port of a circuit model. - * We search the inv_model_name in the CircuitLibrary and + * We search the inv_model_name in the CircuitLibrary and * configure the port inv_model_id */ -void CircuitLibrary::link_port_tri_state_model() { - /* Walk through each ports, get the port id and find the circuit model id by name */ +void CircuitLibrary::link_port_tri_state_model() { + /* Walk through each ports, get the port id and find the circuit model id by + * name */ for (auto& port_id : ports()) { /* Bypass empty name */ if (true == port_tri_state_model_names_[port_id].empty()) { continue; } - port_tri_state_model_ids_[port_id] = model(port_tri_state_model_names_[port_id]); + port_tri_state_model_ids_[port_id] = + model(port_tri_state_model_names_[port_id]); } return; -} +} /* Link the inv_model_id for each port of a circuit model. - * We search the inv_model_name in the CircuitLibrary and + * We search the inv_model_name in the CircuitLibrary and * configure the port inv_model_id */ -void CircuitLibrary::link_port_inv_model() { - /* Walk through each ports, get the port id and find the circuit model id by name */ +void CircuitLibrary::link_port_inv_model() { + /* Walk through each ports, get the port id and find the circuit model id by + * name */ for (auto& port_id : ports()) { /* Bypass empty name */ if (true == port_inv_model_names_[port_id].empty()) { @@ -2014,47 +2139,53 @@ void CircuitLibrary::link_port_inv_model() { port_inv_model_ids_[port_id] = model(port_inv_model_names_[port_id]); } return; -} +} /* Link the buffer_model - * We search the buffer_model_name in the CircuitLibrary and + * We search the buffer_model_name in the CircuitLibrary and * configure the buffer_model_id */ -void CircuitLibrary::link_buffer_model(const CircuitModelId& model_id) { +void CircuitLibrary::link_buffer_model(const CircuitModelId& model_id) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* Get the circuit model id by name, skip those with empty names*/ - for (size_t buffer_id = 0; buffer_id < buffer_model_names_[model_id].size(); ++buffer_id) { + for (size_t buffer_id = 0; buffer_id < buffer_model_names_[model_id].size(); + ++buffer_id) { if (true == buffer_model_names_[model_id][buffer_id].empty()) { continue; } - buffer_model_ids_[model_id][buffer_id] = model(buffer_model_names_[model_id][buffer_id]); + buffer_model_ids_[model_id][buffer_id] = + model(buffer_model_names_[model_id][buffer_id]); } return; -} +} /* Link the buffer_model - * We search the buffer_model_name in the CircuitLibrary and + * We search the buffer_model_name in the CircuitLibrary and * configure the buffer_model_id */ -void CircuitLibrary::link_pass_gate_logic_model(const CircuitModelId& model_id) { +void CircuitLibrary::link_pass_gate_logic_model( + const CircuitModelId& model_id) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* Get the circuit model id by name, skip those with empty names*/ if (true == pass_gate_logic_model_names_[model_id].empty()) { return; } - pass_gate_logic_model_ids_[model_id] = model(pass_gate_logic_model_names_[model_id]); + pass_gate_logic_model_ids_[model_id] = + model(pass_gate_logic_model_names_[model_id]); return; } /* Find if a model is already in the submodel list */ -bool CircuitLibrary::is_unique_submodel(const CircuitModelId& model_id, const CircuitModelId& submodel_id) { +bool CircuitLibrary::is_unique_submodel(const CircuitModelId& model_id, + const CircuitModelId& submodel_id) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); VTR_ASSERT(valid_model_id(submodel_id)); - - std::vector::iterator it = std::find(sub_models_[model_id].begin(), sub_models_[model_id].end(), submodel_id); + + std::vector::iterator it = std::find( + sub_models_[model_id].begin(), sub_models_[model_id].end(), submodel_id); if (it == sub_models_[model_id].end()) { return true; } @@ -2062,10 +2193,10 @@ bool CircuitLibrary::is_unique_submodel(const CircuitModelId& model_id, const Ci } /* Build the sub module list for each circuit model, - * Find the linked circuit model id in + * Find the linked circuit model id in * pass-gate, buffers, ports */ void CircuitLibrary::build_submodels() { - for (const auto& model: models()) { + for (const auto& model : models()) { /* Make sure a clean start */ sub_models_[model].clear(); @@ -2077,7 +2208,7 @@ void CircuitLibrary::build_submodels() { /* Skip any invalid ids */ if (CircuitModelId::INVALID() == buffer_model) { continue; - } + } candidates.push_back(buffer_model); } @@ -2085,20 +2216,20 @@ void CircuitLibrary::build_submodels() { /* Skip any invalid ids */ if (CircuitModelId::INVALID() != pass_gate_logic_model_ids_[model]) { candidates.push_back(pass_gate_logic_model_ids_[model]); - } + } /* Find each port circuit models */ - for (const auto& port: model_ports(model)) { + for (const auto& port : model_ports(model)) { /* Find tri-state circuit models */ /* Skip any invalid ids */ if (CircuitModelId::INVALID() != port_tri_state_model_ids_[port]) { candidates.push_back(port_tri_state_model_ids_[port]); - } + } /* Find inv circuit models */ /* Skip any invalid ids */ if (CircuitModelId::INVALID() != port_inv_model_ids_[port]) { candidates.push_back(port_inv_model_ids_[port]); - } + } } /* Build a unique list */ @@ -2116,8 +2247,8 @@ void CircuitLibrary::build_model_timing_graph(const CircuitModelId& model_id) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - /* Now we start allocating a timing graph - * Add outgoing edges for each input pin of the circuit model + /* Now we start allocating a timing graph + * Add outgoing edges for each input pin of the circuit model */ for (const auto& from_port_id : model_input_ports(model_id)) { /* Add edges for each input pin */ @@ -2139,19 +2270,19 @@ void CircuitLibrary::build_model_timing_graph(const CircuitModelId& model_id) { } /************************************************************************ - * Public Mutators: builders and linkers + * Public Mutators: builders and linkers ***********************************************************************/ /* Build the links for attributes of each model by searching the model_names */ void CircuitLibrary::build_model_links() { /* Walk through each circuit model, build links one by one */ for (auto& model_id : models()) { /* Build links for buffers, pass-gates model */ - link_buffer_model(model_id); - link_pass_gate_logic_model(model_id); + link_buffer_model(model_id); + link_pass_gate_logic_model(model_id); } /* Build links for ports */ - link_port_tri_state_model(); - link_port_inv_model(); + link_port_tri_state_model(); + link_port_inv_model(); /* Build submodels */ build_submodels(); @@ -2165,7 +2296,7 @@ void CircuitLibrary::build_timing_graphs() { invalidate_model_timing_graph(); /* Walk through each circuit model, build timing graph one by one */ for (auto& model_id : models()) { - build_model_timing_graph(model_id); + build_model_timing_graph(model_id); /* Annotate timing information */ set_timing_graph_delays(model_id); } @@ -2176,34 +2307,38 @@ void CircuitLibrary::build_timing_graphs() { void CircuitLibrary::auto_detect_default_models() { /* Go through the model fast look-up */ for (const auto& curr_type_models : model_lookup_) { - if ( (1 == curr_type_models.size()) - && (false == model_is_default(curr_type_models[0]))) { + if ((1 == curr_type_models.size()) && + (false == model_is_default(curr_type_models[0]))) { /* This is the only model in this type, * it is safe to set it to be default * Give a warning for users */ set_model_is_default(curr_type_models[0], true); - VTR_LOG_WARN("Automatically set circuit model '%s' to be default in its type.\n", - model_name(curr_type_models[0]).c_str()); + VTR_LOG_WARN( + "Automatically set circuit model '%s' to be default in its type.\n", + model_name(curr_type_models[0]).c_str()); } } } /************************************************************************ - * Internal mutators: build timing graphs + * Internal mutators: build timing graphs ***********************************************************************/ -/* Add an edge between two pins of two ports, and assign an default timing value */ -void CircuitLibrary::add_edge(const CircuitModelId& model_id, - const CircuitPortId& from_port, const size_t& from_pin, - const CircuitPortId& to_port, const size_t& to_pin) { +/* Add an edge between two pins of two ports, and assign an default timing value + */ +void CircuitLibrary::add_edge(const CircuitModelId& model_id, + const CircuitPortId& from_port, + const size_t& from_pin, + const CircuitPortId& to_port, + const size_t& to_pin) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - /* Create an edge in the edge id list */ + /* Create an edge in the edge id list */ CircuitEdgeId edge_id = CircuitEdgeId(edge_ids_.size()); /* Expand the edge list */ edge_ids_.push_back(edge_id); - + /* Initialize other attributes */ edge_parent_model_ids_.push_back(model_id); @@ -2236,14 +2371,13 @@ void CircuitLibrary::add_edge(const CircuitModelId& model_id, return; } -void CircuitLibrary::set_edge_delay(const CircuitModelId& model_id, - const CircuitEdgeId& circuit_edge_id, - const enum e_circuit_model_delay_type& delay_type, - const float& delay_value) { +void CircuitLibrary::set_edge_delay( + const CircuitModelId& model_id, const CircuitEdgeId& circuit_edge_id, + const enum e_circuit_model_delay_type& delay_type, const float& delay_value) { /* validate the circuit_edge_id */ VTR_ASSERT(valid_circuit_edge_id(circuit_edge_id)); VTR_ASSERT(valid_delay_type(model_id, delay_type)); - + edge_timing_info_[circuit_edge_id][size_t(delay_type)] = delay_value; return; } @@ -2256,12 +2390,13 @@ void CircuitLibrary::set_timing_graph_delays(const CircuitModelId& model_id) { for (const auto& delay_type : delay_types_[model_id]) { /* Parse the input port names and output names. * We will store the parsing results in vectors: - * 1. vector for port ids for each port name + * 1. vector for port ids for each port name * 2. vector for pin ids for each port name */ /* Parse the string for inputs */ - openfpga::MultiPortParser input_port_parser(delay_in_port_names_[model_id][size_t(delay_type)]); + openfpga::MultiPortParser input_port_parser( + delay_in_port_names_[model_id][size_t(delay_type)]); std::vector input_ports = input_port_parser.ports(); std::vector input_port_ids; std::vector input_pin_ids; @@ -2273,7 +2408,8 @@ void CircuitLibrary::set_timing_graph_delays(const CircuitModelId& model_id) { VTR_ASSERT(CircuitPortId::INVALID() != port_id); if (0 == port_info.get_width()) { /* we need to configure the port width if it is zero. - * This means that parser find some compact port defintion such as + * This means that parser find some compact port defintion such as + * */ size_t port_width = port_size(port_id); port_info.set_width(port_width); @@ -2290,7 +2426,8 @@ void CircuitLibrary::set_timing_graph_delays(const CircuitModelId& model_id) { } /* Parse the string for outputs */ - openfpga::MultiPortParser output_port_parser(delay_out_port_names_[model_id][size_t(delay_type)]); + openfpga::MultiPortParser output_port_parser( + delay_out_port_names_[model_id][size_t(delay_type)]); std::vector output_ports = output_port_parser.ports(); std::vector output_port_ids; std::vector output_pin_ids; @@ -2302,7 +2439,8 @@ void CircuitLibrary::set_timing_graph_delays(const CircuitModelId& model_id) { VTR_ASSERT(CircuitPortId::INVALID() != port_id); if (0 == port_info.get_width()) { /* we need to configure the port width if it is zero. - * This means that parser find some compact port defintion such as + * This means that parser find some compact port defintion such as + * */ size_t port_width = port_size(port_id); port_info.set_width(port_width); @@ -2319,7 +2457,8 @@ void CircuitLibrary::set_timing_graph_delays(const CircuitModelId& model_id) { } /* Parse the delay matrix */ - openfpga::PortDelayParser port_delay_parser(delay_values_[model_id][size_t(delay_type)]); + openfpga::PortDelayParser port_delay_parser( + delay_values_[model_id][size_t(delay_type)]); /* Make sure the delay matrix size matches */ VTR_ASSERT(port_delay_parser.height() == output_port_ids.size()); @@ -2332,11 +2471,10 @@ void CircuitLibrary::set_timing_graph_delays(const CircuitModelId& model_id) { for (size_t j = 0; j < port_delay_parser.width(); ++j) { float delay_value = port_delay_parser.delay(i, j); CircuitEdgeId edge_id = edge(input_port_ids[j], input_pin_ids[j], - output_port_ids[i], output_pin_ids[i]); + output_port_ids[i], output_pin_ids[i]); /* make sure we have an valid edge_id */ VTR_ASSERT(true == valid_circuit_edge_id(edge_id)); - set_edge_delay(model_id, edge_id, - delay_type, delay_value); + set_edge_delay(model_id, edge_id, delay_type, delay_value); } } } @@ -2344,7 +2482,7 @@ void CircuitLibrary::set_timing_graph_delays(const CircuitModelId& model_id) { } /************************************************************************ - * Internal mutators: build fast look-ups + * Internal mutators: build fast look-ups ***********************************************************************/ /* Build fast look-up for circuit models */ void CircuitLibrary::build_model_lookup() { @@ -2371,7 +2509,8 @@ void CircuitLibrary::build_model_lookup() { if (false == model_is_default_[type[id]]) { continue; } - /* Once we find a default model, swap with the first element and finish the loop */ + /* Once we find a default model, swap with the first element and finish + * the loop */ std::swap(type[0], type[id]); break; } @@ -2398,48 +2537,58 @@ void CircuitLibrary::build_model_port_lookup() { } /************************************************************************ - * Internal invalidators/validators + * Internal invalidators/validators ***********************************************************************/ /* Validators */ bool CircuitLibrary::valid_model_id(const CircuitModelId& model_id) const { - return ( size_t(model_id) < model_ids_.size() ) && ( model_id == model_ids_[model_id] ); + return (size_t(model_id) < model_ids_.size()) && + (model_id == model_ids_[model_id]); } -bool CircuitLibrary::valid_circuit_port_id(const CircuitPortId& circuit_port_id) const { - return ( size_t(circuit_port_id) < port_ids_.size() ) && ( circuit_port_id == port_ids_[circuit_port_id] ); +bool CircuitLibrary::valid_circuit_port_id( + const CircuitPortId& circuit_port_id) const { + return (size_t(circuit_port_id) < port_ids_.size()) && + (circuit_port_id == port_ids_[circuit_port_id]); } -bool CircuitLibrary::valid_circuit_pin_id(const CircuitPortId& circuit_port_id, const size_t& pin_id) const { +bool CircuitLibrary::valid_circuit_pin_id(const CircuitPortId& circuit_port_id, + const size_t& pin_id) const { /* validate the model_id */ VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); - return ( size_t(pin_id) < port_size(circuit_port_id) ); + return (size_t(pin_id) < port_size(circuit_port_id)); } bool CircuitLibrary::valid_edge_id(const CircuitEdgeId& edge_id) const { /* validate the model_id */ - return ( size_t(edge_id) < edge_ids_.size() ) && ( edge_id == edge_ids_[edge_id] ); + return (size_t(edge_id) < edge_ids_.size()) && + (edge_id == edge_ids_[edge_id]); } -bool CircuitLibrary::valid_delay_type(const CircuitModelId& model_id, const enum e_circuit_model_delay_type& delay_type) const { +bool CircuitLibrary::valid_delay_type( + const CircuitModelId& model_id, + const enum e_circuit_model_delay_type& delay_type) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return ( size_t(delay_type) < delay_types_[model_id].size() ) && ( delay_type == delay_types_[model_id][size_t(delay_type)] ); + return (size_t(delay_type) < delay_types_[model_id].size()) && + (delay_type == delay_types_[model_id][size_t(delay_type)]); } -bool CircuitLibrary::valid_circuit_edge_id(const CircuitEdgeId& circuit_edge_id) const { - return ( size_t(circuit_edge_id) < edge_ids_.size() ) && ( circuit_edge_id == edge_ids_[circuit_edge_id] ); +bool CircuitLibrary::valid_circuit_edge_id( + const CircuitEdgeId& circuit_edge_id) const { + return (size_t(circuit_edge_id) < edge_ids_.size()) && + (circuit_edge_id == edge_ids_[circuit_edge_id]); } -/* Validate the value of constant input - * A -1 value for the const values means there is no const inputs - * A 0 value for the const values means it is logic 0 - * A 1 value for the const values means it is logic 1 - * Others are invalid +/* Validate the value of constant input + * A -1 value for the const values means there is no const inputs + * A 0 value for the const values means it is logic 0 + * A 1 value for the const values means it is logic 1 + * Others are invalid */ -bool CircuitLibrary::valid_mux_const_input_value(const size_t& const_input_value) const { - return ( (size_t(-1) == const_input_value) - || (0 == const_input_value) - || (1 == const_input_value) ); +bool CircuitLibrary::valid_mux_const_input_value( + const size_t& const_input_value) const { + return ((size_t(-1) == const_input_value) || (0 == const_input_value) || + (1 == const_input_value)); } /* Invalidators */ @@ -2462,7 +2611,7 @@ void CircuitLibrary::invalidate_model_timing_graph() { for (const auto& port_id : ports()) { port_in_edge_ids_[port_id].clear(); port_out_edge_ids_[port_id].clear(); - } + } edge_src_port_ids_.clear(); edge_src_pin_ids_.clear(); @@ -2475,5 +2624,5 @@ void CircuitLibrary::invalidate_model_timing_graph() { } /************************************************************************ - * End of file : circuit_library.cpp + * End of file : circuit_library.cpp ***********************************************************************/ diff --git a/libs/libarchopenfpga/src/circuit_library.h b/libs/libarchopenfpga/src/circuit_library.h index ffd2f1661..30caef09c 100644 --- a/libs/libarchopenfpga/src/circuit_library.h +++ b/libs/libarchopenfpga/src/circuit_library.h @@ -1,27 +1,24 @@ /* IMPORTANT: - * The following preprocessing flags are added to - * avoid compilation error when this headers are included in more than 1 times + * The following preprocessing flags are added to + * avoid compilation error when this headers are included in more than 1 times */ #ifndef CIRCUIT_LIBRARY_H #define CIRCUIT_LIBRARY_H /* - * Notes in include header files in a head file - * Only include the neccessary header files + * Notes in include header files in a head file + * Only include the neccessary header files * that is required by the data types in the function/class declarations! */ /* Header files should be included in a sequence */ /* Standard header files required go first */ #include -#include "vtr_geometry.h" - -#include "vtr_vector.h" -#include "vtr_range.h" - -#include "circuit_types.h" - #include "circuit_library_fwd.h" +#include "circuit_types.h" +#include "vtr_geometry.h" +#include "vtr_range.h" +#include "vtr_vector.h" /************************************************************************ * The class CircuitLibrary is a critical data structure for OpenFPGA @@ -39,590 +36,722 @@ * * It includes the following data: * - * Fundamental Information + * Fundamental Information * ----------------------- * 1. model_ids_ : unique identifier to find a circuit model - * Use a strong id for search, to avoid illegal type casting - * 2. model_types_: types of the circuit model, see details in the definition of enum e_circuit_model_type - * 3. model_names_: unique names for each circuit models. - * It should be the same as user-defined Verilog modules, if it is not auto-generated - * 4. model_prefix_: the prefix of a circuit model when it is instanciated - * 5. verilog_netlist_: specified path and file name of Verilog netlist if a circuit model is not auto-generated - * 6. spice_netlist_: specified path and file name of CIRCUIT netlist if a circuit model is not auto-generated - * 7. is_default_: indicate if the circuit model is the default one among all those in the same type - * 8. sub_models_: the sub circuit models included by a circuit model. It is a collection of unique circuit model ids - * found in the CircuitModelId of pass-gate/buffers/port-related circuit models. + * Use a strong id for search, to avoid illegal type + *casting + * 2. model_types_: types of the circuit model, see details in the definition of + *enum e_circuit_model_type + * 3. model_names_: unique names for each circuit models. + * It should be the same as user-defined Verilog + *modules, if it is not auto-generated + * 4. model_prefix_: the prefix of a circuit model when it is instanciated + * 5. verilog_netlist_: specified path and file name of Verilog netlist if a + *circuit model is not auto-generated + * 6. spice_netlist_: specified path and file name of CIRCUIT netlist if a + *circuit model is not auto-generated + * 7. is_default_: indicate if the circuit model is the default one among all + *those in the same type + * 8. sub_models_: the sub circuit models included by a circuit model. It is a + *collection of unique circuit model ids found in the CircuitModelId of + *pass-gate/buffers/port-related circuit models. * * ------ Fast look-ups----- - * 1. model_lookup_: A multi-dimension vector to provide fast look-up on circuit models for users - * It classifies CircuitModelIds by their type and set the default model in the first element for each type. - * 2. model_port_lookup_: A multi-dimension vector to provide fast look-up on ports of circuit models for users - * It classifies Ports by their types + * 1. model_lookup_: A multi-dimension vector to provide fast look-up on + *circuit models for users It classifies CircuitModelIds by their type and set + *the default model in the first element for each type. + * 2. model_port_lookup_: A multi-dimension vector to provide fast look-up on + *ports of circuit models for users It classifies Ports by their types * * ------ Verilog generation options ----- - * 1. dump_structural_verilog_: if Verilog generator will output structural Verilog syntax for the circuit model - * 2. dump_explicit_port_map_: if Verilog generator will use explicit port mapping when instanciate the circuit model + * 1. dump_structural_verilog_: if Verilog generator will output structural + *Verilog syntax for the circuit model + * 2. dump_explicit_port_map_: if Verilog generator will use explicit port + *mapping when instanciate the circuit model * * ------ Design technology information ----- - * 1. design_tech_types_: the design technology [cmos|rram] for each circuit model - * 2. is_power_gated_: specify if the circuit model is power-gated (contain a input to turn on/off VDD and GND) + * 1. design_tech_types_: the design technology [cmos|rram] for each circuit + *model + * 2. is_power_gated_: specify if the circuit model is power-gated (contain a + *input to turn on/off VDD and GND) * * ------ Buffer existence ----- * Use vectors to simplify the defition of buffer existence: - * index (low=0 to high) represents INPUT, OUTPUT, LUT_INPUT_BUF, LUT_INPUT_INV, LUT_INTER_BUFFER - * 1. buffer_existence_: specify if this circuit model has an buffer - * 2. buffer_model_name_: specify the name of circuit model for the buffer - * 3. buffer_model_id_: specify the id of circuit model for the buffer + * index (low=0 to high) represents INPUT, OUTPUT, LUT_INPUT_BUF, + *LUT_INPUT_INV, LUT_INTER_BUFFER + * 1. buffer_existence_: specify if this circuit model has an buffer + * 2. buffer_model_name_: specify the name of circuit model for the buffer + * 3. buffer_model_id_: specify the id of circuit model for the buffer * * ------ Pass-gate-related parameters ------ - * 1. pass_gate_logic_model_name_: specify the name of circuit model for the pass gate logic - * 2. pass_gate_logic_model_id_: specify the id of circuit model for the pass gate logic + * 1. pass_gate_logic_model_name_: specify the name of circuit model for the + *pass gate logic + * 2. pass_gate_logic_model_id_: specify the id of circuit model for the pass + *gate logic * * ------ Port information ------ - * - port_ids_: unique id of ports belonging to a circuit model + * - port_ids_: unique id of ports belonging to a circuit model * - port_model_ids_: unique id of the parent circuit model for the port - * - port_types_: types of ports belonging to a circuit model + * - port_types_: types of ports belonging to a circuit model * - port_sizes_: width of ports belonging to a circuit model - * - port_prefix_: prefix of a port when instance of a circuit model - * - port_lib_names_: port name in the standard cell library, only used when explicit_port_mapping is enabled - * - port_inv_prefix_: the prefix to be added for the inverted port. This is mainly used by SRAM ports, which have an coupled inverterd port - * - port_is_mode_select: specify if this port is used to select operating modes of the circuit model + * - port_prefix_: prefix of a port when instance of a circuit model + * - port_lib_names_: port name in the standard cell library, only used when + *explicit_port_mapping is enabled + * - port_inv_prefix_: the prefix to be added for the inverted port. This is + *mainly used by SRAM ports, which have an coupled inverterd port + * - port_is_mode_select: specify if this port is used to select operating modes + *of the circuit model * - port_is_io: specify if this port is an io port - * - port_is_data_io: specify if this port is an io port that can be mapped to a signal from netlist - * - port_is_global: specify if this port is a global signal shared by other circuit model - * - port_is_reset: specify if this port is a reset signal which needs special pulse widths in testbenches - * - port_is_set: specify if this port is a set signal which needs special pulse widths in testbenches - * - port_is_config_enable: specify if this port is a config_enable signal which needs special pulse widths in testbenches - * - port_is_prog: specify if this port is for FPGA programming use which needs special pulse widths in testbenches - * - port_tri_state_model_name: the name of circuit model linked to tri-state the port - * - port_tri_state_model_ids_: the Id of circuit model linked to tri-state the port - * - port_inv_model_names_: the name of inverter circuit model linked to the port + * - port_is_data_io: specify if this port is an io port that can be mapped to a + *signal from netlist + * - port_is_global: specify if this port is a global signal shared by other + *circuit model + * - port_is_reset: specify if this port is a reset signal which needs special + *pulse widths in testbenches + * - port_is_set: specify if this port is a set signal which needs special pulse + *widths in testbenches + * - port_is_config_enable: specify if this port is a config_enable signal which + *needs special pulse widths in testbenches + * - port_is_prog: specify if this port is for FPGA programming use which needs + *special pulse widths in testbenches + * - port_tri_state_model_name: the name of circuit model linked to tri-state + *the port + * - port_tri_state_model_ids_: the Id of circuit model linked to tri-state the + *port + * - port_inv_model_names_: the name of inverter circuit model linked to the + *port * - port_inv_model_ids_: the Id of inverter circuit model linked to the port - * - port_tri_state_map_: only applicable to inputs of LUTs, the tri-state map applied to each pin of this port - * - port_lut_frac_level_: only applicable to outputs of LUTs, indicate which level of outputs inside LUT multiplexing structure will be used - * - port_lut_output_mask_: only applicable to outputs of LUTs, indicate which output at an internal level of LUT multiplexing structure will be used - * - port_sram_orgz_: only applicable to SRAM ports, indicate how the SRAMs will be organized, either memory decoders or scan-chains + * - port_tri_state_map_: only applicable to inputs of LUTs, the tri-state map + *applied to each pin of this port + * - port_lut_frac_level_: only applicable to outputs of LUTs, indicate which + *level of outputs inside LUT multiplexing structure will be used + * - port_lut_output_mask_: only applicable to outputs of LUTs, indicate which + *output at an internal level of LUT multiplexing structure will be used + * - port_sram_orgz_: only applicable to SRAM ports, indicate how the SRAMs will + *be organized, either memory decoders or scan-chains * * ------ Delay information ------ * 1. delay_types_: type of pin-to-pin delay, either rising_edge of falling_edge - * 2. delay_in_port_names_: name of input ports that the pin-to-pin delay is linked to - * 3. delay_in_port_names_: name of output ports that the pin-to-pin delay is linked to - * 4. delay_values_: delay values of the pin-to-pin delay + * 2. delay_in_port_names_: name of input ports that the pin-to-pin delay is + *linked to + * 3. delay_in_port_names_: name of output ports that the pin-to-pin delay is + *linked to + * 4. delay_values_: delay values of the pin-to-pin delay * * ------ Timing graph information: TODO: consider using tatum? ------ * Timing graph is allocated when delay information is made - * 1. edge_ids_ : ids of edges in the timing graph - * 2. port_in_edge_ids_: ids of input edges for each pin of a circuit port - * 3. port_out_edge_ids_: ids of output edges for each pin of a circuit port - * 4. edge_src_port_ids_: ids of source ports that each edge is connected to - * 5. edge_src_pin_ids_: ids of source pin that each edge is connected to - * 6. edge_sink_port_ids_: ids of sink ports that each edge is connected to - * 7. edge_sink_pin_ids_: ids of sink pin that each edge is connected to - * 8. edge_trise_: rising delay of the edge - * 9. edge_tfall_: falling delay of the edge + * 1. edge_ids_ : ids of edges in the timing graph + * 2. port_in_edge_ids_: ids of input edges for each pin of a circuit port + * 3. port_out_edge_ids_: ids of output edges for each pin of a circuit port + * 4. edge_src_port_ids_: ids of source ports that each edge is connected to + * 5. edge_src_pin_ids_: ids of source pin that each edge is connected to + * 6. edge_sink_port_ids_: ids of sink ports that each edge is connected to + * 7. edge_sink_pin_ids_: ids of sink pin that each edge is connected to + * 8. edge_trise_: rising delay of the edge + * 9. edge_tfall_: falling delay of the edge * * ------ Buffer/Inverter-related parameters ------ * Note: only applicable to circuit models whose type is buffer or inverter * 1. buffer_types_: type of the buffer, either buffer or inverter * 2. buffer_location_maps_: location of the buffer, only applicable to LUTs * 3. buffer_sizes_: size of buffer (transistor size for the first stage) - * 4. buffer_is_tapered_: specify if this buffer has multiple stages - * 5. buffer_num_levels: specify the number of levels of this buffer (if this is defined as multi-level buffer) + * 4. buffer_is_tapered_: specify if this buffer has multiple stages + * 5. buffer_num_levels: specify the number of levels of this buffer (if this + *is defined as multi-level buffer) * 6. buffer_f_per_stage: specify the driving strength of the buffer by stage * * ------ Pass-gate-logic-related parameters ------ * Note: only applicable to circuit models whose type is pass-gate-logic - * 1. pass_gate_logic_types_: types of the pass-gate-logic, either transmission-gate or pass-transistor - * 2. pass_gate_logic_nmos_sizes_: size of NMOS transistor in the pass-gate-logic - * 3. pass_gate_logic_pmos_sizes_: size of PMOS transistor in the pass-gate-logic, only applicable for transmission-gates + * 1. pass_gate_logic_types_: types of the pass-gate-logic, either + *transmission-gate or pass-transistor + * 2. pass_gate_logic_nmos_sizes_: size of NMOS transistor in the + *pass-gate-logic + * 3. pass_gate_logic_pmos_sizes_: size of PMOS transistor in the + *pass-gate-logic, only applicable for transmission-gates * * ------ Multiplexer-related parameters ------ * Note: only applicable to circuit models whose type is MUX - * 1. mux_structure_: specify the structure of a multiplexer, one-level, multi-level or tree-like - * 2. mux_num_levels_: specify the number of levels for a multiplexer + * 1. mux_structure_: specify the structure of a multiplexer, one-level, + *multi-level or tree-like + * 2. mux_num_levels_: specify the number of levels for a multiplexer * 3. mux_add_const_input_: specify if this multiplexer has a constant input - * 4. mux_const_input_values_: specify the value of the constant input for this multiplexer (valid only when mux_add_const_input is true) - * 5. mux_use_local_encoder_: specify if the mux as a local encoder between SRAMs and multiplexing structure - * 6. mux_advanced_rram_design_: specify if the multiplexer will use advanced RRAM circuit design topology + * 4. mux_const_input_values_: specify the value of the constant input for this + *multiplexer (valid only when mux_add_const_input is true) + * 5. mux_use_local_encoder_: specify if the mux as a local encoder between + *SRAMs and multiplexing structure + * 6. mux_advanced_rram_design_: specify if the multiplexer will use advanced + *RRAM circuit design topology * * ------ LUT-related parameters ------ * Note: only applicable to circuit models whose type is LUT - * 1. lut_is_fracturable_: specify if this LUT is built with fracturable structure + * 1. lut_is_fracturable_: specify if this LUT is built with fracturable + *structure * * ------ RRAM-related parameters ------ * Note: only applicable to circuit models whose design technology is RRAM * 1. rlrs: RRAM resistance in Low-Resistance State (LRS) * 2. rhrs: RRAM resistance in High-Resistance State (HRS) - * The following transistor sizes are applicable for 4T1R programming structures + * The following transistor sizes are applicable for 4T1R programming + *structures * 3. wprog_set_nmos: size of n-type programming transistor used to set a RRAM * 4. wprog_set_pmos: size of p-type programming transistor used to set a RRAM - * 5. wprog_reset_nmos: size of n-type programming transistor used to reset a RRAM - * 6. wprog_reset_pmos: size of p-type programming transistor used to reset a RRAM + * 5. wprog_reset_nmos: size of n-type programming transistor used to reset a + *RRAM + * 6. wprog_reset_pmos: size of p-type programming transistor used to reset a + *RRAM * * ------ Metal wire-related parameters ------ * Note: only applicable to circuit models whose type is wires or channel wires - * 1. wire_types_: types of the metal wire for the model - * 2. wire_res_val_: resistance value of the metal wire for the circuit model - * 3. wire_cap_val_: capacitance value of the metal wire for the circuit model - * 4. wire_num_levels_: number of levels of the metal wire model for the circuit model + * 1. wire_types_: types of the metal wire for the model + * 2. wire_res_val_: resistance value of the metal wire for the circuit model + * 3. wire_cap_val_: capacitance value of the metal wire for the circuit model + * 4. wire_num_levels_: number of levels of the metal wire model for the circuit + *model ***********************************************************************/ class CircuitLibrary { - public: /* Types */ - typedef vtr::vector::const_iterator circuit_model_iterator; - typedef vtr::vector::const_iterator circuit_model_string_iterator; - typedef vtr::vector::const_iterator circuit_port_iterator; - typedef vtr::vector::const_iterator circuit_edge_iterator; - /* Create range */ - typedef vtr::Range circuit_model_range; - typedef vtr::Range circuit_port_range; - typedef vtr::Range circuit_edge_range; - /* local enumeration for buffer existence */ - enum e_buffer_type: unsigned char{ - INPUT = 0, OUTPUT, LUT_INPUT_BUFFER, LUT_INPUT_INVERTER, LUT_INTER_BUFFER, NUM_BUFFER_TYPE /* Last one is a counter */ - }; - public: /* Constructors */ - CircuitLibrary(); - public: /* Accessors: aggregates */ - circuit_model_range models() const; - circuit_port_range ports() const; - std::vector models_by_type(const enum e_circuit_model_type& type) const; - public: /* Public Accessors: Basic data query on Circuit Models*/ - size_t num_models() const; - enum e_circuit_model_type model_type(const CircuitModelId& model_id) const; - std::string model_name(const CircuitModelId& model_id) const; - std::string model_prefix(const CircuitModelId& model_id) const; - std::string model_verilog_netlist(const CircuitModelId& model_id) const; - std::string model_spice_netlist(const CircuitModelId& model_id) const; - bool model_is_default(const CircuitModelId& model_id) const; - bool dump_structural_verilog(const CircuitModelId& model_id) const; - bool dump_explicit_port_map(const CircuitModelId& model_id) const; - /* Design technology information */ - enum e_circuit_model_design_tech design_tech_type(const CircuitModelId& model_id) const; - bool is_power_gated(const CircuitModelId& model_id) const; - /* Device technology information */ - std::string device_model_name(const CircuitModelId& model_id) const; - /* General buffer information */ - bool is_input_buffered(const CircuitModelId& model_id) const; - bool is_output_buffered(const CircuitModelId& model_id) const; - /* LUT-related information */ - bool is_lut_intermediate_buffered(const CircuitModelId& model_id) const; - bool is_lut_fracturable(const CircuitModelId& model_id) const; - CircuitModelId lut_input_buffer_model(const CircuitModelId& model_id) const; - CircuitModelId lut_input_inverter_model(const CircuitModelId& model_id) const; - CircuitModelId lut_intermediate_buffer_model(const CircuitModelId& model_id) const; - std::string lut_intermediate_buffer_location_map(const CircuitModelId& model_id) const; - /* Pass-gate-logic information */ - CircuitModelId pass_gate_logic_model(const CircuitModelId& model_id) const; - std::string pass_gate_logic_model_name(const CircuitModelId& model_id) const; - enum e_circuit_model_pass_gate_logic_type pass_gate_logic_type(const CircuitModelId& model_id) const; - float pass_gate_logic_pmos_size(const CircuitModelId& model_id) const; - float pass_gate_logic_nmos_size(const CircuitModelId& model_id) const; - /* Multiplexer information */ - enum e_circuit_model_structure mux_structure(const CircuitModelId& model_id) const; - size_t mux_num_levels(const CircuitModelId& model_id) const; - bool mux_add_const_input(const CircuitModelId& model_id) const; - size_t mux_const_input_value(const CircuitModelId& model_id) const; - bool mux_use_local_encoder(const CircuitModelId& model_id) const; - bool mux_use_advanced_rram_design(const CircuitModelId& model_id) const; - /* Gate information */ - enum e_circuit_model_gate_type gate_type(const CircuitModelId& model_id) const; - /* Buffer information */ - enum e_circuit_model_buffer_type buffer_type(const CircuitModelId& model_id) const; - size_t buffer_size(const CircuitModelId& model_id) const; - size_t buffer_num_levels(const CircuitModelId& model_id) const; - size_t buffer_f_per_stage(const CircuitModelId& model_id) const; - CircuitModelId input_buffer_model(const CircuitModelId& model_id) const; - CircuitModelId output_buffer_model(const CircuitModelId& model_id) const; - /* Delay information */ - size_t num_delay_info(const CircuitModelId& model_id) const; - /* Wire parameters */ - e_wire_model_type wire_type(const CircuitModelId& model_id) const; - float wire_r(const CircuitModelId& model_id) const; - float wire_c(const CircuitModelId& model_id) const; - size_t wire_num_level(const CircuitModelId& model_id) const; - /* RRAM information */ - float rram_rlrs(const CircuitModelId& model_id) const; - float rram_rhrs(const CircuitModelId& model_id) const; - float rram_wprog_set_pmos(const CircuitModelId& model_id) const; - float rram_wprog_set_nmos(const CircuitModelId& model_id) const; - float rram_wprog_reset_pmos(const CircuitModelId& model_id) const; - float rram_wprog_reset_nmos(const CircuitModelId& model_id) const; - public: /* Public Accessors: Basic data query on cirucit models' Circuit Ports*/ - CircuitPortId model_port(const CircuitModelId& model_id, const std::string& name) const; - size_t num_model_ports(const CircuitModelId& model_id) const; - size_t num_model_ports_by_type(const CircuitModelId& model_id, const enum e_circuit_model_port_type& port_type, const bool& include_global_port) const; - std::vector model_ports(const CircuitModelId& model_id) const; - std::vector model_global_ports(const CircuitModelId& model_id, const bool& recursive) const; - std::vector model_global_ports_by_type(const CircuitModelId& model_id, - const enum e_circuit_model_port_type& type, - const bool& recursive, - const std::vector& ignore_model_types) const; - std::vector model_global_ports_by_type(const CircuitModelId& model_id, - const std::vector& type, - const bool& recursive, - const bool& ignore_config_memories) const; - std::vector model_global_ports_by_type(const CircuitModelId& model_id, - const enum e_circuit_model_port_type& type, - const bool& recursive, - const bool& ignore_config_memories) const; + public: /* Types */ + typedef vtr::vector::const_iterator + circuit_model_iterator; + typedef vtr::vector::const_iterator + circuit_model_string_iterator; + typedef vtr::vector::const_iterator + circuit_port_iterator; + typedef vtr::vector::const_iterator + circuit_edge_iterator; + /* Create range */ + typedef vtr::Range circuit_model_range; + typedef vtr::Range circuit_port_range; + typedef vtr::Range circuit_edge_range; + /* local enumeration for buffer existence */ + enum e_buffer_type : unsigned char { + INPUT = 0, + OUTPUT, + LUT_INPUT_BUFFER, + LUT_INPUT_INVERTER, + LUT_INTER_BUFFER, + NUM_BUFFER_TYPE /* Last one is a counter */ + }; - std::vector model_ports_by_type(const CircuitModelId& model_id, const enum e_circuit_model_port_type& port_type) const; - std::vector model_ports_by_type(const CircuitModelId& model_id, const enum e_circuit_model_port_type& port_type, const bool& include_global_port) const; - std::vector model_input_ports(const CircuitModelId& model_id) const; - std::vector model_output_ports(const CircuitModelId& model_id) const; - std::vector pins(const CircuitPortId& circuit_port_id) const; - public: /* Public Accessors: Basic data query on Circuit Ports*/ - bool is_input_port(const CircuitPortId& circuit_port_id) const; - bool is_output_port(const CircuitPortId& circuit_port_id) const; - enum e_circuit_model_port_type port_type(const CircuitPortId& circuit_port_id) const; - size_t port_size(const CircuitPortId& circuit_port_id) const; - std::string port_prefix(const CircuitPortId& circuit_port_id) const; - std::string port_lib_name(const CircuitPortId& circuit_port_id) const; - std::string port_inv_prefix(const CircuitPortId& circuit_port_id) const; - size_t port_default_value(const CircuitPortId& circuit_port_id) const; - bool port_is_io(const CircuitPortId& circuit_port_id) const; - bool port_is_data_io(const CircuitPortId& circuit_port_id) const; - bool port_is_mode_select(const CircuitPortId& circuit_port_id) const; - bool port_is_global(const CircuitPortId& circuit_port_id) const; - bool port_is_reset(const CircuitPortId& circuit_port_id) const; - bool port_is_set(const CircuitPortId& circuit_port_id) const; - bool port_is_config_enable(const CircuitPortId& circuit_port_id) const; - bool port_is_prog(const CircuitPortId& circuit_port_id) const; - bool port_is_shift_register(const CircuitPortId& circuit_port_id) const; - size_t port_lut_frac_level(const CircuitPortId& circuit_port_id) const; - bool port_is_harden_lut_port(const CircuitPortId& circuit_port_id) const; - std::vector port_lut_output_mask(const CircuitPortId& circuit_port_id) const; - std::string port_tri_state_map(const CircuitPortId& circuit_port_id) const; - CircuitModelId port_tri_state_model(const CircuitPortId& circuit_port_id) const; - std::string port_tri_state_model_name(const CircuitPortId& circuit_port_id) const; - CircuitModelId port_parent_model(const CircuitPortId& circuit_port_id) const; - std::string model_name(const CircuitPortId& port_id) const; - std::string port_inv_model_name(const CircuitPortId& circuit_port_id) const; - public: /* Public Accessors: Timing graph */ - /* Get source/sink nodes and delay of edges */ - std::vector timing_edges_by_model(const CircuitModelId& model_id) const; - CircuitPortId timing_edge_src_port(const CircuitEdgeId& edge) const; - size_t timing_edge_src_pin(const CircuitEdgeId& edge) const; - CircuitPortId timing_edge_sink_port(const CircuitEdgeId& edge) const; - size_t timing_edge_sink_pin(const CircuitEdgeId& edge) const; - float timing_edge_delay(const CircuitEdgeId& edge, const enum e_circuit_model_delay_type& delay_type) const; - public: /* Public Accessors: Methods to find circuit model */ - CircuitModelId model(const char* name) const; - CircuitModelId model(const std::string& name) const; - CircuitModelId default_model(const enum e_circuit_model_type& type) const; - public: /* Public Accessors: Timing graph */ - CircuitEdgeId edge(const CircuitPortId& from_port, const size_t from_pin, - const CircuitPortId& to_port, const size_t to_pin); - public: /* Public Mutators */ - CircuitModelId add_model(const enum e_circuit_model_type& type); - /* Fundamental information */ - void set_model_name(const CircuitModelId& model_id, const std::string& name); - void set_model_prefix(const CircuitModelId& model_id, const std::string& prefix); - void set_model_verilog_netlist(const CircuitModelId& model_id, const std::string& verilog_netlist); - void set_model_spice_netlist(const CircuitModelId& model_id, const std::string& spice_netlist); - void set_model_is_default(const CircuitModelId& model_id, const bool& is_default); - /* Verilog generator options */ - void set_model_dump_structural_verilog(const CircuitModelId& model_id, const bool& dump_structural_verilog); - void set_model_dump_explicit_port_map(const CircuitModelId& model_id, const bool& dump_explicit_port_map); - /* Design technology information */ - void set_model_design_tech_type(const CircuitModelId& model_id, const enum e_circuit_model_design_tech& design_tech_type); - void set_model_is_power_gated(const CircuitModelId& model_id, const bool& is_power_gated); - /* Design technology information */ - void set_device_model_name(const CircuitModelId& model_id, const std::string& name); - /* Buffer existence */ - void set_model_input_buffer(const CircuitModelId& model_id, - const bool& existence, const std::string& model_name); - void set_model_output_buffer(const CircuitModelId& model_id, - const bool& existence, const std::string& model_name); - void set_model_lut_input_buffer(const CircuitModelId& model_id, - const bool& existence, const std::string& model_name); - void set_model_lut_input_inverter(const CircuitModelId& model_id, - const bool& existence, const std::string& model_name); - void set_model_lut_intermediate_buffer(const CircuitModelId& model_id, - const bool& existence, const std::string& model_name); - void set_model_lut_intermediate_buffer_location_map(const CircuitModelId& model_id, - const std::string& location_map); - /* Pass-gate-related parameters */ - void set_model_pass_gate_logic(const CircuitModelId& model_id, const std::string& model_name); - /* Port information */ - CircuitPortId add_model_port(const CircuitModelId& model_id, - const enum e_circuit_model_port_type& port_type); - void set_port_size(const CircuitPortId& circuit_port_id, - const size_t& port_size); - void set_port_prefix(const CircuitPortId& circuit_port_id, - const std::string& port_prefix); - void set_port_lib_name(const CircuitPortId& circuit_port_id, - const std::string& lib_name); - void set_port_inv_prefix(const CircuitPortId& circuit_port_id, - const std::string& inv_prefix); - void set_port_default_value(const CircuitPortId& circuit_port_id, - const size_t& default_val); - void set_port_is_io(const CircuitPortId& circuit_port_id, - const bool& is_io); - void set_port_is_data_io(const CircuitPortId& circuit_port_id, - const bool& is_data_io); - void set_port_is_mode_select(const CircuitPortId& circuit_port_id, - const bool& is_mode_select); - void set_port_is_global(const CircuitPortId& circuit_port_id, - const bool& is_global); - void set_port_is_reset(const CircuitPortId& circuit_port_id, - const bool& is_reset); - void set_port_is_set(const CircuitPortId& circuit_port_id, - const bool& is_set); - void set_port_is_config_enable(const CircuitPortId& circuit_port_id, - const bool& is_config_enable); - void set_port_is_prog(const CircuitPortId& circuit_port_id, - const bool& is_prog); - void set_port_is_shift_register(const CircuitPortId& circuit_port_id, - const bool& is_shift_register); - void set_port_tri_state_model_name(const CircuitPortId& circuit_port_id, - const std::string& model_name); - void set_port_tri_state_model_id(const CircuitPortId& circuit_port_id, - const CircuitModelId& port_model_id); - void set_port_inv_model_name(const CircuitPortId& circuit_port_id, - const std::string& inv_model_name); - void set_port_inv_model_id(const CircuitPortId& circuit_port_id, - const CircuitModelId& inv_model_id); - void set_port_tri_state_map(const CircuitPortId& circuit_port_id, - const std::string& tri_state_map); - void set_port_lut_frac_level(const CircuitPortId& circuit_port_id, - const size_t& lut_frac_level); - void set_port_is_harden_lut_port(const CircuitPortId& circuit_port_id, - const bool& is_harden_lut_port); - void set_port_lut_output_mask(const CircuitPortId& circuit_port_id, - const std::vector& lut_output_masks); - void set_port_sram_orgz(const CircuitPortId& circuit_port_id, - const enum e_config_protocol_type& sram_orgz); - /* Delay information */ - void add_delay_info(const CircuitModelId& model_id, - const enum e_circuit_model_delay_type& delay_type); - void set_delay_in_port_names(const CircuitModelId& model_id, - const enum e_circuit_model_delay_type& delay_type, - const std::string& in_port_names); - void set_delay_out_port_names(const CircuitModelId& model_id, - const enum e_circuit_model_delay_type& delay_type, - const std::string& out_port_names); - void set_delay_values(const CircuitModelId& model_id, - const enum e_circuit_model_delay_type& delay_type, - const std::string& delay_values); - /* Buffer/Inverter-related parameters */ - void set_buffer_type(const CircuitModelId& model_id, - const enum e_circuit_model_buffer_type& buffer_type); - void set_buffer_size(const CircuitModelId& model_id, - const float& buffer_size); - void set_buffer_num_levels(const CircuitModelId& model_id, - const size_t& num_levels); - void set_buffer_f_per_stage(const CircuitModelId& model_id, - const size_t& f_per_stage); - /* Pass-gate-related parameters */ - void set_pass_gate_logic_type(const CircuitModelId& model_id, - const enum e_circuit_model_pass_gate_logic_type& pass_gate_logic_type); - void set_pass_gate_logic_nmos_size(const CircuitModelId& model_id, - const float& nmos_size); - void set_pass_gate_logic_pmos_size(const CircuitModelId& model_id, - const float& pmos_size); - /* Multiplexer-related parameters */ - void set_mux_structure(const CircuitModelId& model_id, - const enum e_circuit_model_structure& mux_structure); - void set_mux_num_levels(const CircuitModelId& model_id, - const size_t& num_levels); - void set_mux_const_input_value(const CircuitModelId& model_id, - const size_t& const_input_value); - void set_mux_use_local_encoder(const CircuitModelId& model_id, - const bool& use_local_encoder); - void set_mux_use_advanced_rram_design(const CircuitModelId& model_id, - const bool& use_advanced_rram_design); - /* LUT-related parameters */ - void set_lut_is_fracturable(const CircuitModelId& model_id, - const bool& is_fracturable); - /* Gate-related parameters */ - void set_gate_type(const CircuitModelId& model_id, - const enum e_circuit_model_gate_type& gate_type); - /* RRAM-related design technology information */ - void set_rram_rlrs(const CircuitModelId& model_id, - const float& rlrs); - void set_rram_rhrs(const CircuitModelId& model_id, - const float& rhrs); - void set_rram_wprog_set_nmos(const CircuitModelId& model_id, - const float& wprog_set_nmos); - void set_rram_wprog_set_pmos(const CircuitModelId& model_id, - const float& wprog_set_pmos); - void set_rram_wprog_reset_nmos(const CircuitModelId& model_id, - const float& wprog_reset_nmos); - void set_rram_wprog_reset_pmos(const CircuitModelId& model_id, - const float& wprog_reset_pmos); - /* Wire parameters */ - void set_wire_type(const CircuitModelId& model_id, - const enum e_wire_model_type& wire_type); - void set_wire_r(const CircuitModelId& model_id, - const float& r_val); - void set_wire_c(const CircuitModelId& model_id, - const float& c_val); - void set_wire_num_level(const CircuitModelId& model_id, - const size_t& num_level); - private: /* Private Mutators: builders */ - void set_model_buffer(const CircuitModelId& model_id, const enum e_buffer_type buffer_type, const bool& existence, const std::string& model_name); - void link_port_tri_state_model(); - void link_port_inv_model(); - void link_buffer_model(const CircuitModelId& model_id); - void link_pass_gate_logic_model(const CircuitModelId& model_id); - bool is_unique_submodel(const CircuitModelId& model_id, const CircuitModelId& submodel_id); - void build_model_timing_graph(const CircuitModelId& model_id); - void build_submodels(); - public: /* Public Mutators: builders */ - void build_model_links(); - void build_timing_graphs(); - /* Automatically identify the default models for each type, - * suggest to do this after circuit library is built - */ - void auto_detect_default_models(); - public: /* Internal mutators: build timing graphs */ - void add_edge(const CircuitModelId& model_id, - const CircuitPortId& from_port, const size_t& from_pin, - const CircuitPortId& to_port, const size_t& to_pin); - void set_edge_delay(const CircuitModelId& model_id, - const CircuitEdgeId& circuit_edge_id, - const enum e_circuit_model_delay_type& delay_type, - const float& delay_value); - /* validate the circuit_edge_id */ - void set_timing_graph_delays(const CircuitModelId& model_id); - public: /* Internal mutators: build fast look-ups */ - void build_model_lookup(); - void build_model_port_lookup(); - public: /* Public invalidators/validators */ - bool valid_model_id(const CircuitModelId& model_id) const; - bool valid_circuit_port_id(const CircuitPortId& circuit_port_id) const; - bool valid_circuit_pin_id(const CircuitPortId& circuit_port_id, const size_t& pin_id) const; - private: /* Internal invalidators/validators */ - /* Validators */ - bool valid_edge_id(const CircuitEdgeId& edge_id) const; - bool valid_delay_type(const CircuitModelId& model_id, const enum e_circuit_model_delay_type& delay_type) const; - bool valid_circuit_edge_id(const CircuitEdgeId& circuit_edge_id) const; - bool valid_mux_const_input_value(const size_t& const_input_value) const; - /* Invalidators */ - void invalidate_model_lookup() const; - void invalidate_model_port_lookup() const; - void invalidate_model_timing_graph(); - private: /* Internal data */ - /* Fundamental information */ - vtr::vector model_ids_; - vtr::vector model_types_; - vtr::vector model_names_; - vtr::vector model_prefix_; - vtr::vector model_verilog_netlists_; - vtr::vector model_spice_netlists_; - vtr::vector model_is_default_; + public: /* Constructors */ + CircuitLibrary(); - /* Submodules that a circuit model contains */ - vtr::vector> sub_models_; + public: /* Accessors: aggregates */ + circuit_model_range models() const; + circuit_port_range ports() const; + std::vector models_by_type( + const enum e_circuit_model_type& type) const; - /* fast look-up for circuit models to categorize by types - * [type][num_ids] - * Important: we force the default circuit model in the first element for each type - */ - typedef std::vector> CircuitModelLookup; - mutable CircuitModelLookup model_lookup_; /* [model_type][model_ids] */ - typedef vtr::vector>> CircuitModelPortLookup; - mutable CircuitModelPortLookup model_port_lookup_; /* [model_id][port_type][port_ids] */ + public: /* Public Accessors: Basic data query on Circuit Models*/ + size_t num_models() const; + enum e_circuit_model_type model_type(const CircuitModelId& model_id) const; + std::string model_name(const CircuitModelId& model_id) const; + std::string model_prefix(const CircuitModelId& model_id) const; + std::string model_verilog_netlist(const CircuitModelId& model_id) const; + std::string model_spice_netlist(const CircuitModelId& model_id) const; + bool model_is_default(const CircuitModelId& model_id) const; + bool dump_structural_verilog(const CircuitModelId& model_id) const; + bool dump_explicit_port_map(const CircuitModelId& model_id) const; + /* Design technology information */ + enum e_circuit_model_design_tech design_tech_type( + const CircuitModelId& model_id) const; + bool is_power_gated(const CircuitModelId& model_id) const; + /* Device technology information */ + std::string device_model_name(const CircuitModelId& model_id) const; + /* General buffer information */ + bool is_input_buffered(const CircuitModelId& model_id) const; + bool is_output_buffered(const CircuitModelId& model_id) const; + /* LUT-related information */ + bool is_lut_intermediate_buffered(const CircuitModelId& model_id) const; + bool is_lut_fracturable(const CircuitModelId& model_id) const; + CircuitModelId lut_input_buffer_model(const CircuitModelId& model_id) const; + CircuitModelId lut_input_inverter_model(const CircuitModelId& model_id) const; + CircuitModelId lut_intermediate_buffer_model( + const CircuitModelId& model_id) const; + std::string lut_intermediate_buffer_location_map( + const CircuitModelId& model_id) const; + /* Pass-gate-logic information */ + CircuitModelId pass_gate_logic_model(const CircuitModelId& model_id) const; + std::string pass_gate_logic_model_name(const CircuitModelId& model_id) const; + enum e_circuit_model_pass_gate_logic_type pass_gate_logic_type( + const CircuitModelId& model_id) const; + float pass_gate_logic_pmos_size(const CircuitModelId& model_id) const; + float pass_gate_logic_nmos_size(const CircuitModelId& model_id) const; + /* Multiplexer information */ + enum e_circuit_model_structure mux_structure( + const CircuitModelId& model_id) const; + size_t mux_num_levels(const CircuitModelId& model_id) const; + bool mux_add_const_input(const CircuitModelId& model_id) const; + size_t mux_const_input_value(const CircuitModelId& model_id) const; + bool mux_use_local_encoder(const CircuitModelId& model_id) const; + bool mux_use_advanced_rram_design(const CircuitModelId& model_id) const; + /* Gate information */ + enum e_circuit_model_gate_type gate_type( + const CircuitModelId& model_id) const; + /* Buffer information */ + enum e_circuit_model_buffer_type buffer_type( + const CircuitModelId& model_id) const; + size_t buffer_size(const CircuitModelId& model_id) const; + size_t buffer_num_levels(const CircuitModelId& model_id) const; + size_t buffer_f_per_stage(const CircuitModelId& model_id) const; + CircuitModelId input_buffer_model(const CircuitModelId& model_id) const; + CircuitModelId output_buffer_model(const CircuitModelId& model_id) const; + /* Delay information */ + size_t num_delay_info(const CircuitModelId& model_id) const; + /* Wire parameters */ + e_wire_model_type wire_type(const CircuitModelId& model_id) const; + float wire_r(const CircuitModelId& model_id) const; + float wire_c(const CircuitModelId& model_id) const; + size_t wire_num_level(const CircuitModelId& model_id) const; + /* RRAM information */ + float rram_rlrs(const CircuitModelId& model_id) const; + float rram_rhrs(const CircuitModelId& model_id) const; + float rram_wprog_set_pmos(const CircuitModelId& model_id) const; + float rram_wprog_set_nmos(const CircuitModelId& model_id) const; + float rram_wprog_reset_pmos(const CircuitModelId& model_id) const; + float rram_wprog_reset_nmos(const CircuitModelId& model_id) const; - /* Verilog generator options */ - vtr::vector dump_structural_verilog_; - vtr::vector dump_explicit_port_map_; - - /* Design technology information */ - vtr::vector design_tech_types_; - vtr::vector is_power_gated_; + public + : /* Public Accessors: Basic data query on cirucit models' Circuit Ports*/ + CircuitPortId model_port(const CircuitModelId& model_id, + const std::string& name) const; + size_t num_model_ports(const CircuitModelId& model_id) const; + size_t num_model_ports_by_type( + const CircuitModelId& model_id, + const enum e_circuit_model_port_type& port_type, + const bool& include_global_port) const; + std::vector model_ports(const CircuitModelId& model_id) const; + std::vector model_global_ports(const CircuitModelId& model_id, + const bool& recursive) const; + std::vector model_global_ports_by_type( + const CircuitModelId& model_id, const enum e_circuit_model_port_type& type, + const bool& recursive, + const std::vector& ignore_model_types) const; + std::vector model_global_ports_by_type( + const CircuitModelId& model_id, + const std::vector& type, + const bool& recursive, const bool& ignore_config_memories) const; + std::vector model_global_ports_by_type( + const CircuitModelId& model_id, const enum e_circuit_model_port_type& type, + const bool& recursive, const bool& ignore_config_memories) const; - /* Device technology information */ - vtr::vector device_model_names_; + std::vector model_ports_by_type( + const CircuitModelId& model_id, + const enum e_circuit_model_port_type& port_type) const; + std::vector model_ports_by_type( + const CircuitModelId& model_id, + const enum e_circuit_model_port_type& port_type, + const bool& include_global_port) const; + std::vector model_input_ports( + const CircuitModelId& model_id) const; + std::vector model_output_ports( + const CircuitModelId& model_id) const; + std::vector pins(const CircuitPortId& circuit_port_id) const; - /* Buffer existence */ - vtr::vector> buffer_existence_; - vtr::vector> buffer_model_names_; - vtr::vector> buffer_model_ids_; - vtr::vector> buffer_location_maps_; + public: /* Public Accessors: Basic data query on Circuit Ports*/ + bool is_input_port(const CircuitPortId& circuit_port_id) const; + bool is_output_port(const CircuitPortId& circuit_port_id) const; + enum e_circuit_model_port_type port_type( + const CircuitPortId& circuit_port_id) const; + size_t port_size(const CircuitPortId& circuit_port_id) const; + std::string port_prefix(const CircuitPortId& circuit_port_id) const; + std::string port_lib_name(const CircuitPortId& circuit_port_id) const; + std::string port_inv_prefix(const CircuitPortId& circuit_port_id) const; + size_t port_default_value(const CircuitPortId& circuit_port_id) const; + bool port_is_io(const CircuitPortId& circuit_port_id) const; + bool port_is_data_io(const CircuitPortId& circuit_port_id) const; + bool port_is_mode_select(const CircuitPortId& circuit_port_id) const; + bool port_is_global(const CircuitPortId& circuit_port_id) const; + bool port_is_reset(const CircuitPortId& circuit_port_id) const; + bool port_is_set(const CircuitPortId& circuit_port_id) const; + bool port_is_config_enable(const CircuitPortId& circuit_port_id) const; + bool port_is_prog(const CircuitPortId& circuit_port_id) const; + bool port_is_shift_register(const CircuitPortId& circuit_port_id) const; + size_t port_lut_frac_level(const CircuitPortId& circuit_port_id) const; + bool port_is_harden_lut_port(const CircuitPortId& circuit_port_id) const; + std::vector port_lut_output_mask( + const CircuitPortId& circuit_port_id) const; + std::string port_tri_state_map(const CircuitPortId& circuit_port_id) const; + CircuitModelId port_tri_state_model( + const CircuitPortId& circuit_port_id) const; + std::string port_tri_state_model_name( + const CircuitPortId& circuit_port_id) const; + CircuitModelId port_parent_model(const CircuitPortId& circuit_port_id) const; + std::string model_name(const CircuitPortId& port_id) const; + std::string port_inv_model_name(const CircuitPortId& circuit_port_id) const; - /* Pass-gate-related parameters */ - vtr::vector pass_gate_logic_model_names_; - vtr::vector pass_gate_logic_model_ids_; + public: /* Public Accessors: Timing graph */ + /* Get source/sink nodes and delay of edges */ + std::vector timing_edges_by_model( + const CircuitModelId& model_id) const; + CircuitPortId timing_edge_src_port(const CircuitEdgeId& edge) const; + size_t timing_edge_src_pin(const CircuitEdgeId& edge) const; + CircuitPortId timing_edge_sink_port(const CircuitEdgeId& edge) const; + size_t timing_edge_sink_pin(const CircuitEdgeId& edge) const; + float timing_edge_delay( + const CircuitEdgeId& edge, + const enum e_circuit_model_delay_type& delay_type) const; - /* Port information */ - vtr::vector port_ids_; - vtr::vector port_model_ids_; - vtr::vector port_types_; - vtr::vector port_sizes_; - vtr::vector port_prefix_; - vtr::vector port_lib_names_; - vtr::vector port_inv_prefix_; - vtr::vector port_default_values_; - vtr::vector port_is_io_; - vtr::vector port_is_data_io_; - vtr::vector port_is_mode_select_; - vtr::vector port_is_global_; - vtr::vector port_is_reset_; - vtr::vector port_is_set_; - vtr::vector port_is_config_enable_; - vtr::vector port_is_prog_; - vtr::vector port_is_shift_register_; - vtr::vector port_tri_state_model_names_; - vtr::vector port_tri_state_model_ids_; - vtr::vector port_inv_model_names_; - vtr::vector port_inv_model_ids_; - vtr::vector port_tri_state_maps_; - vtr::vector port_lut_frac_level_; - vtr::vector port_is_harden_lut_port_; - vtr::vector> port_lut_output_masks_; - vtr::vector port_sram_orgz_; + public: /* Public Accessors: Methods to find circuit model */ + CircuitModelId model(const char* name) const; + CircuitModelId model(const std::string& name) const; + CircuitModelId default_model(const enum e_circuit_model_type& type) const; - /* Timing graphs */ - vtr::vector edge_ids_; - vtr::vector edge_parent_model_ids_; - vtr::vector> port_in_edge_ids_; - vtr::vector> port_out_edge_ids_; - vtr::vector edge_src_port_ids_; - vtr::vector edge_src_pin_ids_; - vtr::vector edge_sink_port_ids_; - vtr::vector edge_sink_pin_ids_; - vtr::vector> edge_timing_info_; /* x0 => trise, x1 => tfall */ + public: /* Public Accessors: Timing graph */ + CircuitEdgeId edge(const CircuitPortId& from_port, const size_t from_pin, + const CircuitPortId& to_port, const size_t to_pin); - /* Delay information */ - vtr::vector> delay_types_; - vtr::vector> delay_in_port_names_; - vtr::vector> delay_out_port_names_; - vtr::vector> delay_values_; + public: /* Public Mutators */ + CircuitModelId add_model(const enum e_circuit_model_type& type); + /* Fundamental information */ + void set_model_name(const CircuitModelId& model_id, const std::string& name); + void set_model_prefix(const CircuitModelId& model_id, + const std::string& prefix); + void set_model_verilog_netlist(const CircuitModelId& model_id, + const std::string& verilog_netlist); + void set_model_spice_netlist(const CircuitModelId& model_id, + const std::string& spice_netlist); + void set_model_is_default(const CircuitModelId& model_id, + const bool& is_default); + /* Verilog generator options */ + void set_model_dump_structural_verilog(const CircuitModelId& model_id, + const bool& dump_structural_verilog); + void set_model_dump_explicit_port_map(const CircuitModelId& model_id, + const bool& dump_explicit_port_map); + /* Design technology information */ + void set_model_design_tech_type( + const CircuitModelId& model_id, + const enum e_circuit_model_design_tech& design_tech_type); + void set_model_is_power_gated(const CircuitModelId& model_id, + const bool& is_power_gated); + /* Design technology information */ + void set_device_model_name(const CircuitModelId& model_id, + const std::string& name); + /* Buffer existence */ + void set_model_input_buffer(const CircuitModelId& model_id, + const bool& existence, + const std::string& model_name); + void set_model_output_buffer(const CircuitModelId& model_id, + const bool& existence, + const std::string& model_name); + void set_model_lut_input_buffer(const CircuitModelId& model_id, + const bool& existence, + const std::string& model_name); + void set_model_lut_input_inverter(const CircuitModelId& model_id, + const bool& existence, + const std::string& model_name); + void set_model_lut_intermediate_buffer(const CircuitModelId& model_id, + const bool& existence, + const std::string& model_name); + void set_model_lut_intermediate_buffer_location_map( + const CircuitModelId& model_id, const std::string& location_map); + /* Pass-gate-related parameters */ + void set_model_pass_gate_logic(const CircuitModelId& model_id, + const std::string& model_name); + /* Port information */ + CircuitPortId add_model_port(const CircuitModelId& model_id, + const enum e_circuit_model_port_type& port_type); + void set_port_size(const CircuitPortId& circuit_port_id, + const size_t& port_size); + void set_port_prefix(const CircuitPortId& circuit_port_id, + const std::string& port_prefix); + void set_port_lib_name(const CircuitPortId& circuit_port_id, + const std::string& lib_name); + void set_port_inv_prefix(const CircuitPortId& circuit_port_id, + const std::string& inv_prefix); + void set_port_default_value(const CircuitPortId& circuit_port_id, + const size_t& default_val); + void set_port_is_io(const CircuitPortId& circuit_port_id, const bool& is_io); + void set_port_is_data_io(const CircuitPortId& circuit_port_id, + const bool& is_data_io); + void set_port_is_mode_select(const CircuitPortId& circuit_port_id, + const bool& is_mode_select); + void set_port_is_global(const CircuitPortId& circuit_port_id, + const bool& is_global); + void set_port_is_reset(const CircuitPortId& circuit_port_id, + const bool& is_reset); + void set_port_is_set(const CircuitPortId& circuit_port_id, + const bool& is_set); + void set_port_is_config_enable(const CircuitPortId& circuit_port_id, + const bool& is_config_enable); + void set_port_is_prog(const CircuitPortId& circuit_port_id, + const bool& is_prog); + void set_port_is_shift_register(const CircuitPortId& circuit_port_id, + const bool& is_shift_register); + void set_port_tri_state_model_name(const CircuitPortId& circuit_port_id, + const std::string& model_name); + void set_port_tri_state_model_id(const CircuitPortId& circuit_port_id, + const CircuitModelId& port_model_id); + void set_port_inv_model_name(const CircuitPortId& circuit_port_id, + const std::string& inv_model_name); + void set_port_inv_model_id(const CircuitPortId& circuit_port_id, + const CircuitModelId& inv_model_id); + void set_port_tri_state_map(const CircuitPortId& circuit_port_id, + const std::string& tri_state_map); + void set_port_lut_frac_level(const CircuitPortId& circuit_port_id, + const size_t& lut_frac_level); + void set_port_is_harden_lut_port(const CircuitPortId& circuit_port_id, + const bool& is_harden_lut_port); + void set_port_lut_output_mask(const CircuitPortId& circuit_port_id, + const std::vector& lut_output_masks); + void set_port_sram_orgz(const CircuitPortId& circuit_port_id, + const enum e_config_protocol_type& sram_orgz); + /* Delay information */ + void add_delay_info(const CircuitModelId& model_id, + const enum e_circuit_model_delay_type& delay_type); + void set_delay_in_port_names( + const CircuitModelId& model_id, + const enum e_circuit_model_delay_type& delay_type, + const std::string& in_port_names); + void set_delay_out_port_names( + const CircuitModelId& model_id, + const enum e_circuit_model_delay_type& delay_type, + const std::string& out_port_names); + void set_delay_values(const CircuitModelId& model_id, + const enum e_circuit_model_delay_type& delay_type, + const std::string& delay_values); + /* Buffer/Inverter-related parameters */ + void set_buffer_type(const CircuitModelId& model_id, + const enum e_circuit_model_buffer_type& buffer_type); + void set_buffer_size(const CircuitModelId& model_id, + const float& buffer_size); + void set_buffer_num_levels(const CircuitModelId& model_id, + const size_t& num_levels); + void set_buffer_f_per_stage(const CircuitModelId& model_id, + const size_t& f_per_stage); + /* Pass-gate-related parameters */ + void set_pass_gate_logic_type( + const CircuitModelId& model_id, + const enum e_circuit_model_pass_gate_logic_type& pass_gate_logic_type); + void set_pass_gate_logic_nmos_size(const CircuitModelId& model_id, + const float& nmos_size); + void set_pass_gate_logic_pmos_size(const CircuitModelId& model_id, + const float& pmos_size); + /* Multiplexer-related parameters */ + void set_mux_structure(const CircuitModelId& model_id, + const enum e_circuit_model_structure& mux_structure); + void set_mux_num_levels(const CircuitModelId& model_id, + const size_t& num_levels); + void set_mux_const_input_value(const CircuitModelId& model_id, + const size_t& const_input_value); + void set_mux_use_local_encoder(const CircuitModelId& model_id, + const bool& use_local_encoder); + void set_mux_use_advanced_rram_design(const CircuitModelId& model_id, + const bool& use_advanced_rram_design); + /* LUT-related parameters */ + void set_lut_is_fracturable(const CircuitModelId& model_id, + const bool& is_fracturable); + /* Gate-related parameters */ + void set_gate_type(const CircuitModelId& model_id, + const enum e_circuit_model_gate_type& gate_type); + /* RRAM-related design technology information */ + void set_rram_rlrs(const CircuitModelId& model_id, const float& rlrs); + void set_rram_rhrs(const CircuitModelId& model_id, const float& rhrs); + void set_rram_wprog_set_nmos(const CircuitModelId& model_id, + const float& wprog_set_nmos); + void set_rram_wprog_set_pmos(const CircuitModelId& model_id, + const float& wprog_set_pmos); + void set_rram_wprog_reset_nmos(const CircuitModelId& model_id, + const float& wprog_reset_nmos); + void set_rram_wprog_reset_pmos(const CircuitModelId& model_id, + const float& wprog_reset_pmos); + /* Wire parameters */ + void set_wire_type(const CircuitModelId& model_id, + const enum e_wire_model_type& wire_type); + void set_wire_r(const CircuitModelId& model_id, const float& r_val); + void set_wire_c(const CircuitModelId& model_id, const float& c_val); + void set_wire_num_level(const CircuitModelId& model_id, + const size_t& num_level); - /* Buffer/Inverter-related parameters */ - vtr::vector buffer_types_; - vtr::vector buffer_sizes_; - vtr::vector buffer_num_levels_; - vtr::vector buffer_f_per_stage_; + private: /* Private Mutators: builders */ + void set_model_buffer(const CircuitModelId& model_id, + const enum e_buffer_type buffer_type, + const bool& existence, const std::string& model_name); + void link_port_tri_state_model(); + void link_port_inv_model(); + void link_buffer_model(const CircuitModelId& model_id); + void link_pass_gate_logic_model(const CircuitModelId& model_id); + bool is_unique_submodel(const CircuitModelId& model_id, + const CircuitModelId& submodel_id); + void build_model_timing_graph(const CircuitModelId& model_id); + void build_submodels(); - /* Pass-gate-related parameters */ - vtr::vector pass_gate_logic_types_; - vtr::vector> pass_gate_logic_sizes_; /* x=> nmos_size; y => pmos_size */ + public: /* Public Mutators: builders */ + void build_model_links(); + void build_timing_graphs(); + /* Automatically identify the default models for each type, + * suggest to do this after circuit library is built + */ + void auto_detect_default_models(); - /* Multiplexer-related parameters */ - vtr::vector mux_structure_; - vtr::vector mux_num_levels_; - vtr::vector mux_const_input_values_; - vtr::vector mux_use_local_encoder_; - vtr::vector mux_use_advanced_rram_design_; + public: /* Internal mutators: build timing graphs */ + void add_edge(const CircuitModelId& model_id, const CircuitPortId& from_port, + const size_t& from_pin, const CircuitPortId& to_port, + const size_t& to_pin); + void set_edge_delay(const CircuitModelId& model_id, + const CircuitEdgeId& circuit_edge_id, + const enum e_circuit_model_delay_type& delay_type, + const float& delay_value); + /* validate the circuit_edge_id */ + void set_timing_graph_delays(const CircuitModelId& model_id); - /* LUT-related parameters */ - vtr::vector lut_is_fracturable_; + public: /* Internal mutators: build fast look-ups */ + void build_model_lookup(); + void build_model_port_lookup(); - /* Gate-related parameters */ - vtr::vector gate_types_; + public: /* Public invalidators/validators */ + bool valid_model_id(const CircuitModelId& model_id) const; + bool valid_circuit_port_id(const CircuitPortId& circuit_port_id) const; + bool valid_circuit_pin_id(const CircuitPortId& circuit_port_id, + const size_t& pin_id) const; - /* RRAM-related design technology information */ - vtr::vector> rram_res_; /* x => R_LRS, y => R_HRS */ - vtr::vector> wprog_set_; /* x => wprog_set_nmos, y=> wprog_set_pmos */ - vtr::vector> wprog_reset_; /* x => wprog_reset_nmos, y=> wprog_reset_pmos */ - - /* Wire parameters */ - vtr::vector wire_types_; - vtr::vector> wire_rc_; /* x => wire_res_val, y=> wire_cap_val */ - vtr::vector wire_num_levels_; + private: /* Internal invalidators/validators */ + /* Validators */ + bool valid_edge_id(const CircuitEdgeId& edge_id) const; + bool valid_delay_type( + const CircuitModelId& model_id, + const enum e_circuit_model_delay_type& delay_type) const; + bool valid_circuit_edge_id(const CircuitEdgeId& circuit_edge_id) const; + bool valid_mux_const_input_value(const size_t& const_input_value) const; + /* Invalidators */ + void invalidate_model_lookup() const; + void invalidate_model_port_lookup() const; + void invalidate_model_timing_graph(); + + private: /* Internal data */ + /* Fundamental information */ + vtr::vector model_ids_; + vtr::vector model_types_; + vtr::vector model_names_; + vtr::vector model_prefix_; + vtr::vector model_verilog_netlists_; + vtr::vector model_spice_netlists_; + vtr::vector model_is_default_; + + /* Submodules that a circuit model contains */ + vtr::vector> sub_models_; + + /* fast look-up for circuit models to categorize by types + * [type][num_ids] + * Important: we force the default circuit model in the first element for each + * type + */ + typedef std::vector> CircuitModelLookup; + mutable CircuitModelLookup model_lookup_; /* [model_type][model_ids] */ + typedef vtr::vector>> + CircuitModelPortLookup; + mutable CircuitModelPortLookup + model_port_lookup_; /* [model_id][port_type][port_ids] */ + + /* Verilog generator options */ + vtr::vector dump_structural_verilog_; + vtr::vector dump_explicit_port_map_; + + /* Design technology information */ + vtr::vector + design_tech_types_; + vtr::vector is_power_gated_; + + /* Device technology information */ + vtr::vector device_model_names_; + + /* Buffer existence */ + vtr::vector> buffer_existence_; + vtr::vector> buffer_model_names_; + vtr::vector> buffer_model_ids_; + vtr::vector> buffer_location_maps_; + + /* Pass-gate-related parameters */ + vtr::vector pass_gate_logic_model_names_; + vtr::vector pass_gate_logic_model_ids_; + + /* Port information */ + vtr::vector port_ids_; + vtr::vector port_model_ids_; + vtr::vector port_types_; + vtr::vector port_sizes_; + vtr::vector port_prefix_; + vtr::vector port_lib_names_; + vtr::vector port_inv_prefix_; + vtr::vector port_default_values_; + vtr::vector port_is_io_; + vtr::vector port_is_data_io_; + vtr::vector port_is_mode_select_; + vtr::vector port_is_global_; + vtr::vector port_is_reset_; + vtr::vector port_is_set_; + vtr::vector port_is_config_enable_; + vtr::vector port_is_prog_; + vtr::vector port_is_shift_register_; + vtr::vector port_tri_state_model_names_; + vtr::vector port_tri_state_model_ids_; + vtr::vector port_inv_model_names_; + vtr::vector port_inv_model_ids_; + vtr::vector port_tri_state_maps_; + vtr::vector port_lut_frac_level_; + vtr::vector port_is_harden_lut_port_; + vtr::vector> port_lut_output_masks_; + vtr::vector port_sram_orgz_; + + /* Timing graphs */ + vtr::vector edge_ids_; + vtr::vector edge_parent_model_ids_; + vtr::vector> + port_in_edge_ids_; + vtr::vector> + port_out_edge_ids_; + vtr::vector edge_src_port_ids_; + vtr::vector edge_src_pin_ids_; + vtr::vector edge_sink_port_ids_; + vtr::vector edge_sink_pin_ids_; + vtr::vector> + edge_timing_info_; /* x0 => trise, x1 => tfall */ + + /* Delay information */ + vtr::vector> + delay_types_; + vtr::vector> delay_in_port_names_; + vtr::vector> delay_out_port_names_; + vtr::vector> delay_values_; + + /* Buffer/Inverter-related parameters */ + vtr::vector buffer_types_; + vtr::vector buffer_sizes_; + vtr::vector buffer_num_levels_; + vtr::vector buffer_f_per_stage_; + + /* Pass-gate-related parameters */ + vtr::vector + pass_gate_logic_types_; + vtr::vector> + pass_gate_logic_sizes_; /* x=> nmos_size; y => pmos_size */ + + /* Multiplexer-related parameters */ + vtr::vector mux_structure_; + vtr::vector mux_num_levels_; + vtr::vector mux_const_input_values_; + vtr::vector mux_use_local_encoder_; + vtr::vector mux_use_advanced_rram_design_; + + /* LUT-related parameters */ + vtr::vector lut_is_fracturable_; + + /* Gate-related parameters */ + vtr::vector gate_types_; + + /* RRAM-related design technology information */ + vtr::vector> + rram_res_; /* x => R_LRS, y => R_HRS */ + vtr::vector> + wprog_set_; /* x => wprog_set_nmos, y=> wprog_set_pmos */ + vtr::vector> + wprog_reset_; /* x => wprog_reset_nmos, y=> wprog_reset_pmos */ + + /* Wire parameters */ + vtr::vector wire_types_; + vtr::vector> + wire_rc_; /* x => wire_res_val, y=> wire_cap_val */ + vtr::vector wire_num_levels_; }; #endif diff --git a/libs/libarchopenfpga/src/circuit_library_fwd.h b/libs/libarchopenfpga/src/circuit_library_fwd.h index cef4fc4a0..f07681ece 100644 --- a/libs/libarchopenfpga/src/circuit_library_fwd.h +++ b/libs/libarchopenfpga/src/circuit_library_fwd.h @@ -1,11 +1,11 @@ /************************************************************************ * A header file for CircuitLibrary class, including critical data declaration * Please include this file only for using any CircuitLibrary data structure - * Refer to circuit_library.h for more details + * Refer to circuit_library.h for more details ***********************************************************************/ /************************************************************************ - * Create strong id for Circuit Models/Ports to avoid illegal type casting + * Create strong id for Circuit Models/Ports to avoid illegal type casting ***********************************************************************/ #ifndef CIRCUIT_LIBRARY_FWD_H #define CIRCUIT_LIBRARY_FWD_H diff --git a/libs/libarchopenfpga/src/circuit_types.h b/libs/libarchopenfpga/src/circuit_types.h index 12b881db0..35000d80e 100644 --- a/libs/libarchopenfpga/src/circuit_types.h +++ b/libs/libarchopenfpga/src/circuit_types.h @@ -1,19 +1,19 @@ /* IMPORTANT: - * The following preprocessing flags are added to - * avoid compilation error when this headers are included in more than 1 times + * The following preprocessing flags are added to + * avoid compilation error when this headers are included in more than 1 times */ #ifndef CIRCUIT_TYPES_H #define CIRCUIT_TYPES_H -#include #include +#include /************************************************************************ * This file includes basic enumeration types for circuit models ***********************************************************************/ /* - * Notes in include header files in a head file - * Only include the neccessary header files + * Notes in include header files in a head file + * Only include the neccessary header files * that is required by the data types in the function/class declarations! */ /* Header files should be included in a sequence */ @@ -21,81 +21,90 @@ /*Struct for a CIRCUIT model of a module*/ enum e_circuit_model_type { - CIRCUIT_MODEL_CHAN_WIRE, - CIRCUIT_MODEL_WIRE, - CIRCUIT_MODEL_MUX, - CIRCUIT_MODEL_LUT, - CIRCUIT_MODEL_FF, - CIRCUIT_MODEL_SRAM, + CIRCUIT_MODEL_CHAN_WIRE, + CIRCUIT_MODEL_WIRE, + CIRCUIT_MODEL_MUX, + CIRCUIT_MODEL_LUT, + CIRCUIT_MODEL_FF, + CIRCUIT_MODEL_SRAM, CIRCUIT_MODEL_HARDLOGIC, CIRCUIT_MODEL_CCFF, - CIRCUIT_MODEL_IOPAD, - CIRCUIT_MODEL_INVBUF, - CIRCUIT_MODEL_PASSGATE, + CIRCUIT_MODEL_IOPAD, + CIRCUIT_MODEL_INVBUF, + CIRCUIT_MODEL_PASSGATE, CIRCUIT_MODEL_GATE, NUM_CIRCUIT_MODEL_TYPES }; /* Strings correspond to each port type */ -constexpr std::array CIRCUIT_MODEL_TYPE_STRING = {{"chan_wire", "wire", "mux", "lut", "ff", "sram", "hard_logic", "ccff", "iopad", "inv_buf", "pass_gate", "gate"}}; +constexpr std::array + CIRCUIT_MODEL_TYPE_STRING = {{"chan_wire", "wire", "mux", "lut", "ff", "sram", + "hard_logic", "ccff", "iopad", "inv_buf", + "pass_gate", "gate"}}; enum e_circuit_model_design_tech { - CIRCUIT_MODEL_DESIGN_CMOS, + CIRCUIT_MODEL_DESIGN_CMOS, CIRCUIT_MODEL_DESIGN_RRAM, NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES }; /* Strings correspond to each design technology type */ -constexpr std::array CIRCUIT_MODEL_DESIGN_TECH_TYPE_STRING = {{"cmos", "rram"}}; +constexpr std::array + CIRCUIT_MODEL_DESIGN_TECH_TYPE_STRING = {{"cmos", "rram"}}; enum e_circuit_model_structure { - CIRCUIT_MODEL_STRUCTURE_TREE, - CIRCUIT_MODEL_STRUCTURE_ONELEVEL, - CIRCUIT_MODEL_STRUCTURE_MULTILEVEL, + CIRCUIT_MODEL_STRUCTURE_TREE, + CIRCUIT_MODEL_STRUCTURE_ONELEVEL, + CIRCUIT_MODEL_STRUCTURE_MULTILEVEL, CIRCUIT_MODEL_STRUCTURE_CROSSBAR, NUM_CIRCUIT_MODEL_STRUCTURE_TYPES }; /* Strings correspond to each type of mux structure */ -constexpr std::array CIRCUIT_MODEL_STRUCTURE_TYPE_STRING = {{"tree", "one_level", "multi_level", "crossbar"}}; +constexpr std::array + CIRCUIT_MODEL_STRUCTURE_TYPE_STRING = { + {"tree", "one_level", "multi_level", "crossbar"}}; enum e_circuit_model_buffer_type { - CIRCUIT_MODEL_BUF_INV, + CIRCUIT_MODEL_BUF_INV, CIRCUIT_MODEL_BUF_BUF, NUM_CIRCUIT_MODEL_BUF_TYPES }; /* Strings correspond to each type of buffer */ -constexpr std::array CIRCUIT_MODEL_BUFFER_TYPE_STRING = {{"inverter", "buffer"}}; +constexpr std::array + CIRCUIT_MODEL_BUFFER_TYPE_STRING = {{"inverter", "buffer"}}; enum e_circuit_model_pass_gate_logic_type { - CIRCUIT_MODEL_PASS_GATE_TRANSMISSION, + CIRCUIT_MODEL_PASS_GATE_TRANSMISSION, CIRCUIT_MODEL_PASS_GATE_TRANSISTOR, - CIRCUIT_MODEL_PASS_GATE_RRAM, /* RRAM can be treated as a special type of pass-gate logic */ - CIRCUIT_MODEL_PASS_GATE_STDCELL, /* Standard cell as a special type of pass-gate logic */ + CIRCUIT_MODEL_PASS_GATE_RRAM, /* RRAM can be treated as a special type of + pass-gate logic */ + CIRCUIT_MODEL_PASS_GATE_STDCELL, /* Standard cell as a special type of + pass-gate logic */ NUM_CIRCUIT_MODEL_PASS_GATE_TYPES }; /* Strings correspond to each type of buffer */ -constexpr std::array CIRCUIT_MODEL_PASSGATE_TYPE_STRING = {{"transmission_gate", "pass_transistor", "rram", "standard_cell"}}; +constexpr std::array + CIRCUIT_MODEL_PASSGATE_TYPE_STRING = { + {"transmission_gate", "pass_transistor", "rram", "standard_cell"}}; enum e_circuit_model_gate_type { - CIRCUIT_MODEL_GATE_AND, + CIRCUIT_MODEL_GATE_AND, CIRCUIT_MODEL_GATE_OR, CIRCUIT_MODEL_GATE_MUX2, NUM_CIRCUIT_MODEL_GATE_TYPES }; /* Strings correspond to each type of logic gate */ -constexpr std::array CIRCUIT_MODEL_GATE_TYPE_STRING = {{"AND", "OR", "MUX2"}}; +constexpr std::array + CIRCUIT_MODEL_GATE_TYPE_STRING = {{"AND", "OR", "MUX2"}}; -enum e_wire_model_type { - WIRE_MODEL_PI, - WIRE_MODEL_T, - NUM_WIRE_MODEL_TYPES -}; +enum e_wire_model_type { WIRE_MODEL_PI, WIRE_MODEL_T, NUM_WIRE_MODEL_TYPES }; /* Strings correspond to each type of logic gate */ -constexpr std::array WIRE_MODEL_TYPE_STRING = {{"pi", "t"}}; +constexpr std::array WIRE_MODEL_TYPE_STRING = + {{"pi", "t"}}; enum e_circuit_model_port_type { - CIRCUIT_MODEL_PORT_INPUT, - CIRCUIT_MODEL_PORT_OUTPUT, - CIRCUIT_MODEL_PORT_INOUT, - CIRCUIT_MODEL_PORT_CLOCK, + CIRCUIT_MODEL_PORT_INPUT, + CIRCUIT_MODEL_PORT_OUTPUT, + CIRCUIT_MODEL_PORT_INOUT, + CIRCUIT_MODEL_PORT_CLOCK, CIRCUIT_MODEL_PORT_SRAM, CIRCUIT_MODEL_PORT_BL, CIRCUIT_MODEL_PORT_BLB, @@ -105,32 +114,37 @@ enum e_circuit_model_port_type { NUM_CIRCUIT_MODEL_PORT_TYPES }; /* Strings correspond to each port type */ -constexpr std::array CIRCUIT_MODEL_PORT_TYPE_STRING = {{"input", "output", "inout", "clock", "sram", "bl", "blb", "wl", "wlb", "wlr"}}; +constexpr std::array + CIRCUIT_MODEL_PORT_TYPE_STRING = {{"input", "output", "inout", "clock", + "sram", "bl", "blb", "wl", "wlb", "wlr"}}; enum e_circuit_model_delay_type { - CIRCUIT_MODEL_DELAY_RISE, + CIRCUIT_MODEL_DELAY_RISE, CIRCUIT_MODEL_DELAY_FALL, NUM_CIRCUIT_MODEL_DELAY_TYPES }; /* Strings correspond to each delay type */ -constexpr std::array CIRCUIT_MODEL_DELAY_TYPE_STRING = {{"rise", "fall"}}; +constexpr std::array + CIRCUIT_MODEL_DELAY_TYPE_STRING = {{"rise", "fall"}}; /******************************************************************** * Types of configuration protocol - * 1. configurable memories are organized and accessed as standalone elements + * 1. configurable memories are organized and accessed as standalone elements * 2. configurable memories are organized and accessed by a scan-chain - * 3. configurable memories are organized and accessed by memory bank - * 4. configurable memories are organized and accessed by frames + * 3. configurable memories are organized and accessed by memory bank + * 4. configurable memories are organized and accessed by frames */ enum e_config_protocol_type { - CONFIG_MEM_STANDALONE, - CONFIG_MEM_SCAN_CHAIN, - CONFIG_MEM_MEMORY_BANK, - CONFIG_MEM_QL_MEMORY_BANK, - CONFIG_MEM_FRAME_BASED, + CONFIG_MEM_STANDALONE, + CONFIG_MEM_SCAN_CHAIN, + CONFIG_MEM_MEMORY_BANK, + CONFIG_MEM_QL_MEMORY_BANK, + CONFIG_MEM_FRAME_BASED, NUM_CONFIG_PROTOCOL_TYPES }; -constexpr std::array CONFIG_PROTOCOL_TYPE_STRING = {{"standalone", "scan_chain", "memory_bank", "ql_memory_bank", "frame_based"}}; +constexpr std::array + CONFIG_PROTOCOL_TYPE_STRING = {{"standalone", "scan_chain", "memory_bank", + "ql_memory_bank", "frame_based"}}; #endif diff --git a/libs/libarchopenfpga/src/config_protocol.cpp b/libs/libarchopenfpga/src/config_protocol.cpp index a5aa748e8..2a617830e 100644 --- a/libs/libarchopenfpga/src/config_protocol.cpp +++ b/libs/libarchopenfpga/src/config_protocol.cpp @@ -1,8 +1,8 @@ +#include "config_protocol.h" + #include "vtr_assert.h" #include "vtr_log.h" -#include "config_protocol.h" - /************************************************************************ * Member functions for class ConfigProtocol ***********************************************************************/ @@ -10,28 +10,20 @@ /************************************************************************ * Constructors ***********************************************************************/ -ConfigProtocol::ConfigProtocol() { - return; -} +ConfigProtocol::ConfigProtocol() { return; } /************************************************************************ * Public Accessors ***********************************************************************/ -e_config_protocol_type ConfigProtocol::type() const { - return type_; -} +e_config_protocol_type ConfigProtocol::type() const { return type_; } std::string ConfigProtocol::memory_model_name() const { return memory_model_name_; } -CircuitModelId ConfigProtocol::memory_model() const { - return memory_model_; -} +CircuitModelId ConfigProtocol::memory_model() const { return memory_model_; } -int ConfigProtocol::num_regions() const { - return num_regions_; -} +int ConfigProtocol::num_regions() const { return num_regions_; } e_blwl_protocol_type ConfigProtocol::bl_protocol_type() const { return bl_protocol_type_; @@ -45,9 +37,7 @@ CircuitModelId ConfigProtocol::bl_memory_model() const { return bl_memory_model_; } -size_t ConfigProtocol::bl_num_banks() const { - return bl_num_banks_; -} +size_t ConfigProtocol::bl_num_banks() const { return bl_num_banks_; } e_blwl_protocol_type ConfigProtocol::wl_protocol_type() const { return wl_protocol_type_; @@ -61,9 +51,7 @@ CircuitModelId ConfigProtocol::wl_memory_model() const { return wl_memory_model_; } -size_t ConfigProtocol::wl_num_banks() const { - return wl_num_banks_; -} +size_t ConfigProtocol::wl_num_banks() const { return wl_num_banks_; } /************************************************************************ * Public Mutators @@ -72,7 +60,8 @@ void ConfigProtocol::set_type(const e_config_protocol_type& type) { type_ = type; } -void ConfigProtocol::set_memory_model_name(const std::string& memory_model_name) { +void ConfigProtocol::set_memory_model_name( + const std::string& memory_model_name) { memory_model_name_ = memory_model_name; } @@ -86,15 +75,20 @@ void ConfigProtocol::set_num_regions(const int& num_regions) { void ConfigProtocol::set_bl_protocol_type(const e_blwl_protocol_type& type) { if (CONFIG_MEM_QL_MEMORY_BANK != type_) { - VTR_LOG_ERROR("BL protocol type is only applicable for configuration protocol '%d'", CONFIG_PROTOCOL_TYPE_STRING[type_]); + VTR_LOG_ERROR( + "BL protocol type is only applicable for configuration protocol '%d'", + CONFIG_PROTOCOL_TYPE_STRING[type_]); return; } bl_protocol_type_ = type; } -void ConfigProtocol::set_bl_memory_model_name(const std::string& memory_model_name) { +void ConfigProtocol::set_bl_memory_model_name( + const std::string& memory_model_name) { if (BLWL_PROTOCOL_SHIFT_REGISTER != bl_protocol_type_) { - VTR_LOG_ERROR("BL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[bl_protocol_type_]); + VTR_LOG_ERROR( + "BL protocol memory model is only applicable when '%d' is defined", + BLWL_PROTOCOL_TYPE_STRING[bl_protocol_type_]); return; } bl_memory_model_name_ = memory_model_name; @@ -102,7 +96,9 @@ void ConfigProtocol::set_bl_memory_model_name(const std::string& memory_model_na void ConfigProtocol::set_bl_memory_model(const CircuitModelId& memory_model) { if (BLWL_PROTOCOL_SHIFT_REGISTER != bl_protocol_type_) { - VTR_LOG_ERROR("BL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[bl_protocol_type_]); + VTR_LOG_ERROR( + "BL protocol memory model is only applicable when '%d' is defined", + BLWL_PROTOCOL_TYPE_STRING[bl_protocol_type_]); return; } bl_memory_model_ = memory_model; @@ -110,24 +106,30 @@ void ConfigProtocol::set_bl_memory_model(const CircuitModelId& memory_model) { void ConfigProtocol::set_bl_num_banks(const size_t& num_banks) { if (BLWL_PROTOCOL_SHIFT_REGISTER != bl_protocol_type_) { - VTR_LOG_ERROR("BL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[bl_protocol_type_]); + VTR_LOG_ERROR( + "BL protocol memory model is only applicable when '%d' is defined", + BLWL_PROTOCOL_TYPE_STRING[bl_protocol_type_]); return; } bl_num_banks_ = num_banks; } - void ConfigProtocol::set_wl_protocol_type(const e_blwl_protocol_type& type) { if (CONFIG_MEM_QL_MEMORY_BANK != type_) { - VTR_LOG_ERROR("WL protocol type is only applicable for configuration protocol '%d'", CONFIG_PROTOCOL_TYPE_STRING[type_]); + VTR_LOG_ERROR( + "WL protocol type is only applicable for configuration protocol '%d'", + CONFIG_PROTOCOL_TYPE_STRING[type_]); return; } wl_protocol_type_ = type; } -void ConfigProtocol::set_wl_memory_model_name(const std::string& memory_model_name) { +void ConfigProtocol::set_wl_memory_model_name( + const std::string& memory_model_name) { if (BLWL_PROTOCOL_SHIFT_REGISTER != wl_protocol_type_) { - VTR_LOG_ERROR("WL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[wl_protocol_type_]); + VTR_LOG_ERROR( + "WL protocol memory model is only applicable when '%d' is defined", + BLWL_PROTOCOL_TYPE_STRING[wl_protocol_type_]); return; } wl_memory_model_name_ = memory_model_name; @@ -135,7 +137,9 @@ void ConfigProtocol::set_wl_memory_model_name(const std::string& memory_model_na void ConfigProtocol::set_wl_memory_model(const CircuitModelId& memory_model) { if (BLWL_PROTOCOL_SHIFT_REGISTER != wl_protocol_type_) { - VTR_LOG_ERROR("WL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[wl_protocol_type_]); + VTR_LOG_ERROR( + "WL protocol memory model is only applicable when '%d' is defined", + BLWL_PROTOCOL_TYPE_STRING[wl_protocol_type_]); return; } wl_memory_model_ = memory_model; @@ -143,9 +147,10 @@ void ConfigProtocol::set_wl_memory_model(const CircuitModelId& memory_model) { void ConfigProtocol::set_wl_num_banks(const size_t& num_banks) { if (BLWL_PROTOCOL_SHIFT_REGISTER != wl_protocol_type_) { - VTR_LOG_ERROR("WL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[wl_protocol_type_]); + VTR_LOG_ERROR( + "WL protocol memory model is only applicable when '%d' is defined", + BLWL_PROTOCOL_TYPE_STRING[wl_protocol_type_]); return; } wl_num_banks_ = num_banks; } - diff --git a/libs/libarchopenfpga/src/config_protocol.h b/libs/libarchopenfpga/src/config_protocol.h index 79bda1a46..3ef7f59d4 100644 --- a/libs/libarchopenfpga/src/config_protocol.h +++ b/libs/libarchopenfpga/src/config_protocol.h @@ -2,8 +2,9 @@ #define CONFIG_PROTOCOL_H #include -#include "circuit_types.h" + #include "circuit_library_fwd.h" +#include "circuit_types.h" /* Data type to define the protocol through which BL/WL can be manipulated */ enum e_blwl_protocol_type { @@ -12,71 +13,80 @@ enum e_blwl_protocol_type { BLWL_PROTOCOL_SHIFT_REGISTER, NUM_BLWL_PROTOCOL_TYPES }; -constexpr std::array BLWL_PROTOCOL_TYPE_STRING = {{"flatten", "decoder", "shift_register"}}; +constexpr std::array + BLWL_PROTOCOL_TYPE_STRING = {{"flatten", "decoder", "shift_register"}}; /******************************************************************** * A data structure to store configuration protocol information *******************************************************************/ class ConfigProtocol { - public: /* Constructors */ - ConfigProtocol(); - public: /* Public Accessors */ - e_config_protocol_type type() const; - std::string memory_model_name() const; - CircuitModelId memory_model() const; - int num_regions() const; + public: /* Constructors */ + ConfigProtocol(); - e_blwl_protocol_type bl_protocol_type() const; - std::string bl_memory_model_name() const; - CircuitModelId bl_memory_model() const; - size_t bl_num_banks() const; - e_blwl_protocol_type wl_protocol_type() const; - 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); + public: /* Public Accessors */ + e_config_protocol_type type() const; + std::string memory_model_name() const; + CircuitModelId memory_model() const; + int num_regions() const; - 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); - void set_bl_num_banks(const size_t& num_banks); - void set_wl_protocol_type(const e_blwl_protocol_type& type); - void set_wl_memory_model_name(const std::string& memory_model_name); - void set_wl_memory_model(const CircuitModelId& memory_model); - void set_wl_num_banks(const size_t& num_banks); - private: /* Internal data */ - /* The type of configuration protocol. - * In other words, it is about how to organize and access each configurable memory - */ - e_config_protocol_type type_; + e_blwl_protocol_type bl_protocol_type() const; + std::string bl_memory_model_name() const; + CircuitModelId bl_memory_model() const; + size_t bl_num_banks() const; + e_blwl_protocol_type wl_protocol_type() const; + std::string wl_memory_model_name() const; + CircuitModelId wl_memory_model() const; + size_t wl_num_banks() const; - /* The circuit model of configuration memory to be used in the protocol */ - std::string memory_model_name_; - CircuitModelId memory_model_; + 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); - /* Number of configurable regions */ - int num_regions_; + 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); + void set_bl_num_banks(const size_t& num_banks); + void set_wl_protocol_type(const e_blwl_protocol_type& type); + void set_wl_memory_model_name(const std::string& memory_model_name); + void set_wl_memory_model(const CircuitModelId& memory_model); + void set_wl_num_banks(const size_t& num_banks); - /* BL & WL protocol: This is only applicable to memory-bank configuration protocols - * - type: defines which protocol to be used. By default, we consider decoders - * - bl/wl_memory_model: defines the circuit model to be used when building shift register chains for BL/WL configuration. - * It must be a valid CCFF circuit model. This is only applicable when shift-register protocol is selected - * for BL or WL. - * - bl/wl_num_banks: defines the number of independent shift register chains (with separated head and tail ports) - * for a given BL protocol per configuration region - */ - e_blwl_protocol_type bl_protocol_type_ = BLWL_PROTOCOL_DECODER; - std::string bl_memory_model_name_; - CircuitModelId bl_memory_model_; - size_t bl_num_banks_; - e_blwl_protocol_type wl_protocol_type_ = BLWL_PROTOCOL_DECODER; - std::string wl_memory_model_name_; - CircuitModelId wl_memory_model_; - size_t wl_num_banks_; + private: /* Internal data */ + /* The type of configuration protocol. + * In other words, it is about how to organize and access each configurable + * memory + */ + e_config_protocol_type type_; + + /* The circuit model of configuration memory to be used in the protocol */ + std::string memory_model_name_; + CircuitModelId memory_model_; + + /* Number of configurable regions */ + int num_regions_; + + /* BL & WL protocol: This is only applicable to memory-bank configuration + * protocols + * - type: defines which protocol to be used. By default, we + * consider decoders + * - bl/wl_memory_model: defines the circuit model to be used when building + * shift register chains for BL/WL configuration. It must be a valid CCFF + * circuit model. This is only applicable when shift-register protocol is + * selected for BL or WL. + * - bl/wl_num_banks: defines the number of independent shift register + * chains (with separated head and tail ports) for a given BL protocol per + * configuration region + */ + e_blwl_protocol_type bl_protocol_type_ = BLWL_PROTOCOL_DECODER; + std::string bl_memory_model_name_; + CircuitModelId bl_memory_model_; + size_t bl_num_banks_; + e_blwl_protocol_type wl_protocol_type_ = BLWL_PROTOCOL_DECODER; + std::string wl_memory_model_name_; + CircuitModelId wl_memory_model_; + size_t wl_num_banks_; }; #endif diff --git a/libs/libarchopenfpga/src/openfpga_arch.h b/libs/libarchopenfpga/src/openfpga_arch.h index 6867a4bb4..3a05d91dd 100644 --- a/libs/libarchopenfpga/src/openfpga_arch.h +++ b/libs/libarchopenfpga/src/openfpga_arch.h @@ -1,15 +1,15 @@ #ifndef OPENFPGA_ARCH_H #define OPENFPGA_ARCH_H -#include #include +#include -#include "circuit_library.h" -#include "technology_library.h" -#include "config_protocol.h" #include "arch_direct.h" -#include "tile_annotation.h" +#include "circuit_library.h" +#include "config_protocol.h" #include "pb_type_annotation.h" +#include "technology_library.h" +#include "tile_annotation.h" /* namespace openfpga begins */ namespace openfpga { @@ -17,7 +17,7 @@ namespace openfpga { /* A unified data structure to store circuit-level settings, * including circuit library, technology library and simulation parameters * - * Note: + * Note: * Once this struct is built by function read_xml_openfpga_arch() * It should be READ-ONLY! Any modification should not be applied later * This is to keep everything well modularized @@ -25,44 +25,44 @@ namespace openfpga { struct Arch { /* Circuit models */ CircuitLibrary circuit_lib; - + /* Technology devices */ TechnologyLibrary tech_lib; /* Binding between circuit models and technology models */ - std::map circuit_tech_binding; + std::map circuit_tech_binding; /* Configuration protocol settings */ ConfigProtocol config_protocol; - /* Mapping from the names of routing switches - * to circuit models in circuit library + /* Mapping from the names of routing switches + * to circuit models in circuit library */ std::map cb_switch2circuit; std::map sb_switch2circuit; /* Mapping from the names of routing segments - * to circuit models in circuit library + * to circuit models in circuit library */ std::map routing_seg2circuit; /* Mapping from the names of direct connection - * to circuit models in circuit library + * to circuit models in circuit library */ ArchDirect arch_direct; /* Physical tile annotations: * Global port definition for tile ports - */ + */ TileAnnotation tile_annotations; - /* Pb type annotations + /* Pb type annotations * Bind from operating to physical * Bind from physical to circuit model */ std::vector pb_type_annotations; }; -} /* namespace openfpga ends */ +} // namespace openfpga #endif diff --git a/libs/libarchopenfpga/src/openfpga_arch_linker.cpp b/libs/libarchopenfpga/src/openfpga_arch_linker.cpp index 33009f537..2c4c10b29 100644 --- a/libs/libarchopenfpga/src/openfpga_arch_linker.cpp +++ b/libs/libarchopenfpga/src/openfpga_arch_linker.cpp @@ -2,48 +2,56 @@ * This file includes the functions that build links between * data structures inside the openfpga arch data structure *******************************************************************/ -#include "vtr_log.h" -#include "vtr_assert.h" - #include "openfpga_arch_linker.h" +#include "vtr_assert.h" +#include "vtr_log.h" + /******************************************************************** * Link the circuit model inside configuration protocol * to these circuit models defined in circuit library *******************************************************************/ void link_config_protocol_to_circuit_library(openfpga::Arch& openfpga_arch) { - CircuitModelId config_memory_model = openfpga_arch.circuit_lib.model(openfpga_arch.config_protocol.memory_model_name()); + CircuitModelId config_memory_model = openfpga_arch.circuit_lib.model( + openfpga_arch.config_protocol.memory_model_name()); /* Error out if the circuit model id is invalid */ if (CircuitModelId::INVALID() == config_memory_model) { - VTR_LOG("Invalid memory model name '%s' defined in !", - openfpga_arch.config_protocol.memory_model_name().c_str()); + VTR_LOG( + "Invalid memory model name '%s' defined in !", + openfpga_arch.config_protocol.memory_model_name().c_str()); exit(1); } - openfpga_arch.config_protocol.set_memory_model(config_memory_model); + openfpga_arch.config_protocol.set_memory_model(config_memory_model); /* Optional: we need to bind the memory model for BL/WL protocols */ if (!openfpga_arch.config_protocol.bl_memory_model_name().empty()) { - CircuitModelId bl_memory_model = openfpga_arch.circuit_lib.model(openfpga_arch.config_protocol.bl_memory_model_name()); + CircuitModelId bl_memory_model = openfpga_arch.circuit_lib.model( + openfpga_arch.config_protocol.bl_memory_model_name()); /* Error out if the circuit model id is invalid */ if (CircuitModelId::INVALID() == bl_memory_model) { - VTR_LOG("Invalid bl memory model name '%s' defined in !", - openfpga_arch.config_protocol.bl_memory_model_name().c_str()); + VTR_LOG( + "Invalid bl memory model name '%s' defined in " + "!", + openfpga_arch.config_protocol.bl_memory_model_name().c_str()); exit(1); } - openfpga_arch.config_protocol.set_bl_memory_model(bl_memory_model); + openfpga_arch.config_protocol.set_bl_memory_model(bl_memory_model); } if (!openfpga_arch.config_protocol.wl_memory_model_name().empty()) { - CircuitModelId wl_memory_model = openfpga_arch.circuit_lib.model(openfpga_arch.config_protocol.wl_memory_model_name()); + CircuitModelId wl_memory_model = openfpga_arch.circuit_lib.model( + openfpga_arch.config_protocol.wl_memory_model_name()); /* Error out if the circuit model id is invalid */ if (CircuitModelId::INVALID() == wl_memory_model) { - VTR_LOG("Invalid wl memory model name '%s' defined in !", - openfpga_arch.config_protocol.wl_memory_model_name().c_str()); + VTR_LOG( + "Invalid wl memory model name '%s' defined in " + "!", + openfpga_arch.config_protocol.wl_memory_model_name().c_str()); exit(1); } - openfpga_arch.config_protocol.set_wl_memory_model(wl_memory_model); + openfpga_arch.config_protocol.set_wl_memory_model(wl_memory_model); } } @@ -55,13 +63,16 @@ void bind_circuit_model_to_technology_model(openfpga::Arch& openfpga_arch) { /* Ensure a clean start */ openfpga_arch.circuit_tech_binding.clear(); - for (const CircuitModelId& circuit_model : openfpga_arch.circuit_lib.models()) { - const std::string device_model_name = openfpga_arch.circuit_lib.device_model_name(circuit_model); + for (const CircuitModelId& circuit_model : + openfpga_arch.circuit_lib.models()) { + const std::string device_model_name = + openfpga_arch.circuit_lib.device_model_name(circuit_model); if (true == device_model_name.empty()) { continue; } /* Try to find the device model name in technology library */ - TechnologyModelId tech_model = openfpga_arch.tech_lib.model(device_model_name); + TechnologyModelId tech_model = + openfpga_arch.tech_lib.model(device_model_name); if (false == openfpga_arch.tech_lib.valid_model_id(tech_model)) { VTR_LOG("Invalid device model name '%s' defined in circuit model '%s'!", device_model_name.c_str(), @@ -78,10 +89,10 @@ void bind_circuit_model_to_technology_model(openfpga::Arch& openfpga_arch) { * to a default SRAM circuit model. * This function aims to ease the XML writing, allowing users to skip * the circuit model definition for SRAM ports that are used by default - * TODO: Maybe deprecated as we prefer strict definition + * TODO: Maybe deprecated as we prefer strict definition *******************************************************************/ -void config_circuit_models_sram_port_to_default_sram_model(CircuitLibrary& circuit_lib, - const CircuitModelId& default_sram_model) { +void config_circuit_models_sram_port_to_default_sram_model( + CircuitLibrary& circuit_lib, const CircuitModelId& default_sram_model) { VTR_ASSERT(CircuitModelId::INVALID() != default_sram_model); for (const auto& model : circuit_lib.models()) { @@ -94,26 +105,32 @@ void config_circuit_models_sram_port_to_default_sram_model(CircuitLibrary& circu /* Write for the default SRAM SPICE model! */ circuit_lib.set_port_tri_state_model_id(port, default_sram_model); - /* Only show warning when we try to override the given spice_model_name ! */ - if (true == circuit_lib.port_tri_state_model_name(port).empty()) { - VTR_LOG("Use the default configurable memory model '%s' for circuit model '%s' port '%s')\n", - circuit_lib.model_name(default_sram_model).c_str(), - circuit_lib.model_name(model).c_str(), - circuit_lib.port_prefix(port).c_str()); + /* Only show warning when we try to override the given spice_model_name ! + */ + if (true == circuit_lib.port_tri_state_model_name(port).empty()) { + VTR_LOG( + "Use the default configurable memory model '%s' for circuit model " + "'%s' port '%s')\n", + circuit_lib.model_name(default_sram_model).c_str(), + circuit_lib.model_name(model).c_str(), + circuit_lib.port_prefix(port).c_str()); continue; } /* Give a warning !!! */ - if (circuit_lib.model_name(default_sram_model) != circuit_lib.port_tri_state_model_name(port)) { - VTR_LOG_WARN("Overwrite SRAM circuit model for circuit model port (name:%s, port:%s) to be the correct one (name:%s)!\n", - circuit_lib.model_name(model).c_str(), - circuit_lib.port_prefix(port).c_str(), - circuit_lib.model_name(default_sram_model).c_str()); + if (circuit_lib.model_name(default_sram_model) != + circuit_lib.port_tri_state_model_name(port)) { + VTR_LOG_WARN( + "Overwrite SRAM circuit model for circuit model port (name:%s, " + "port:%s) to be the correct one (name:%s)!\n", + circuit_lib.model_name(model).c_str(), + circuit_lib.port_prefix(port).c_str(), + circuit_lib.model_name(default_sram_model).c_str()); } } } /* Rebuild the submodels for circuit_library - * because we have created links for ports + * because we have created links for ports */ circuit_lib.build_model_links(); } diff --git a/libs/libarchopenfpga/src/openfpga_arch_linker.h b/libs/libarchopenfpga/src/openfpga_arch_linker.h index a6c966058..d4c9671bb 100644 --- a/libs/libarchopenfpga/src/openfpga_arch_linker.h +++ b/libs/libarchopenfpga/src/openfpga_arch_linker.h @@ -7,7 +7,7 @@ void link_config_protocol_to_circuit_library(openfpga::Arch& openfpga_arch); void bind_circuit_model_to_technology_model(openfpga::Arch& openfpga_arch); -void config_circuit_models_sram_port_to_default_sram_model(CircuitLibrary& circuit_lib, - const CircuitModelId& default_sram_model); +void config_circuit_models_sram_port_to_default_sram_model( + CircuitLibrary& circuit_lib, const CircuitModelId& default_sram_model); #endif diff --git a/libs/libarchopenfpga/src/pb_type_annotation.cpp b/libs/libarchopenfpga/src/pb_type_annotation.cpp index 1a1a7ea31..24c1e4307 100644 --- a/libs/libarchopenfpga/src/pb_type_annotation.cpp +++ b/libs/libarchopenfpga/src/pb_type_annotation.cpp @@ -1,20 +1,20 @@ /************************************************************************ * Member functions for class PbTypeAnnotation ***********************************************************************/ -#include -#include "vtr_log.h" -#include "vtr_assert.h" #include "pb_type_annotation.h" +#include + +#include "vtr_assert.h" +#include "vtr_log.h" + /* namespace openfpga begins */ namespace openfpga { /************************************************************************ * Constructors ***********************************************************************/ -PbTypeAnnotation::PbTypeAnnotation() { - return; -} +PbTypeAnnotation::PbTypeAnnotation() { return; } /************************************************************************ * Public Accessors @@ -23,7 +23,8 @@ std::string PbTypeAnnotation::operating_pb_type_name() const { return operating_pb_type_name_; } -std::vector PbTypeAnnotation::operating_parent_pb_type_names() const { +std::vector PbTypeAnnotation::operating_parent_pb_type_names() + const { return operating_parent_pb_type_names_; } @@ -32,16 +33,16 @@ std::vector PbTypeAnnotation::operating_parent_mode_names() const { } bool PbTypeAnnotation::is_operating_pb_type() const { - return (false == operating_pb_type_name_.empty()) - && (false == physical_pb_type_name_.empty()); + return (false == operating_pb_type_name_.empty()) && + (false == physical_pb_type_name_.empty()); } - std::string PbTypeAnnotation::physical_pb_type_name() const { return physical_pb_type_name_; } -std::vector PbTypeAnnotation::physical_parent_pb_type_names() const { +std::vector PbTypeAnnotation::physical_parent_pb_type_names() + const { return physical_parent_pb_type_names_; } @@ -50,21 +51,17 @@ std::vector PbTypeAnnotation::physical_parent_mode_names() const { } bool PbTypeAnnotation::is_physical_pb_type() const { - return (true == operating_pb_type_name_.empty()) - && (false == physical_pb_type_name_.empty()); + return (true == operating_pb_type_name_.empty()) && + (false == physical_pb_type_name_.empty()); } std::string PbTypeAnnotation::physical_mode_name() const { return physical_mode_name_; } -std::string PbTypeAnnotation::idle_mode_name() const { - return idle_mode_name_; -} +std::string PbTypeAnnotation::idle_mode_name() const { return idle_mode_name_; } -std::vector PbTypeAnnotation::mode_bits() const { - return mode_bits_; -} +std::vector PbTypeAnnotation::mode_bits() const { return mode_bits_; } std::string PbTypeAnnotation::circuit_model_name() const { return circuit_model_name_; @@ -86,8 +83,10 @@ std::vector PbTypeAnnotation::port_names() const { return keys; } -std::map> PbTypeAnnotation::physical_pb_type_port(const std::string& port_name) const { - std::map>>::const_iterator it = operating_pb_type_ports_.find(port_name); +std::map> PbTypeAnnotation::physical_pb_type_port( + const std::string& port_name) const { + std::map>>::const_iterator + it = operating_pb_type_ports_.find(port_name); if (it == operating_pb_type_ports_.end()) { /* Return an empty port */ return std::map>(); @@ -103,8 +102,10 @@ std::vector PbTypeAnnotation::interconnect_names() const { return keys; } -std::string PbTypeAnnotation::interconnect_circuit_model_name(const std::string& interc_name) const { - std::map::const_iterator it = interconnect_circuit_model_names_.find(interc_name); +std::string PbTypeAnnotation::interconnect_circuit_model_name( + const std::string& interc_name) const { + std::map::const_iterator it = + interconnect_circuit_model_names_.find(interc_name); if (it == interconnect_circuit_model_names_.end()) { return std::string(); } @@ -119,11 +120,13 @@ void PbTypeAnnotation::set_operating_pb_type_name(const std::string& name) { operating_pb_type_name_ = name; } -void PbTypeAnnotation::set_operating_parent_pb_type_names(const std::vector& names) { +void PbTypeAnnotation::set_operating_parent_pb_type_names( + const std::vector& names) { operating_parent_pb_type_names_ = names; } -void PbTypeAnnotation::set_operating_parent_mode_names(const std::vector& names) { +void PbTypeAnnotation::set_operating_parent_mode_names( + const std::vector& names) { operating_parent_mode_names_ = names; } @@ -131,11 +134,13 @@ void PbTypeAnnotation::set_physical_pb_type_name(const std::string& name) { physical_pb_type_name_ = name; } -void PbTypeAnnotation::set_physical_parent_pb_type_names(const std::vector& names) { +void PbTypeAnnotation::set_physical_parent_pb_type_names( + const std::vector& names) { physical_parent_pb_type_names_ = names; } -void PbTypeAnnotation::set_physical_parent_mode_names(const std::vector& names) { +void PbTypeAnnotation::set_physical_parent_mode_names( + const std::vector& names) { physical_parent_mode_names_ = names; } @@ -166,28 +171,35 @@ void PbTypeAnnotation::set_physical_pb_type_index_offset(const int& value) { physical_pb_type_index_offset_ = value; } -void PbTypeAnnotation::add_pb_type_port_pair(const std::string& operating_pb_port_name, - const BasicPort& physical_pb_port) { +void PbTypeAnnotation::add_pb_type_port_pair( + const std::string& operating_pb_port_name, + const BasicPort& physical_pb_port) { /* Give a warning if the operating_pb_port_name already exist */ - std::map>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); + std::map>>::const_iterator + it = operating_pb_type_ports_.find(operating_pb_port_name); /* If not exist, initialize and set a default value */ if (it == operating_pb_type_ports_.end()) { - operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0, 0}; + operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0, + 0}; /* We can return early */ return; } - /* If the physical port is not in the list, we create one and set a default value */ - if (0 == operating_pb_type_ports_[operating_pb_port_name].count(physical_pb_port)) { - operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0, 0}; + /* If the physical port is not in the list, we create one and set a default + * value */ + if (0 == operating_pb_type_ports_[operating_pb_port_name].count( + physical_pb_port)) { + operating_pb_type_ports_[operating_pb_port_name][physical_pb_port] = {0, 0, + 0}; } } -void PbTypeAnnotation::set_physical_pin_initial_offset(const std::string& operating_pb_port_name, - const BasicPort& physical_pb_port, - const int& physical_pin_initial_offset) { - std::map>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); +void PbTypeAnnotation::set_physical_pin_initial_offset( + const std::string& operating_pb_port_name, const BasicPort& physical_pb_port, + const int& physical_pin_initial_offset) { + std::map>>::const_iterator + it = operating_pb_type_ports_.find(operating_pb_port_name); if (it == operating_pb_type_ports_.end()) { VTR_LOG_ERROR("The operating pb_type port '%s' is not valid!\n", @@ -195,22 +207,25 @@ void PbTypeAnnotation::set_physical_pin_initial_offset(const std::string& operat exit(1); } - if (operating_pb_type_ports_[operating_pb_port_name].end() == operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) { - VTR_LOG_ERROR("The physical pb_type port '%s[%lu:%lu]' definition for operating pb_type port '%s' is not valid!\n", - physical_pb_port.get_name().c_str(), - physical_pb_port.get_lsb(), - physical_pb_port.get_msb(), - operating_pb_port_name.c_str()); + if (operating_pb_type_ports_[operating_pb_port_name].end() == + operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) { + VTR_LOG_ERROR( + "The physical pb_type port '%s[%lu:%lu]' definition for operating " + "pb_type port '%s' is not valid!\n", + physical_pb_port.get_name().c_str(), physical_pb_port.get_lsb(), + physical_pb_port.get_msb(), operating_pb_port_name.c_str()); exit(1); } - operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][0] = physical_pin_initial_offset; + operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][0] = + physical_pin_initial_offset; } -void PbTypeAnnotation::set_physical_pin_rotate_offset(const std::string& operating_pb_port_name, - const BasicPort& physical_pb_port, - const int& physical_pin_rotate_offset) { - std::map>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); +void PbTypeAnnotation::set_physical_pin_rotate_offset( + const std::string& operating_pb_port_name, const BasicPort& physical_pb_port, + const int& physical_pin_rotate_offset) { + std::map>>::const_iterator + it = operating_pb_type_ports_.find(operating_pb_port_name); if (it == operating_pb_type_ports_.end()) { VTR_LOG_ERROR("The operating pb_type port '%s' is not valid!\n", @@ -218,22 +233,25 @@ void PbTypeAnnotation::set_physical_pin_rotate_offset(const std::string& operati exit(1); } - if (operating_pb_type_ports_[operating_pb_port_name].end() == operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) { - VTR_LOG_ERROR("The physical pb_type port '%s[%lu:%lu]' definition for operating pb_type port '%s' is not valid!\n", - physical_pb_port.get_name().c_str(), - physical_pb_port.get_lsb(), - physical_pb_port.get_msb(), - operating_pb_port_name.c_str()); + if (operating_pb_type_ports_[operating_pb_port_name].end() == + operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) { + VTR_LOG_ERROR( + "The physical pb_type port '%s[%lu:%lu]' definition for operating " + "pb_type port '%s' is not valid!\n", + physical_pb_port.get_name().c_str(), physical_pb_port.get_lsb(), + physical_pb_port.get_msb(), operating_pb_port_name.c_str()); exit(1); } - operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][1] = physical_pin_rotate_offset; + operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][1] = + physical_pin_rotate_offset; } -void PbTypeAnnotation::set_physical_port_rotate_offset(const std::string& operating_pb_port_name, - const BasicPort& physical_pb_port, - const int& physical_port_rotate_offset) { - std::map>>::const_iterator it = operating_pb_type_ports_.find(operating_pb_port_name); +void PbTypeAnnotation::set_physical_port_rotate_offset( + const std::string& operating_pb_port_name, const BasicPort& physical_pb_port, + const int& physical_port_rotate_offset) { + std::map>>::const_iterator + it = operating_pb_type_ports_.find(operating_pb_port_name); if (it == operating_pb_type_ports_.end()) { VTR_LOG_ERROR("The operating pb_type port '%s' is not valid!\n", @@ -241,22 +259,24 @@ void PbTypeAnnotation::set_physical_port_rotate_offset(const std::string& operat exit(1); } - if (operating_pb_type_ports_[operating_pb_port_name].end() == operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) { - VTR_LOG_ERROR("The physical pb_type port '%s[%lu:%lu]' definition for operating pb_type port '%s' is not valid!\n", - physical_pb_port.get_name().c_str(), - physical_pb_port.get_lsb(), - physical_pb_port.get_msb(), - operating_pb_port_name.c_str()); + if (operating_pb_type_ports_[operating_pb_port_name].end() == + operating_pb_type_ports_[operating_pb_port_name].find(physical_pb_port)) { + VTR_LOG_ERROR( + "The physical pb_type port '%s[%lu:%lu]' definition for operating " + "pb_type port '%s' is not valid!\n", + physical_pb_port.get_name().c_str(), physical_pb_port.get_lsb(), + physical_pb_port.get_msb(), operating_pb_port_name.c_str()); exit(1); } - operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][2] = physical_port_rotate_offset; + operating_pb_type_ports_[operating_pb_port_name][physical_pb_port][2] = + physical_port_rotate_offset; } - -void PbTypeAnnotation::add_interconnect_circuit_model_pair(const std::string& interc_name, - const std::string& circuit_model_name) { - std::map::const_iterator it = interconnect_circuit_model_names_.find(interc_name); +void PbTypeAnnotation::add_interconnect_circuit_model_pair( + const std::string& interc_name, const std::string& circuit_model_name) { + std::map::const_iterator it = + interconnect_circuit_model_names_.find(interc_name); /* Give a warning if the interconnection name already exist */ if (it != interconnect_circuit_model_names_.end()) { VTR_LOG_WARN("Redefine interconnect '%s' with circuit model '%s'\n", @@ -266,4 +286,4 @@ void PbTypeAnnotation::add_interconnect_circuit_model_pair(const std::string& in interconnect_circuit_model_names_[interc_name] = circuit_model_name; } -} /* namespace openfpga ends */ +} // namespace openfpga diff --git a/libs/libarchopenfpga/src/pb_type_annotation.h b/libs/libarchopenfpga/src/pb_type_annotation.h index 2a0b8804e..df4d0b0ba 100644 --- a/libs/libarchopenfpga/src/pb_type_annotation.h +++ b/libs/libarchopenfpga/src/pb_type_annotation.h @@ -4,9 +4,9 @@ /******************************************************************** * Include header files required by the data structure definition *******************************************************************/ -#include -#include #include +#include +#include #include "openfpga_port.h" @@ -31,157 +31,165 @@ namespace openfpga { * to other data structures, please create another one in other header files *******************************************************************/ class PbTypeAnnotation { - public: /* Constructor */ - PbTypeAnnotation(); - public: /* Public accessors */ - std::string operating_pb_type_name() const; - std::vector operating_parent_pb_type_names() const; - std::vector operating_parent_mode_names() const; - bool is_operating_pb_type() const; - std::string physical_pb_type_name() const; - std::vector physical_parent_pb_type_names() const; - std::vector physical_parent_mode_names() const; - bool is_physical_pb_type() const; - std::string physical_mode_name() const; - std::string idle_mode_name() const; - std::vector mode_bits() const; - std::string circuit_model_name() const; - float physical_pb_type_index_factor() const; - int physical_pb_type_index_offset() const; - std::vector port_names() const; - std::map> physical_pb_type_port(const std::string& port_name) const; - std::vector interconnect_names() const; - std::string interconnect_circuit_model_name(const std::string& interc_name) const; - public: /* Public mutators */ - void set_operating_pb_type_name(const std::string& name); - void set_operating_parent_pb_type_names(const std::vector& names); - void set_operating_parent_mode_names(const std::vector& names); - void set_physical_pb_type_name(const std::string& name); - void set_physical_parent_pb_type_names(const std::vector& names); - void set_physical_parent_mode_names(const std::vector& names); - void set_physical_mode_name(const std::string& name); - void set_idle_mode_name(const std::string& name); - void set_mode_bits(const std::vector& mode_bits); - void set_circuit_model_name(const std::string& name); - void set_physical_pb_type_index_factor(const float& value); - void set_physical_pb_type_index_offset(const int& value); - void add_pb_type_port_pair(const std::string& operating_pb_port_name, - const BasicPort& physical_pb_port); - void set_physical_pin_initial_offset(const std::string& operating_pb_port_name, - const BasicPort& physical_pb_port, - const int& physical_pin_initial_offset); - void set_physical_pin_rotate_offset(const std::string& operating_pb_port_name, - const BasicPort& physical_pb_port, - const int& physical_pin_rotate_offset); - void set_physical_port_rotate_offset(const std::string& operating_pb_port_name, - const BasicPort& physical_pb_port, - const int& physical_port_rotate_offset); - void add_interconnect_circuit_model_pair(const std::string& interc_name, - const std::string& circuit_model_name); - private: /* Internal data */ - /* Binding between physical pb_type and operating pb_type - * both operating and physial pb_type names contain the full names - * defined in the hierarchy of pb_types - * e.g. - * clb.fle[frac_logic].frac_lut6 - * ^ - * | - * mode_name - * - * The pb_type name 'frac_lut6' will be stored in - * either operating or physical pb_type_name - * The parent pb_type and mode names will be stored in - * either operating or physical parent_pb_type_name and parent_mode_names - * - */ - std::string operating_pb_type_name_; - std::vector operating_parent_pb_type_names_; - std::vector operating_parent_mode_names_; + public: /* Constructor */ + PbTypeAnnotation(); - std::string physical_pb_type_name_; - std::vector physical_parent_pb_type_names_; - std::vector physical_parent_mode_names_; + public: /* Public accessors */ + std::string operating_pb_type_name() const; + std::vector operating_parent_pb_type_names() const; + std::vector operating_parent_mode_names() const; + bool is_operating_pb_type() const; + std::string physical_pb_type_name() const; + std::vector physical_parent_pb_type_names() const; + std::vector physical_parent_mode_names() const; + bool is_physical_pb_type() const; + std::string physical_mode_name() const; + std::string idle_mode_name() const; + std::vector mode_bits() const; + std::string circuit_model_name() const; + float physical_pb_type_index_factor() const; + int physical_pb_type_index_offset() const; + std::vector port_names() const; + std::map> physical_pb_type_port( + const std::string& port_name) const; + std::vector interconnect_names() const; + std::string interconnect_circuit_model_name( + const std::string& interc_name) const; - /* Identify which mode is the physical implementation of an operating pb_type */ - std::string physical_mode_name_; + public: /* Public mutators */ + void set_operating_pb_type_name(const std::string& name); + void set_operating_parent_pb_type_names( + const std::vector& names); + void set_operating_parent_mode_names(const std::vector& names); + void set_physical_pb_type_name(const std::string& name); + void set_physical_parent_pb_type_names(const std::vector& names); + void set_physical_parent_mode_names(const std::vector& names); + void set_physical_mode_name(const std::string& name); + void set_idle_mode_name(const std::string& name); + void set_mode_bits(const std::vector& mode_bits); + void set_circuit_model_name(const std::string& name); + void set_physical_pb_type_index_factor(const float& value); + void set_physical_pb_type_index_offset(const int& value); + void add_pb_type_port_pair(const std::string& operating_pb_port_name, + const BasicPort& physical_pb_port); + void set_physical_pin_initial_offset( + const std::string& operating_pb_port_name, + const BasicPort& physical_pb_port, const int& physical_pin_initial_offset); + void set_physical_pin_rotate_offset(const std::string& operating_pb_port_name, + const BasicPort& physical_pb_port, + const int& physical_pin_rotate_offset); + void set_physical_port_rotate_offset( + const std::string& operating_pb_port_name, + const BasicPort& physical_pb_port, const int& physical_port_rotate_offset); + void add_interconnect_circuit_model_pair( + const std::string& interc_name, const std::string& circuit_model_name); - /* Identify in which mode is the pb_type will operate when it is not used */ - std::string idle_mode_name_; + private: /* Internal data */ + /* Binding between physical pb_type and operating pb_type + * both operating and physial pb_type names contain the full names + * defined in the hierarchy of pb_types + * e.g. + * clb.fle[frac_logic].frac_lut6 + * ^ + * | + * mode_name + * + * The pb_type name 'frac_lut6' will be stored in + * either operating or physical pb_type_name + * The parent pb_type and mode names will be stored in + * either operating or physical parent_pb_type_name and parent_mode_names + * + */ + std::string operating_pb_type_name_; + std::vector operating_parent_pb_type_names_; + std::vector operating_parent_mode_names_; - /* Configuration bits to select an operting mode for the circuit mode name */ - std::vector mode_bits_; + std::string physical_pb_type_name_; + std::vector physical_parent_pb_type_names_; + std::vector physical_parent_mode_names_; - /* Circuit mode name linked to a physical pb_type. - * This is only applicable to the physical pb_type - */ - std::string circuit_model_name_; + /* Identify which mode is the physical implementation of an operating pb_type + */ + std::string physical_mode_name_; - /* The factor aims to align the indices for pb_type between operating and physical modes, - * especially when an operating mode contains multiple pb_type (num_pb>1) - * that are linked to the same physical pb_type. - * When number of physical_pb_type is larger than 1, - * the index of pb_type will be multipled by the given factor. - * - * For example, a factor of 2 is used to map - * operating pb_type adder[5] with a full path clb.fle[arith].adder[5] - * to physical pb_type adder[10] with a full path clb.fle[physical].adder[10] - */ - float physical_pb_type_index_factor_; + /* Identify in which mode is the pb_type will operate when it is not used */ + std::string idle_mode_name_; - /* The offset aims to align the indices for pb_type between operating and physical modes, - * especially when an operating mode contains multiple pb_type (num_pb>1) - * that are linked to the same physical pb_type. - * When number of physical_pb_type is larger than 1, - * the index of pb_type will be shifted by the given factor. - * - * For example, an offset of 1 is used to map - * operating pb_type adder[0] with a full path clb.fle[arith].adder[0] - * to physical pb_type adder[1] with a full path clb.fle[physical].adder[1] - */ - int physical_pb_type_index_offset_; + /* Configuration bits to select an operting mode for the circuit mode name */ + std::vector mode_bits_; - /* Link from the pins under an operating pb_type to pairs of - * its physical pb_type and - * - its pin initial offset: the first element of the std::array - * - pin-level rotating offset: the second element of the std::array - * - port-level rotating offset: the third element of the std::array - * - * The offsets aim to align the pin indices for port of pb_type - * between operating and physical modes, especially when an operating - * mode contains multiple pb_type (num_pb>1) that are linked to - * the same physical pb_type. - * When physical_mode_pin_rotate_offset is larger than zero, - * the pin index of pb_type (whose index is large than 1) - * will be shifted by the given offset. - * - * For example, an initial offset of -32 is used to map - * operating pb_type bram[0].dout[32] with a full path memory[dual_port].bram[0] - * operating pb_type bram[0].dout[33] with a full path memory[dual_port].bram[0] - * to - * physical pb_type bram[0].dout_a[0] with a full path memory[physical].bram[0] - * physical pb_type bram[0].dout_a[1] with a full path memory[physical].bram[0] - * - * For example, a pin-level rotating offset of 9 is used to map - * operating pb_type mult_9x9[0].a[0] with a full path mult[frac].mult_9x9[0] - * operating pb_type mult_9x9[0].a[1] with a full path mult[frac].mult_9x9[1] - * to - * physical pb_type mult_36x36.a[0] with a full path mult[physical].mult_36x36[0] - * physical pb_type mult_36x36.a[9] with a full path mult[physical].mult_36x36[0] - * - * For example, a port-level rotating offset of 9 is used to map - * operating pb_type mult_9x9[0].a[0:8] with a full path mult[frac].mult_9x9[0] - * operating pb_type mult_9x9[1].a[0:8] with a full path mult[frac].mult_9x9[1] - * to - * physical pb_type mult_36x36.a[0:8] with a full path mult[physical].mult_36x36[0] - * physical pb_type mult_36x36.a[9:17] with a full path mult[physical].mult_36x36[0] - */ - std::map>> operating_pb_type_ports_; + /* Circuit mode name linked to a physical pb_type. + * This is only applicable to the physical pb_type + */ + std::string circuit_model_name_; - /* Link between the interconnects under this pb_type and circuit model names */ - std::map interconnect_circuit_model_names_; + /* The factor aims to align the indices for pb_type between operating and + * physical modes, especially when an operating mode contains multiple pb_type + * (num_pb>1) that are linked to the same physical pb_type. When number of + * physical_pb_type is larger than 1, the index of pb_type will be multipled + * by the given factor. + * + * For example, a factor of 2 is used to map + * operating pb_type adder[5] with a full path clb.fle[arith].adder[5] + * to physical pb_type adder[10] with a full path clb.fle[physical].adder[10] + */ + float physical_pb_type_index_factor_; + + /* The offset aims to align the indices for pb_type between operating and + * physical modes, especially when an operating mode contains multiple pb_type + * (num_pb>1) that are linked to the same physical pb_type. When number of + * physical_pb_type is larger than 1, the index of pb_type will be shifted by + * the given factor. + * + * For example, an offset of 1 is used to map + * operating pb_type adder[0] with a full path clb.fle[arith].adder[0] + * to physical pb_type adder[1] with a full path clb.fle[physical].adder[1] + */ + int physical_pb_type_index_offset_; + + /* Link from the pins under an operating pb_type to pairs of + * its physical pb_type and + * - its pin initial offset: the first element of the std::array + * - pin-level rotating offset: the second element of the std::array + * - port-level rotating offset: the third element of the std::array + * + * The offsets aim to align the pin indices for port of pb_type + * between operating and physical modes, especially when an operating + * mode contains multiple pb_type (num_pb>1) that are linked to + * the same physical pb_type. + * When physical_mode_pin_rotate_offset is larger than zero, + * the pin index of pb_type (whose index is large than 1) + * will be shifted by the given offset. + * + * For example, an initial offset of -32 is used to map + * operating pb_type bram[0].dout[32] with a full path + * memory[dual_port].bram[0] operating pb_type bram[0].dout[33] with a full + * path memory[dual_port].bram[0] to physical pb_type bram[0].dout_a[0] with a + * full path memory[physical].bram[0] physical pb_type bram[0].dout_a[1] with + * a full path memory[physical].bram[0] + * + * For example, a pin-level rotating offset of 9 is used to map + * operating pb_type mult_9x9[0].a[0] with a full path + * mult[frac].mult_9x9[0] operating pb_type mult_9x9[0].a[1] with a full path + * mult[frac].mult_9x9[1] to physical pb_type mult_36x36.a[0] with a full path + * mult[physical].mult_36x36[0] physical pb_type mult_36x36.a[9] with a full + * path mult[physical].mult_36x36[0] + * + * For example, a port-level rotating offset of 9 is used to map + * operating pb_type mult_9x9[0].a[0:8] with a full path + * mult[frac].mult_9x9[0] operating pb_type mult_9x9[1].a[0:8] with a full + * path mult[frac].mult_9x9[1] to physical pb_type mult_36x36.a[0:8] with a + * full path mult[physical].mult_36x36[0] physical pb_type mult_36x36.a[9:17] + * with a full path mult[physical].mult_36x36[0] + */ + std::map>> + operating_pb_type_ports_; + + /* Link between the interconnects under this pb_type and circuit model names + */ + std::map interconnect_circuit_model_names_; }; -} /* namespace openfpga ends */ +} // namespace openfpga #endif - diff --git a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp index 05ffc492d..7447bec2a 100644 --- a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp @@ -17,64 +17,70 @@ /* Headers from libarchfpga */ #include "arch_error.h" -#include "read_xml_util.h" - #include "read_xml_bitstream_setting.h" +#include "read_xml_util.h" /******************************************************************** * Parse XML description for a pb_type annotation under a XML node *******************************************************************/ -static -void read_xml_bitstream_pb_type_setting(pugi::xml_node& xml_pb_type, - const pugiutil::loc_data& loc_data, - openfpga::BitstreamSetting& bitstream_setting) { - const std::string& name_attr = get_attribute(xml_pb_type, "name", loc_data).as_string(); - const std::string& source_attr = get_attribute(xml_pb_type, "source", loc_data).as_string(); - const std::string& content_attr = get_attribute(xml_pb_type, "content", loc_data).as_string(); +static void read_xml_bitstream_pb_type_setting( + pugi::xml_node& xml_pb_type, const pugiutil::loc_data& loc_data, + openfpga::BitstreamSetting& bitstream_setting) { + const std::string& name_attr = + get_attribute(xml_pb_type, "name", loc_data).as_string(); + const std::string& source_attr = + get_attribute(xml_pb_type, "source", loc_data).as_string(); + const std::string& content_attr = + get_attribute(xml_pb_type, "content", loc_data).as_string(); /* Parse the attributes for operating pb_type */ openfpga::PbParser operating_pb_parser(name_attr); /* Add to bitstream setting */ - BitstreamPbTypeSettingId bitstream_pb_type_id = bitstream_setting.add_bitstream_pb_type_setting(operating_pb_parser.leaf(), - operating_pb_parser.parents(), - operating_pb_parser.modes(), - source_attr, - content_attr); + BitstreamPbTypeSettingId bitstream_pb_type_id = + bitstream_setting.add_bitstream_pb_type_setting( + operating_pb_parser.leaf(), operating_pb_parser.parents(), + operating_pb_parser.modes(), source_attr, content_attr); /* Parse if the bitstream overwritting is applied to mode bits of a pb_type */ - const bool& is_mode_select_bitstream = get_attribute(xml_pb_type, "is_mode_select_bitstream", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false); - bitstream_setting.set_mode_select_bitstream(bitstream_pb_type_id, is_mode_select_bitstream); + const bool& is_mode_select_bitstream = + get_attribute(xml_pb_type, "is_mode_select_bitstream", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_bool(false); + bitstream_setting.set_mode_select_bitstream(bitstream_pb_type_id, + is_mode_select_bitstream); - const int& offset = get_attribute(xml_pb_type, "bitstream_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(0); - bitstream_setting.set_bitstream_offset(bitstream_pb_type_id, offset); + const int& offset = get_attribute(xml_pb_type, "bitstream_offset", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_int(0); + bitstream_setting.set_bitstream_offset(bitstream_pb_type_id, offset); } /******************************************************************** * Parse XML description for a pb_type annotation under a XML node *******************************************************************/ -static -void read_xml_bitstream_interconnect_setting(pugi::xml_node& xml_pb_type, - const pugiutil::loc_data& loc_data, - openfpga::BitstreamSetting& bitstream_setting) { - const std::string& name_attr = get_attribute(xml_pb_type, "name", loc_data).as_string(); - const std::string& default_path_attr = get_attribute(xml_pb_type, "default_path", loc_data).as_string(); +static void read_xml_bitstream_interconnect_setting( + pugi::xml_node& xml_pb_type, const pugiutil::loc_data& loc_data, + openfpga::BitstreamSetting& bitstream_setting) { + const std::string& name_attr = + get_attribute(xml_pb_type, "name", loc_data).as_string(); + const std::string& default_path_attr = + get_attribute(xml_pb_type, "default_path", loc_data).as_string(); /* Parse the attributes for operating pb_type */ openfpga::PbParser operating_pb_parser(name_attr); /* Add to bitstream setting */ - bitstream_setting.add_bitstream_interconnect_setting(operating_pb_parser.leaf(), - operating_pb_parser.parents(), - operating_pb_parser.modes(), - default_path_attr); + bitstream_setting.add_bitstream_interconnect_setting( + operating_pb_parser.leaf(), operating_pb_parser.parents(), + operating_pb_parser.modes(), default_path_attr); } /******************************************************************** * Parse XML codes about to an object *******************************************************************/ -openfpga::BitstreamSetting read_xml_bitstream_setting(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data) { +openfpga::BitstreamSetting read_xml_bitstream_setting( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data) { openfpga::BitstreamSetting bitstream_setting; /* Iterate over the children under this node, @@ -82,18 +88,20 @@ openfpga::BitstreamSetting read_xml_bitstream_setting(pugi::xml_node& Node, */ for (pugi::xml_node xml_child : Node.children()) { /* Error out if the XML child has an invalid name! */ - if ( (xml_child.name() != std::string("pb_type")) - && (xml_child.name() != std::string("interconnect")) ) { + if ((xml_child.name() != std::string("pb_type")) && + (xml_child.name() != std::string("interconnect"))) { bad_tag(xml_child, loc_data, Node, {"pb_type | interconnect"}); } if (xml_child.name() == std::string("pb_type")) { - read_xml_bitstream_pb_type_setting(xml_child, loc_data, bitstream_setting); + read_xml_bitstream_pb_type_setting(xml_child, loc_data, + bitstream_setting); } else { VTR_ASSERT_SAFE(xml_child.name() == std::string("interconnect")); - read_xml_bitstream_interconnect_setting(xml_child, loc_data, bitstream_setting); + read_xml_bitstream_interconnect_setting(xml_child, loc_data, + bitstream_setting); } - } + } return bitstream_setting; } diff --git a/libs/libarchopenfpga/src/read_xml_bitstream_setting.h b/libs/libarchopenfpga/src/read_xml_bitstream_setting.h index d3b16ec82..205a108b7 100644 --- a/libs/libarchopenfpga/src/read_xml_bitstream_setting.h +++ b/libs/libarchopenfpga/src/read_xml_bitstream_setting.h @@ -4,15 +4,15 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "pugixml_util.hpp" -#include "pugixml.hpp" #include "bitstream_setting.h" +#include "pugixml.hpp" +#include "pugixml_util.hpp" /******************************************************************** * Function declaration *******************************************************************/ -openfpga::BitstreamSetting read_xml_bitstream_setting(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data); +openfpga::BitstreamSetting read_xml_bitstream_setting( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data); #endif diff --git a/libs/libarchopenfpga/src/read_xml_circuit_library.cpp b/libs/libarchopenfpga/src/read_xml_circuit_library.cpp index 0137f961b..13ff84800 100644 --- a/libs/libarchopenfpga/src/read_xml_circuit_library.cpp +++ b/libs/libarchopenfpga/src/read_xml_circuit_library.cpp @@ -18,14 +18,13 @@ /* Headers from openfpgautil library */ #include "openfpga_tokenizer.h" - #include "read_xml_circuit_library.h" /******************************************************************** * Convert string to the enumerate of model type *******************************************************************/ -static -e_circuit_model_type string_to_circuit_model_type(const std::string& type_string) { +static e_circuit_model_type string_to_circuit_model_type( + const std::string& type_string) { for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_TYPES; ++itype) { if (std::string(CIRCUIT_MODEL_TYPE_STRING[itype]) == type_string) { return static_cast(itype); @@ -39,10 +38,11 @@ e_circuit_model_type string_to_circuit_model_type(const std::string& type_string /******************************************************************** * Convert string to the enumerate of model type *******************************************************************/ -static -e_circuit_model_design_tech string_to_design_tech_type(const std::string& type_string) { +static e_circuit_model_design_tech string_to_design_tech_type( + const std::string& type_string) { for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES; ++itype) { - if (std::string(CIRCUIT_MODEL_DESIGN_TECH_TYPE_STRING[itype]) == type_string) { + if (std::string(CIRCUIT_MODEL_DESIGN_TECH_TYPE_STRING[itype]) == + type_string) { return static_cast(itype); } } @@ -53,8 +53,8 @@ e_circuit_model_design_tech string_to_design_tech_type(const std::string& type_s /******************************************************************** * Convert string to the enumerate of buffer type *******************************************************************/ -static -e_circuit_model_buffer_type string_to_buffer_type(const std::string& type_string) { +static e_circuit_model_buffer_type string_to_buffer_type( + const std::string& type_string) { for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_BUF_TYPES; ++itype) { if (std::string(CIRCUIT_MODEL_BUFFER_TYPE_STRING[itype]) == type_string) { return static_cast(itype); @@ -67,8 +67,8 @@ e_circuit_model_buffer_type string_to_buffer_type(const std::string& type_string /******************************************************************** * Convert string to the enumerate of pass-gate-logic type *******************************************************************/ -static -e_circuit_model_pass_gate_logic_type string_to_passgate_type(const std::string& type_string) { +static e_circuit_model_pass_gate_logic_type string_to_passgate_type( + const std::string& type_string) { for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_PASS_GATE_TYPES; ++itype) { if (std::string(CIRCUIT_MODEL_PASSGATE_TYPE_STRING[itype]) == type_string) { return static_cast(itype); @@ -81,10 +81,11 @@ e_circuit_model_pass_gate_logic_type string_to_passgate_type(const std::string& /******************************************************************** * Convert string to the enumerate of multiplexer structure *******************************************************************/ -static -e_circuit_model_structure string_to_mux_structure_type(const std::string& type_string) { +static e_circuit_model_structure string_to_mux_structure_type( + const std::string& type_string) { for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_STRUCTURE_TYPES; ++itype) { - if (std::string(CIRCUIT_MODEL_STRUCTURE_TYPE_STRING[itype]) == type_string) { + if (std::string(CIRCUIT_MODEL_STRUCTURE_TYPE_STRING[itype]) == + type_string) { return static_cast(itype); } } @@ -95,8 +96,8 @@ e_circuit_model_structure string_to_mux_structure_type(const std::string& type_s /******************************************************************** * Convert string to the enumerate of logic gate type *******************************************************************/ -static -e_circuit_model_gate_type string_to_gate_type(const std::string& type_string) { +static e_circuit_model_gate_type string_to_gate_type( + const std::string& type_string) { for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_GATE_TYPES; ++itype) { if (std::string(CIRCUIT_MODEL_GATE_TYPE_STRING[itype]) == type_string) { return static_cast(itype); @@ -109,8 +110,8 @@ e_circuit_model_gate_type string_to_gate_type(const std::string& type_string) { /******************************************************************** * Convert string to the enumerate of circuit model port type *******************************************************************/ -static -e_circuit_model_port_type string_to_circuit_model_port_type(const std::string& type_string) { +static e_circuit_model_port_type string_to_circuit_model_port_type( + const std::string& type_string) { for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_PORT_TYPES; ++itype) { if (std::string(CIRCUIT_MODEL_PORT_TYPE_STRING[itype]) == type_string) { return static_cast(itype); @@ -123,8 +124,8 @@ e_circuit_model_port_type string_to_circuit_model_port_type(const std::string& t /******************************************************************** * Convert string to the enumerate of wire model type *******************************************************************/ -static -e_wire_model_type string_to_wire_model_type(const std::string& type_string) { +static e_wire_model_type string_to_wire_model_type( + const std::string& type_string) { for (size_t itype = 0; itype < NUM_WIRE_MODEL_TYPES; ++itype) { if (std::string(WIRE_MODEL_TYPE_STRING[itype]) == type_string) { return static_cast(itype); @@ -137,8 +138,8 @@ e_wire_model_type string_to_wire_model_type(const std::string& type_string) { /******************************************************************** * Convert string to the enumerate of delay model type *******************************************************************/ -static -e_circuit_model_delay_type string_to_circuit_model_delay_type(const std::string& type_string) { +static e_circuit_model_delay_type string_to_circuit_model_delay_type( + const std::string& type_string) { for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_DELAY_TYPES; ++itype) { if (std::string(CIRCUIT_MODEL_DELAY_TYPE_STRING[itype]) == type_string) { return static_cast(itype); @@ -151,80 +152,100 @@ e_circuit_model_delay_type string_to_circuit_model_delay_type(const std::string& /******************************************************************** * Parse XML codes of design technology of a circuit model to circuit library *******************************************************************/ -static -void read_xml_model_design_technology(pugi::xml_node& xml_model, - const pugiutil::loc_data& loc_data, - CircuitLibrary& circuit_lib, const CircuitModelId& model) { - - auto xml_design_tech = get_single_child(xml_model, "design_technology", loc_data); +static void read_xml_model_design_technology(pugi::xml_node& xml_model, + const pugiutil::loc_data& loc_data, + CircuitLibrary& circuit_lib, + const CircuitModelId& model) { + auto xml_design_tech = + get_single_child(xml_model, "design_technology", loc_data); /* Identify if the circuit model power-gated */ - circuit_lib.set_model_is_power_gated(model, get_attribute(xml_design_tech, "power_gated", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + circuit_lib.set_model_is_power_gated( + model, get_attribute(xml_design_tech, "power_gated", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); /* Identify the type of design technology */ - const char* type_attr = get_attribute(xml_design_tech, "type", loc_data).value(); + const char* type_attr = + get_attribute(xml_design_tech, "type", loc_data).value(); /* Translate the type of design technology to enumerate */ - e_circuit_model_design_tech design_tech_type = string_to_design_tech_type(std::string(type_attr)); + e_circuit_model_design_tech design_tech_type = + string_to_design_tech_type(std::string(type_attr)); if (NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES == design_tech_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_design_tech), - "Invalid 'type' attribute '%s'\n", - type_attr); + "Invalid 'type' attribute '%s'\n", type_attr); } circuit_lib.set_model_design_tech_type(model, design_tech_type); - + /* Parse exclusive attributes for inverters and buffers */ if (CIRCUIT_MODEL_INVBUF == circuit_lib.model_type(model)) { /* Identify the topology of the buffer */ - const char* topology_attr = get_attribute(xml_design_tech, "topology", loc_data).value(); + const char* topology_attr = + get_attribute(xml_design_tech, "topology", loc_data).value(); /* Translate the type of buffer to enumerate */ - e_circuit_model_buffer_type buf_type = string_to_buffer_type(std::string(topology_attr)); + e_circuit_model_buffer_type buf_type = + string_to_buffer_type(std::string(topology_attr)); if (NUM_CIRCUIT_MODEL_BUF_TYPES == buf_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_design_tech), - "Invalid 'topology' attribute '%s'\n", - topology_attr); - } + "Invalid 'topology' attribute '%s'\n", topology_attr); + } circuit_lib.set_buffer_type(model, buf_type); - /* Parse the others options: - * 1. size of buffer in the first stage - * 2. number of levels + /* Parse the others options: + * 1. size of buffer in the first stage + * 2. number of levels * 3. driving strength per stage */ - circuit_lib.set_buffer_size(model, get_attribute(xml_design_tech, "size", loc_data).as_float(0.)); - circuit_lib.set_buffer_num_levels(model, get_attribute(xml_design_tech, "num_level", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(1)); - circuit_lib.set_buffer_f_per_stage(model, get_attribute(xml_design_tech, "f_per_stage", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(4)); + circuit_lib.set_buffer_size( + model, get_attribute(xml_design_tech, "size", loc_data).as_float(0.)); + circuit_lib.set_buffer_num_levels( + model, get_attribute(xml_design_tech, "num_level", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_int(1)); + circuit_lib.set_buffer_f_per_stage( + model, get_attribute(xml_design_tech, "f_per_stage", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_int(4)); } - + /* Parse exclusive attributes for pass-gate logics */ if (CIRCUIT_MODEL_PASSGATE == circuit_lib.model_type(model)) { /* Identify the topology of the pass-gate logic */ - const char* topology_attr = get_attribute(xml_design_tech, "topology", loc_data).value(); + const char* topology_attr = + get_attribute(xml_design_tech, "topology", loc_data).value(); /* Translate the type of pass-gate logic to enumerate */ - e_circuit_model_pass_gate_logic_type passgate_type = string_to_passgate_type(std::string(topology_attr)); + e_circuit_model_pass_gate_logic_type passgate_type = + string_to_passgate_type(std::string(topology_attr)); if (NUM_CIRCUIT_MODEL_PASS_GATE_TYPES == passgate_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_design_tech), - "Invalid 'topology' attribute '%s'\n", - topology_attr); - } + "Invalid 'topology' attribute '%s'\n", topology_attr); + } circuit_lib.set_pass_gate_logic_type(model, passgate_type); - /* Parse the others options: - * 1. pmos size to be used in the pass gate logic - * 2. nmos size to be used in the pass gate logic + /* Parse the others options: + * 1. pmos size to be used in the pass gate logic + * 2. nmos size to be used in the pass gate logic */ - circuit_lib.set_pass_gate_logic_pmos_size(model, get_attribute(xml_design_tech, "pmos_size", loc_data).as_float(0.)); - circuit_lib.set_pass_gate_logic_nmos_size(model, get_attribute(xml_design_tech, "nmos_size", loc_data).as_float(0.)); + circuit_lib.set_pass_gate_logic_pmos_size( + model, + get_attribute(xml_design_tech, "pmos_size", loc_data).as_float(0.)); + circuit_lib.set_pass_gate_logic_nmos_size( + model, + get_attribute(xml_design_tech, "nmos_size", loc_data).as_float(0.)); } /* Parse exclusive attributes for Look-Up Tables (LUTs) */ if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) { /* Identify if this is a fracturable LUT */ - circuit_lib.set_lut_is_fracturable(model, get_attribute(xml_design_tech, "fracturable_lut", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + circuit_lib.set_lut_is_fracturable( + model, get_attribute(xml_design_tech, "fracturable_lut", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); /* Set default MUX-relate attributes as LUT contains a tree-like MUX */ circuit_lib.set_mux_structure(model, CIRCUIT_MODEL_STRUCTURE_TREE); circuit_lib.set_mux_use_local_encoder(model, false); @@ -237,34 +258,42 @@ void read_xml_model_design_technology(pugi::xml_node& xml_model, if (CIRCUIT_MODEL_DESIGN_CMOS == circuit_lib.design_tech_type(model)) { circuit_lib.set_mux_structure(model, CIRCUIT_MODEL_STRUCTURE_TREE); } else { - VTR_ASSERT_SAFE(CIRCUIT_MODEL_DESIGN_RRAM == circuit_lib.design_tech_type(model)); + VTR_ASSERT_SAFE(CIRCUIT_MODEL_DESIGN_RRAM == + circuit_lib.design_tech_type(model)); circuit_lib.set_mux_structure(model, CIRCUIT_MODEL_STRUCTURE_ONELEVEL); } /* Identify the topology of the multiplexer structure */ - const char* structure_attr = get_attribute(xml_design_tech, "structure", loc_data).value(); + const char* structure_attr = + get_attribute(xml_design_tech, "structure", loc_data).value(); /* Translate the type of multiplexer structure to enumerate */ - e_circuit_model_structure mux_structure = string_to_mux_structure_type(std::string(structure_attr)); - + e_circuit_model_structure mux_structure = + string_to_mux_structure_type(std::string(structure_attr)); + if (NUM_CIRCUIT_MODEL_STRUCTURE_TYPES == mux_structure) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_design_tech), - "Invalid 'structure' attribute '%s'\n", - structure_attr); - } + "Invalid 'structure' attribute '%s'\n", structure_attr); + } circuit_lib.set_mux_structure(model, mux_structure); - /* Parse the others options: + /* Parse the others options: * 1. constant input values * 2. number of levels if multi-level multiplexer structure is selected * 3. if advanced ReRAM design is used - * 4. if local encoder is to be used + * 4. if local encoder is to be used */ - if (true == get_attribute(xml_design_tech, "add_const_input", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)) { - circuit_lib.set_mux_const_input_value(model, get_attribute(xml_design_tech, "const_input_val", loc_data).as_int(0)); + if (true == get_attribute(xml_design_tech, "add_const_input", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)) { + circuit_lib.set_mux_const_input_value( + model, + get_attribute(xml_design_tech, "const_input_val", loc_data).as_int(0)); } - if (CIRCUIT_MODEL_STRUCTURE_MULTILEVEL == circuit_lib.mux_structure(model)) { - circuit_lib.set_mux_num_levels(model, get_attribute(xml_design_tech, "num_level", loc_data).as_int(1)); - /* Correction on the mux structure: + if (CIRCUIT_MODEL_STRUCTURE_MULTILEVEL == + circuit_lib.mux_structure(model)) { + circuit_lib.set_mux_num_levels( + model, get_attribute(xml_design_tech, "num_level", loc_data).as_int(1)); + /* Correction on the mux structure: * if the number of level is set to 1 in a multi-level multiplexer, * we change the mux structure to one-level */ @@ -272,101 +301,130 @@ void read_xml_model_design_technology(pugi::xml_node& xml_model, circuit_lib.set_mux_structure(model, CIRCUIT_MODEL_STRUCTURE_ONELEVEL); } } - circuit_lib.set_mux_use_advanced_rram_design(model, get_attribute(xml_design_tech, "advanced_rram_design", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); - circuit_lib.set_mux_use_local_encoder(model, get_attribute(xml_design_tech, "local_encoder", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + circuit_lib.set_mux_use_advanced_rram_design( + model, get_attribute(xml_design_tech, "advanced_rram_design", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); + circuit_lib.set_mux_use_local_encoder( + model, get_attribute(xml_design_tech, "local_encoder", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); } /* Parse exclusive attributes for logic gates */ if (CIRCUIT_MODEL_GATE == circuit_lib.model_type(model)) { /* Identify the topology of the logic gate */ - const char* topology_attr = get_attribute(xml_design_tech, "topology", loc_data).value(); + const char* topology_attr = + get_attribute(xml_design_tech, "topology", loc_data).value(); /* Translate the type of logic gate to enumerate */ - e_circuit_model_gate_type gate_type = string_to_gate_type(std::string(topology_attr)); + e_circuit_model_gate_type gate_type = + string_to_gate_type(std::string(topology_attr)); if (NUM_CIRCUIT_MODEL_GATE_TYPES == gate_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_design_tech), - "Invalid 'topology' attribute '%s'\n", - topology_attr); - } + "Invalid 'topology' attribute '%s'\n", topology_attr); + } circuit_lib.set_gate_type(model, gate_type); } /* Parse exclusive attributes for RRAM */ if (CIRCUIT_MODEL_DESIGN_RRAM == circuit_lib.design_tech_type(model)) { - circuit_lib.set_rram_rlrs(model, get_attribute(xml_design_tech, "ron", loc_data).as_float(0.)); - circuit_lib.set_rram_rhrs(model, get_attribute(xml_design_tech, "roff", loc_data).as_float(0.)); - circuit_lib.set_rram_wprog_set_pmos(model, get_attribute(xml_design_tech, "wprog_set_pmos", loc_data).as_float(0.)); - circuit_lib.set_rram_wprog_set_nmos(model, get_attribute(xml_design_tech, "wprog_set_nmos", loc_data).as_float(0.)); - circuit_lib.set_rram_wprog_reset_pmos(model, get_attribute(xml_design_tech, "wprog_reset_pmos", loc_data).as_float(0.)); - circuit_lib.set_rram_wprog_reset_nmos(model, get_attribute(xml_design_tech, "wprog_reset_nmos", loc_data).as_float(0.)); + circuit_lib.set_rram_rlrs( + model, get_attribute(xml_design_tech, "ron", loc_data).as_float(0.)); + circuit_lib.set_rram_rhrs( + model, get_attribute(xml_design_tech, "roff", loc_data).as_float(0.)); + circuit_lib.set_rram_wprog_set_pmos( + model, + get_attribute(xml_design_tech, "wprog_set_pmos", loc_data).as_float(0.)); + circuit_lib.set_rram_wprog_set_nmos( + model, + get_attribute(xml_design_tech, "wprog_set_nmos", loc_data).as_float(0.)); + circuit_lib.set_rram_wprog_reset_pmos( + model, get_attribute(xml_design_tech, "wprog_reset_pmos", loc_data) + .as_float(0.)); + circuit_lib.set_rram_wprog_reset_nmos( + model, get_attribute(xml_design_tech, "wprog_reset_nmos", loc_data) + .as_float(0.)); } } /******************************************************************** * Parse XML codes of device technology of a circuit model to circuit library *******************************************************************/ -static -void read_xml_model_device_technology(pugi::xml_node& xml_model, - const pugiutil::loc_data& loc_data, - CircuitLibrary& circuit_lib, const CircuitModelId& model) { +static void read_xml_model_device_technology(pugi::xml_node& xml_model, + const pugiutil::loc_data& loc_data, + CircuitLibrary& circuit_lib, + const CircuitModelId& model) { + auto xml_device_tech = get_single_child(xml_model, "device_technology", + loc_data, pugiutil::ReqOpt::OPTIONAL); - auto xml_device_tech = get_single_child(xml_model, "device_technology", loc_data, pugiutil::ReqOpt::OPTIONAL); - if (!xml_device_tech) { return; } /* Parse device model name */ - const char* device_model_name_attr = get_attribute(xml_device_tech, "device_model_name", loc_data, pugiutil::ReqOpt::OPTIONAL).value(); + const char* device_model_name_attr = + get_attribute(xml_device_tech, "device_model_name", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .value(); if (nullptr != device_model_name_attr) { - circuit_lib.set_device_model_name(model, std::string(device_model_name_attr)); + circuit_lib.set_device_model_name(model, + std::string(device_model_name_attr)); } } /******************************************************************** * This is a generic function to parse XML codes that describe * a buffer of a circuit model to circuit library - * This function will return a string with the circuit model name + * This function will return a string with the circuit model name * linked to the buffer * If the return is empty, it means that buffer does NOT exist - *******************************************************************/ -static -std::string read_xml_buffer(pugi::xml_node& xml_buffer, - const pugiutil::loc_data& loc_data) { - bool buffer_existence = get_attribute(xml_buffer, "exist", loc_data).as_bool(false); + *******************************************************************/ +static std::string read_xml_buffer(pugi::xml_node& xml_buffer, + const pugiutil::loc_data& loc_data) { + bool buffer_existence = + get_attribute(xml_buffer, "exist", loc_data).as_bool(false); std::string buffer_circuit_model_name(""); - - if (true == buffer_existence) { - buffer_circuit_model_name = get_attribute(xml_buffer, "circuit_model_name", loc_data).as_string(); + + if (true == buffer_existence) { + buffer_circuit_model_name = + get_attribute(xml_buffer, "circuit_model_name", loc_data).as_string(); } return buffer_circuit_model_name; } /******************************************************************** - * Identify the output mask of the port in LUTs, + * Identify the output mask of the port in LUTs, * by default it will be applied to each pin of this port * This is only applicable to output ports of a LUT *******************************************************************/ -static -void read_xml_output_mask(pugi::xml_node& xml_port, - const pugiutil::loc_data& loc_data, - CircuitLibrary& circuit_lib, const CircuitPortId& port) { - std::string output_mask_attr = get_attribute(xml_port, "lut_output_mask", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(); +static void read_xml_output_mask(pugi::xml_node& xml_port, + const pugiutil::loc_data& loc_data, + CircuitLibrary& circuit_lib, + const CircuitPortId& port) { + std::string output_mask_attr = + get_attribute(xml_port, "lut_output_mask", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string(); std::vector mask_vector; if (!output_mask_attr.empty()) { /* Split the string with token ',' */ - openfpga::StringToken string_tokenizer(get_attribute(xml_port, "lut_output_mask", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(nullptr)); + openfpga::StringToken string_tokenizer( + get_attribute(xml_port, "lut_output_mask", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string(nullptr)); for (const std::string& mask_token : string_tokenizer.split(',')) { mask_vector.push_back(std::atoi(mask_token.c_str())); } /* Make sure that the size of mask fits the port size */ if (circuit_lib.port_size(port) != mask_vector.size()) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_port), - "Invalid lut_output_mask attribute '%s'! It must match the port size (=%lu)\n", + "Invalid lut_output_mask attribute '%s'! It must match " + "the port size (=%lu)\n", output_mask_attr.c_str(), circuit_lib.port_size(port)); - } + } } else { /* By default, we give a mask vector covering each pin of the port */ mask_vector.resize(circuit_lib.port_size(port)); @@ -378,213 +436,275 @@ void read_xml_output_mask(pugi::xml_node& xml_port, /******************************************************************** * This is a generic function to parse XML codes that describe * a port of a circuit model to circuit library - *******************************************************************/ -static -void read_xml_circuit_port(pugi::xml_node& xml_port, - const pugiutil::loc_data& loc_data, - CircuitLibrary& circuit_lib, const CircuitModelId& model) { + *******************************************************************/ +static void read_xml_circuit_port(pugi::xml_node& xml_port, + const pugiutil::loc_data& loc_data, + CircuitLibrary& circuit_lib, + const CircuitModelId& model) { /* Find the type of the circuit port - * so that we can add a new circuit port to circuit library + * so that we can add a new circuit port to circuit library */ const char* type_attr = get_attribute(xml_port, "type", loc_data).value(); /* Translate the type of circuit model to enumerate */ - e_circuit_model_port_type port_type = string_to_circuit_model_port_type(std::string(type_attr)); + e_circuit_model_port_type port_type = + string_to_circuit_model_port_type(std::string(type_attr)); if (NUM_CIRCUIT_MODEL_PORT_TYPES == port_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_port), - "Invalid 'type' attribute '%s'\n", - type_attr); + "Invalid 'type' attribute '%s'\n", type_attr); } CircuitPortId port = circuit_lib.add_model_port(model, port_type); /* Parse the name of the port */ - circuit_lib.set_port_prefix(port, get_attribute(xml_port, "prefix", loc_data).as_string()); + circuit_lib.set_port_prefix( + port, get_attribute(xml_port, "prefix", loc_data).as_string()); - /* Parse the name of the port in cell library. By default, the lib_name is the same as port name */ - const char* lib_name_attr = get_attribute(xml_port, "lib_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(nullptr); + /* Parse the name of the port in cell library. By default, the lib_name is the + * same as port name */ + const char* lib_name_attr = + get_attribute(xml_port, "lib_name", loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_string(nullptr); if (nullptr != lib_name_attr) { - circuit_lib.set_port_lib_name(port, get_attribute(xml_port, "lib_name", loc_data).as_string()); + circuit_lib.set_port_lib_name( + port, get_attribute(xml_port, "lib_name", loc_data).as_string()); } else { circuit_lib.set_port_lib_name(port, circuit_lib.port_prefix(port)); } /* Parse the port size, by default it will be 1 */ - circuit_lib.set_port_size(port, get_attribute(xml_port, "size", loc_data).as_int(1)); + circuit_lib.set_port_size( + port, get_attribute(xml_port, "size", loc_data).as_int(1)); /* Identify if the port is for io, this is only applicable to INPUT ports. * By default, it will NOT be a mode selection port */ - circuit_lib.set_port_is_io(port, get_attribute(xml_port, "is_io", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + circuit_lib.set_port_is_io( + port, get_attribute(xml_port, "is_io", loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); - /* Identify if the port is a data io, ONLY applicable to I/O port + /* Identify if the port is a data io, ONLY applicable to I/O port * By default, it will NOT be a data io port */ if (true == circuit_lib.port_is_io(port)) { - circuit_lib.set_port_is_data_io(port, get_attribute(xml_port, "is_data_io", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + circuit_lib.set_port_is_data_io( + port, get_attribute(xml_port, "is_data_io", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); } - /* Identify if the port is for mode selection, this is only applicable to SRAM ports. - * By default, it will NOT be a mode selection port + /* Identify if the port is for mode selection, this is only applicable to SRAM + * ports. By default, it will NOT be a mode selection port */ if (CIRCUIT_MODEL_PORT_SRAM == circuit_lib.port_type(port)) { - circuit_lib.set_port_is_mode_select(port, get_attribute(xml_port, "mode_select", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); - } + circuit_lib.set_port_is_mode_select( + port, get_attribute(xml_port, "mode_select", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); + } /* Identify the default value of the port, by default it will be 0 */ - circuit_lib.set_port_default_value(port, get_attribute(xml_port, "default_val", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(0)); + circuit_lib.set_port_default_value( + port, + get_attribute(xml_port, "default_val", loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_int(0)); - /* Identify the tri-state map of the port, by default it will be nullptr + /* Identify the tri-state map of the port, by default it will be nullptr * This is only applicable to input ports of a LUT */ - if ( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) - && (CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(port)) ) { - const char* tri_state_map_attr = get_attribute(xml_port, "tri_state_map", loc_data, pugiutil::ReqOpt::OPTIONAL).value(); + if ((CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) && + (CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(port))) { + const char* tri_state_map_attr = + get_attribute(xml_port, "tri_state_map", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .value(); if (nullptr != tri_state_map_attr) { - circuit_lib.set_port_tri_state_map(port, get_attribute(xml_port, "tri_state_map", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string()); + circuit_lib.set_port_tri_state_map( + port, get_attribute(xml_port, "tri_state_map", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string()); } } - /* Identify the fracturable-level of the port in LUTs, by default it will be -1 - * This is only applicable to output ports of a LUT + /* Identify the fracturable-level of the port in LUTs, by default it will be + * -1 This is only applicable to output ports of a LUT */ - if ( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) - && (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port)) ) { - circuit_lib.set_port_lut_frac_level(port, get_attribute(xml_port, "lut_frac_level", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-1)); + if ((CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) && + (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port))) { + circuit_lib.set_port_lut_frac_level( + port, get_attribute(xml_port, "lut_frac_level", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_int(-1)); } - /* Identify if the port carries a harden functionality rather than a reconfigurable port - * This is only applicable to LUT circuit models. - * The super LUT circuit model (whose netlists are supposed to be provided by users) contains - * some hard logic inside, e.g., a carry logic. - * By default, a port does NOT carry a hard functionality + /* Identify if the port carries a harden functionality rather than a + * reconfigurable port This is only applicable to LUT circuit models. The + * super LUT circuit model (whose netlists are supposed to be provided by + * users) contains some hard logic inside, e.g., a carry logic. By default, a + * port does NOT carry a hard functionality */ if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) { - circuit_lib.set_port_is_harden_lut_port(port, get_attribute(xml_port, "is_harden_lut_port", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + circuit_lib.set_port_is_harden_lut_port( + port, get_attribute(xml_port, "is_harden_lut_port", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); } - /* Identify the output mask of the port in LUTs, by default it will be applied to each pin of this port - * This is only applicable to output ports of a LUT + /* Identify the output mask of the port in LUTs, by default it will be applied + * to each pin of this port This is only applicable to output ports of a LUT */ - if ( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) - && (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port)) ) { + if ((CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) && + (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port))) { read_xml_output_mask(xml_port, loc_data, circuit_lib, port); } /* Identify if the port is a global port, by default it is NOT */ - circuit_lib.set_port_is_global(port, get_attribute(xml_port, "is_global", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + circuit_lib.set_port_is_global( + port, + get_attribute(xml_port, "is_global", loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); /* Identify if the port is a reset port, by default it is NOT */ - circuit_lib.set_port_is_reset(port, get_attribute(xml_port, "is_reset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + circuit_lib.set_port_is_reset( + port, + get_attribute(xml_port, "is_reset", loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); /* Identify if the port is a set port, by default it is NOT */ - circuit_lib.set_port_is_set(port, get_attribute(xml_port, "is_set", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + circuit_lib.set_port_is_set(port, get_attribute(xml_port, "is_set", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); /* Identify if the port is in programming purpose, by default it is NOT */ - circuit_lib.set_port_is_prog(port, get_attribute(xml_port, "is_prog", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + circuit_lib.set_port_is_prog( + port, + get_attribute(xml_port, "is_prog", loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); /* Identify if the port is in shift register purpose, by default it is NOT */ - circuit_lib.set_port_is_shift_register(port, get_attribute(xml_port, "is_shift_register", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + circuit_lib.set_port_is_shift_register( + port, get_attribute(xml_port, "is_shift_register", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); - /* Identify if the port is to enable programming for FPGAs, by default it is NOT */ - circuit_lib.set_port_is_config_enable(port, get_attribute(xml_port, "is_config_enable", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + /* Identify if the port is to enable programming for FPGAs, by default it is + * NOT */ + circuit_lib.set_port_is_config_enable( + port, get_attribute(xml_port, "is_config_enable", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); /* Find the name of circuit model that this port is linked to */ - circuit_lib.set_port_tri_state_model_name(port, get_attribute(xml_port, "circuit_model_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string()); + circuit_lib.set_port_tri_state_model_name( + port, get_attribute(xml_port, "circuit_model_name", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string()); /* Find the name of circuit model that port is used for inversion of signals, * This is only applicable to BL/WL/BLB/WLB ports */ - if ( (CIRCUIT_MODEL_PORT_BL == circuit_lib.port_type(port)) - || (CIRCUIT_MODEL_PORT_WL == circuit_lib.port_type(port)) - || (CIRCUIT_MODEL_PORT_BLB == circuit_lib.port_type(port)) - || (CIRCUIT_MODEL_PORT_WLB == circuit_lib.port_type(port)) ) { - circuit_lib.set_port_inv_model_name(port, get_attribute(xml_port, "inv_circuit_model_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string()); + if ((CIRCUIT_MODEL_PORT_BL == circuit_lib.port_type(port)) || + (CIRCUIT_MODEL_PORT_WL == circuit_lib.port_type(port)) || + (CIRCUIT_MODEL_PORT_BLB == circuit_lib.port_type(port)) || + (CIRCUIT_MODEL_PORT_WLB == circuit_lib.port_type(port))) { + circuit_lib.set_port_inv_model_name( + port, get_attribute(xml_port, "inv_circuit_model_name", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string()); } } /******************************************************************** * This is a generic function to parse XML codes that describe * RC parasitics for wire circuit model to circuit library - *******************************************************************/ -static -void read_xml_wire_param(pugi::xml_node& xml_wire_param, - const pugiutil::loc_data& loc_data, - CircuitLibrary& circuit_lib, const CircuitModelId& model) { + *******************************************************************/ +static void read_xml_wire_param(pugi::xml_node& xml_wire_param, + const pugiutil::loc_data& loc_data, + CircuitLibrary& circuit_lib, + const CircuitModelId& model) { /* Find the type of the wire model */ - const char* type_attr = get_attribute(xml_wire_param, "model_type", loc_data).value(); + const char* type_attr = + get_attribute(xml_wire_param, "model_type", loc_data).value(); /* Translate the type of circuit model to enumerate */ - e_wire_model_type wire_model_type = string_to_wire_model_type(std::string(type_attr)); + e_wire_model_type wire_model_type = + string_to_wire_model_type(std::string(type_attr)); if (NUM_WIRE_MODEL_TYPES == wire_model_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_wire_param), - "Invalid 'type' attribute '%s'\n", - type_attr); + "Invalid 'type' attribute '%s'\n", type_attr); } circuit_lib.set_wire_type(model, wire_model_type); /* Parse the R and C values */ - circuit_lib.set_wire_r(model, get_attribute(xml_wire_param, "R", loc_data).as_float(0.)); - circuit_lib.set_wire_c(model, get_attribute(xml_wire_param, "C", loc_data).as_float(0.)); + circuit_lib.set_wire_r( + model, get_attribute(xml_wire_param, "R", loc_data).as_float(0.)); + circuit_lib.set_wire_c( + model, get_attribute(xml_wire_param, "C", loc_data).as_float(0.)); /* Parse the number of levels for the wire model */ - circuit_lib.set_wire_num_level(model, get_attribute(xml_wire_param, "num_level", loc_data).as_int(0)); + circuit_lib.set_wire_num_level( + model, get_attribute(xml_wire_param, "num_level", loc_data).as_int(0)); } /******************************************************************** * This is a generic function to parse XML codes that describe * a delay matrix for a circuit model to circuit library - *******************************************************************/ -static -void read_xml_delay_matrix(pugi::xml_node& xml_delay_matrix, - const pugiutil::loc_data& loc_data, - CircuitLibrary& circuit_lib, const CircuitModelId& model) { + *******************************************************************/ +static void read_xml_delay_matrix(pugi::xml_node& xml_delay_matrix, + const pugiutil::loc_data& loc_data, + CircuitLibrary& circuit_lib, + const CircuitModelId& model) { /* Find the type of the delay model, so that we can add to circuit library */ - const char* type_attr = get_attribute(xml_delay_matrix, "type", loc_data).value(); + const char* type_attr = + get_attribute(xml_delay_matrix, "type", loc_data).value(); /* Translate the type of delay matrix for a circuit model to enumerate */ - e_circuit_model_delay_type delay_type = string_to_circuit_model_delay_type(std::string(type_attr)); + e_circuit_model_delay_type delay_type = + string_to_circuit_model_delay_type(std::string(type_attr)); if (NUM_CIRCUIT_MODEL_DELAY_TYPES == delay_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_delay_matrix), - "Invalid 'type' attribute '%s'\n", - type_attr); + "Invalid 'type' attribute '%s'\n", type_attr); } circuit_lib.add_delay_info(model, delay_type); /* Parse the input ports */ - circuit_lib.set_delay_in_port_names(model, delay_type, get_attribute(xml_delay_matrix, "in_port", loc_data).as_string()); + circuit_lib.set_delay_in_port_names( + model, delay_type, + get_attribute(xml_delay_matrix, "in_port", loc_data).as_string()); /* Parse the output ports */ - circuit_lib.set_delay_out_port_names(model, delay_type, get_attribute(xml_delay_matrix, "out_port", loc_data).as_string()); + circuit_lib.set_delay_out_port_names( + model, delay_type, + get_attribute(xml_delay_matrix, "out_port", loc_data).as_string()); /* Parse the delay values */ - circuit_lib.set_delay_values(model, delay_type, std::string(xml_delay_matrix.child_value())); + circuit_lib.set_delay_values(model, delay_type, + std::string(xml_delay_matrix.child_value())); } /******************************************************************** * Parse XML codes of a circuit model to circuit library *******************************************************************/ -static -void read_xml_circuit_model(pugi::xml_node& xml_model, - const pugiutil::loc_data& loc_data, - CircuitLibrary& circuit_lib) { +static void read_xml_circuit_model(pugi::xml_node& xml_model, + const pugiutil::loc_data& loc_data, + CircuitLibrary& circuit_lib) { /* Find the type of the circuit model - * so that we can add a new circuit model to circuit library + * so that we can add a new circuit model to circuit library */ const char* type_attr = get_attribute(xml_model, "type", loc_data).value(); /* Translate the type of circuit model to enumerate */ - e_circuit_model_type model_type = string_to_circuit_model_type(std::string(type_attr)); + e_circuit_model_type model_type = + string_to_circuit_model_type(std::string(type_attr)); if (NUM_CIRCUIT_MODEL_TYPES == model_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_model), - "Invalid 'type' attribute '%s'\n", - type_attr); + "Invalid 'type' attribute '%s'\n", type_attr); } CircuitModelId model = circuit_lib.add_model(model_type); @@ -593,54 +713,77 @@ void read_xml_circuit_model(pugi::xml_node& xml_model, const char* name_attr = get_attribute(xml_model, "name", loc_data).value(); circuit_lib.set_model_name(model, std::string(name_attr)); - /* TODO: This attribute is going to be DEPRECATED + /* TODO: This attribute is going to be DEPRECATED * Find the prefix of the circuit model */ - const char* prefix_attr = get_attribute(xml_model, "prefix", loc_data).value(); + const char* prefix_attr = + get_attribute(xml_model, "prefix", loc_data).value(); circuit_lib.set_model_prefix(model, std::string(prefix_attr)); /* Find a SPICE netlist which is an optional attribute*/ - circuit_lib.set_model_spice_netlist(model, get_attribute(xml_model, "spice_netlist", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string("")); + circuit_lib.set_model_spice_netlist( + model, get_attribute(xml_model, "spice_netlist", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string("")); /* Find a Verilog netlist which is an optional attribute*/ - circuit_lib.set_model_verilog_netlist(model, get_attribute(xml_model, "verilog_netlist", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string("")); + circuit_lib.set_model_verilog_netlist( + model, get_attribute(xml_model, "verilog_netlist", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string("")); /* Find if the circuit model is default in its type */ - circuit_lib.set_model_is_default(model, get_attribute(xml_model, "is_default", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); - + circuit_lib.set_model_is_default( + model, + get_attribute(xml_model, "is_default", loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); + /* Find if the circuit model is should be dumped in structural verilog */ - circuit_lib.set_model_dump_structural_verilog(model, get_attribute(xml_model, "dump_structural_verilog", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + circuit_lib.set_model_dump_structural_verilog( + model, get_attribute(xml_model, "dump_structural_verilog", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); /* Parse attributes under the */ /* Design technology -related attributes */ read_xml_model_design_technology(xml_model, loc_data, circuit_lib, model); - + /* Parse special buffer attributes required by LUTs only */ - if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) { + if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) { /* Input buffer of LUTs */ - auto xml_input_buffer = get_single_child(xml_model, "lut_input_buffer", loc_data); - std::string input_buffer_circuit_model_name = read_xml_buffer(xml_input_buffer, loc_data); - circuit_lib.set_model_lut_input_buffer(model, - true != input_buffer_circuit_model_name.empty(), - input_buffer_circuit_model_name); + auto xml_input_buffer = + get_single_child(xml_model, "lut_input_buffer", loc_data); + std::string input_buffer_circuit_model_name = + read_xml_buffer(xml_input_buffer, loc_data); + circuit_lib.set_model_lut_input_buffer( + model, true != input_buffer_circuit_model_name.empty(), + input_buffer_circuit_model_name); /* Input inverter of LUTs */ - auto xml_input_inverter = get_single_child(xml_model, "lut_input_inverter", loc_data); - std::string input_inverter_circuit_model_name = read_xml_buffer(xml_input_inverter, loc_data); - circuit_lib.set_model_lut_input_inverter(model, - true != input_inverter_circuit_model_name.empty(), - input_inverter_circuit_model_name); + auto xml_input_inverter = + get_single_child(xml_model, "lut_input_inverter", loc_data); + std::string input_inverter_circuit_model_name = + read_xml_buffer(xml_input_inverter, loc_data); + circuit_lib.set_model_lut_input_inverter( + model, true != input_inverter_circuit_model_name.empty(), + input_inverter_circuit_model_name); /* Intermediate buffer of LUTs */ - auto xml_intermediate_buffer = get_single_child(xml_model, "lut_intermediate_buffer", loc_data, pugiutil::ReqOpt::OPTIONAL); + auto xml_intermediate_buffer = + get_single_child(xml_model, "lut_intermediate_buffer", loc_data, + pugiutil::ReqOpt::OPTIONAL); if (xml_intermediate_buffer) { - std::string intermediate_buffer_circuit_model_name = read_xml_buffer(xml_intermediate_buffer, loc_data); - circuit_lib.set_model_lut_intermediate_buffer(model, - true != intermediate_buffer_circuit_model_name.empty(), - intermediate_buffer_circuit_model_name); + std::string intermediate_buffer_circuit_model_name = + read_xml_buffer(xml_intermediate_buffer, loc_data); + circuit_lib.set_model_lut_intermediate_buffer( + model, true != intermediate_buffer_circuit_model_name.empty(), + intermediate_buffer_circuit_model_name); /* If intermediate buffer is defined, try to find the location map */ - if (true != intermediate_buffer_circuit_model_name.empty()) { - circuit_lib.set_model_lut_intermediate_buffer_location_map(model, get_attribute(xml_intermediate_buffer, "location_map", loc_data).as_string()); + if (true != intermediate_buffer_circuit_model_name.empty()) { + circuit_lib.set_model_lut_intermediate_buffer_location_map( + model, + get_attribute(xml_intermediate_buffer, "location_map", loc_data) + .as_string()); } } } @@ -651,60 +794,72 @@ void read_xml_circuit_model(pugi::xml_node& xml_model, * - pass gate * - logic gates */ - if ((CIRCUIT_MODEL_INVBUF == circuit_lib.model_type(model)) - || (CIRCUIT_MODEL_PASSGATE == circuit_lib.model_type(model)) - || (CIRCUIT_MODEL_GATE == circuit_lib.model_type(model))) { - read_xml_model_device_technology(xml_model, loc_data, circuit_lib, model); + if ((CIRCUIT_MODEL_INVBUF == circuit_lib.model_type(model)) || + (CIRCUIT_MODEL_PASSGATE == circuit_lib.model_type(model)) || + (CIRCUIT_MODEL_GATE == circuit_lib.model_type(model))) { + read_xml_model_device_technology(xml_model, loc_data, circuit_lib, model); } - /* Input buffer attributes, NOT required for circuit models which are inverters or buffers */ + /* Input buffer attributes, NOT required for circuit models which are + * inverters or buffers */ if (CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(model)) { - auto xml_input_buffer = get_single_child(xml_model, "input_buffer", loc_data); - std::string input_buffer_circuit_model_name = read_xml_buffer(xml_input_buffer, loc_data); - circuit_lib.set_model_input_buffer(model, - true != input_buffer_circuit_model_name.empty(), - input_buffer_circuit_model_name); + auto xml_input_buffer = + get_single_child(xml_model, "input_buffer", loc_data); + std::string input_buffer_circuit_model_name = + read_xml_buffer(xml_input_buffer, loc_data); + circuit_lib.set_model_input_buffer( + model, true != input_buffer_circuit_model_name.empty(), + input_buffer_circuit_model_name); } - /* Output buffer attributes, NOT required for circuit models which are inverters or buffers */ + /* Output buffer attributes, NOT required for circuit models which are + * inverters or buffers */ if (CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(model)) { - auto xml_output_buffer = get_single_child(xml_model, "output_buffer", loc_data); - std::string output_buffer_circuit_model_name = read_xml_buffer(xml_output_buffer, loc_data); - circuit_lib.set_model_output_buffer(model, - true != output_buffer_circuit_model_name.empty(), - output_buffer_circuit_model_name); + auto xml_output_buffer = + get_single_child(xml_model, "output_buffer", loc_data); + std::string output_buffer_circuit_model_name = + read_xml_buffer(xml_output_buffer, loc_data); + circuit_lib.set_model_output_buffer( + model, true != output_buffer_circuit_model_name.empty(), + output_buffer_circuit_model_name); } /* Pass-gate-logic attributes, required by LUT and MUX */ - if ( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) - || (CIRCUIT_MODEL_MUX == circuit_lib.model_type(model)) ) { - auto xml_pass_gate_logic = get_single_child(xml_model, "pass_gate_logic", loc_data); - circuit_lib.set_model_pass_gate_logic(model, get_attribute(xml_pass_gate_logic, "circuit_model_name", loc_data).as_string()); - } + if ((CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) || + (CIRCUIT_MODEL_MUX == circuit_lib.model_type(model))) { + auto xml_pass_gate_logic = + get_single_child(xml_model, "pass_gate_logic", loc_data); + circuit_lib.set_model_pass_gate_logic( + model, get_attribute(xml_pass_gate_logic, "circuit_model_name", loc_data) + .as_string()); + } /* Parse all the ports belonging to this circuit model - * We count the number of ports in total and then add one by one + * We count the number of ports in total and then add one by one */ - size_t num_ports = count_children(xml_model, "port", loc_data, pugiutil::ReqOpt::OPTIONAL); + size_t num_ports = + count_children(xml_model, "port", loc_data, pugiutil::ReqOpt::OPTIONAL); if (0 < num_ports) { pugi::xml_node xml_port = get_first_child(xml_model, "port", loc_data); while (xml_port) { read_xml_circuit_port(xml_port, loc_data, circuit_lib, model); xml_port = xml_port.next_sibling(xml_port.name()); - } + } } /* Parse the parasitics of wires */ - if ( (CIRCUIT_MODEL_WIRE == circuit_lib.model_type(model)) - || (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) ) { - auto xml_wire_param = get_single_child(xml_model, "wire_param", loc_data); + if ((CIRCUIT_MODEL_WIRE == circuit_lib.model_type(model)) || + (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(model))) { + auto xml_wire_param = get_single_child(xml_model, "wire_param", loc_data); read_xml_wire_param(xml_wire_param, loc_data, circuit_lib, model); } /* Parse all the delay matrix if defined */ - size_t num_delay_matrix = count_children(xml_model, "delay_matrix", loc_data, pugiutil::ReqOpt::OPTIONAL); + size_t num_delay_matrix = count_children(xml_model, "delay_matrix", loc_data, + pugiutil::ReqOpt::OPTIONAL); if (0 < num_delay_matrix) { - pugi::xml_node xml_delay_matrix = get_first_child(xml_model, "delay_matrix", loc_data); + pugi::xml_node xml_delay_matrix = + get_first_child(xml_model, "delay_matrix", loc_data); while (xml_delay_matrix) { read_xml_delay_matrix(xml_delay_matrix, loc_data, circuit_lib, model); xml_delay_matrix = xml_delay_matrix.next_sibling(xml_delay_matrix.name()); @@ -728,8 +883,7 @@ CircuitLibrary read_xml_circuit_library(pugi::xml_node& Node, bad_tag(xml_model, loc_data, Node, {"circuit_model"}); } read_xml_circuit_model(xml_model, loc_data, circuit_lib); - } + } return circuit_lib; } - diff --git a/libs/libarchopenfpga/src/read_xml_circuit_library.h b/libs/libarchopenfpga/src/read_xml_circuit_library.h index cfab2eae6..16cd731a6 100644 --- a/libs/libarchopenfpga/src/read_xml_circuit_library.h +++ b/libs/libarchopenfpga/src/read_xml_circuit_library.h @@ -4,9 +4,9 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "pugixml_util.hpp" -#include "pugixml.hpp" #include "circuit_library.h" +#include "pugixml.hpp" +#include "pugixml_util.hpp" /******************************************************************** * Function declaration diff --git a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp index 0472b7d73..74572de54 100644 --- a/libs/libarchopenfpga/src/read_xml_config_protocol.cpp +++ b/libs/libarchopenfpga/src/read_xml_config_protocol.cpp @@ -14,19 +14,17 @@ /* Headers from libarchfpga */ #include "arch_error.h" -#include "read_xml_util.h" - #include "read_xml_config_protocol.h" +#include "read_xml_util.h" /******************************************************************** * Convert string to the enumerate of configuration protocol type *******************************************************************/ -static -e_config_protocol_type string_to_config_protocol_type(const std::string& type_string) { - +static e_config_protocol_type string_to_config_protocol_type( + const std::string& type_string) { for (size_t itype = 0; itype < NUM_CONFIG_PROTOCOL_TYPES; ++itype) { if (std::string(CONFIG_PROTOCOL_TYPE_STRING[itype]) == type_string) { - return static_cast(itype); + return static_cast(itype); } } @@ -36,12 +34,11 @@ e_config_protocol_type string_to_config_protocol_type(const std::string& type_st /******************************************************************** * Convert string to the enumerate of BL/WL protocol type *******************************************************************/ -static -e_blwl_protocol_type string_to_blwl_protocol_type(const std::string& type_string) { - +static e_blwl_protocol_type string_to_blwl_protocol_type( + const std::string& type_string) { for (size_t itype = 0; itype < NUM_BLWL_PROTOCOL_TYPES; ++itype) { if (std::string(BLWL_PROTOCOL_TYPE_STRING[itype]) == type_string) { - return static_cast(itype); + return static_cast(itype); } } @@ -51,19 +48,19 @@ e_blwl_protocol_type string_to_blwl_protocol_type(const std::string& type_string /******************************************************************** * Parse XML codes of a to an object of configuration protocol *******************************************************************/ -static -void read_xml_bl_protocol(pugi::xml_node& xml_bl_protocol, - const pugiutil::loc_data& loc_data, - ConfigProtocol& config_protocol) { +static void read_xml_bl_protocol(pugi::xml_node& xml_bl_protocol, + const pugiutil::loc_data& loc_data, + ConfigProtocol& config_protocol) { /* Find the type of configuration protocol */ - const char* type_attr = get_attribute(xml_bl_protocol, "protocol", loc_data).value(); + const char* type_attr = + get_attribute(xml_bl_protocol, "protocol", loc_data).value(); /* Translate the type of design technology to enumerate */ - e_blwl_protocol_type blwl_protocol_type = string_to_blwl_protocol_type(std::string(type_attr)); + e_blwl_protocol_type blwl_protocol_type = + string_to_blwl_protocol_type(std::string(type_attr)); if (NUM_BLWL_PROTOCOL_TYPES == blwl_protocol_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bl_protocol), - "Invalid 'protocol' attribute '%s'\n", - type_attr); + "Invalid 'protocol' attribute '%s'\n", type_attr); } config_protocol.set_bl_protocol_type(blwl_protocol_type); @@ -73,27 +70,32 @@ void read_xml_bl_protocol(pugi::xml_node& xml_bl_protocol, * - Find the number of shift register chains for each protocol */ if (BLWL_PROTOCOL_SHIFT_REGISTER == blwl_protocol_type) { - config_protocol.set_bl_memory_model_name(get_attribute(xml_bl_protocol, "circuit_model_name", loc_data).as_string()); - config_protocol.set_bl_num_banks(get_attribute(xml_bl_protocol, "num_banks", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(1)); + config_protocol.set_bl_memory_model_name( + get_attribute(xml_bl_protocol, "circuit_model_name", loc_data) + .as_string()); + config_protocol.set_bl_num_banks(get_attribute(xml_bl_protocol, "num_banks", + loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_int(1)); } } /******************************************************************** * Parse XML codes of a to an object of configuration protocol *******************************************************************/ -static -void read_xml_wl_protocol(pugi::xml_node& xml_wl_protocol, - const pugiutil::loc_data& loc_data, - ConfigProtocol& config_protocol) { +static void read_xml_wl_protocol(pugi::xml_node& xml_wl_protocol, + const pugiutil::loc_data& loc_data, + ConfigProtocol& config_protocol) { /* Find the type of configuration protocol */ - const char* type_attr = get_attribute(xml_wl_protocol, "protocol", loc_data).value(); + const char* type_attr = + get_attribute(xml_wl_protocol, "protocol", loc_data).value(); /* Translate the type of design technology to enumerate */ - e_blwl_protocol_type blwl_protocol_type = string_to_blwl_protocol_type(std::string(type_attr)); + e_blwl_protocol_type blwl_protocol_type = + string_to_blwl_protocol_type(std::string(type_attr)); if (NUM_BLWL_PROTOCOL_TYPES == blwl_protocol_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_wl_protocol), - "Invalid 'protocol' attribute '%s'\n", - type_attr); + "Invalid 'protocol' attribute '%s'\n", type_attr); } config_protocol.set_wl_protocol_type(blwl_protocol_type); @@ -103,60 +105,75 @@ void read_xml_wl_protocol(pugi::xml_node& xml_wl_protocol, * - Find the number of shift register chains for each protocol */ if (BLWL_PROTOCOL_SHIFT_REGISTER == blwl_protocol_type) { - config_protocol.set_wl_memory_model_name(get_attribute(xml_wl_protocol, "circuit_model_name", loc_data).as_string()); - config_protocol.set_wl_num_banks(get_attribute(xml_wl_protocol, "num_banks", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(1)); + config_protocol.set_wl_memory_model_name( + get_attribute(xml_wl_protocol, "circuit_model_name", loc_data) + .as_string()); + config_protocol.set_wl_num_banks(get_attribute(xml_wl_protocol, "num_banks", + loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_int(1)); } } /******************************************************************** * Parse XML codes of a to an object of configuration protocol *******************************************************************/ -static -void read_xml_config_organization(pugi::xml_node& xml_config_orgz, - const pugiutil::loc_data& loc_data, - ConfigProtocol& config_protocol) { +static void read_xml_config_organization(pugi::xml_node& xml_config_orgz, + const pugiutil::loc_data& loc_data, + ConfigProtocol& config_protocol) { /* Find the type of configuration protocol */ - const char* type_attr = get_attribute(xml_config_orgz, "type", loc_data).value(); + const char* type_attr = + get_attribute(xml_config_orgz, "type", loc_data).value(); /* Translate the type of design technology to enumerate */ - e_config_protocol_type config_orgz_type = string_to_config_protocol_type(std::string(type_attr)); + e_config_protocol_type config_orgz_type = + string_to_config_protocol_type(std::string(type_attr)); if (NUM_CONFIG_PROTOCOL_TYPES == config_orgz_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_config_orgz), - "Invalid 'type' attribute '%s'\n", - type_attr); + "Invalid 'type' attribute '%s'\n", type_attr); } config_protocol.set_type(config_orgz_type); /* Find the circuit model used by the configuration protocol */ - config_protocol.set_memory_model_name(get_attribute(xml_config_orgz, "circuit_model_name", loc_data).as_string()); + config_protocol.set_memory_model_name( + get_attribute(xml_config_orgz, "circuit_model_name", loc_data).as_string()); /* Parse the number of configurable regions - * At least 1 region should be defined, otherwise error out + * At least 1 region should be defined, otherwise error out */ - config_protocol.set_num_regions(get_attribute(xml_config_orgz, "num_regions", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(1)); + config_protocol.set_num_regions(get_attribute(xml_config_orgz, "num_regions", + 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 should be defined!\n", + "Invalid 'num_region=%d' definition. At least 1 region " + "should be defined!\n", config_protocol.num_regions()); } /* Parse BL & WL protocols */ if (config_protocol.type() == CONFIG_MEM_QL_MEMORY_BANK) { - pugi::xml_node xml_bl_protocol = get_single_child(xml_config_orgz, "bl", loc_data, pugiutil::ReqOpt::OPTIONAL); + pugi::xml_node xml_bl_protocol = get_single_child( + xml_config_orgz, "bl", loc_data, pugiutil::ReqOpt::OPTIONAL); if (xml_bl_protocol) { read_xml_bl_protocol(xml_bl_protocol, loc_data, config_protocol); } - pugi::xml_node xml_wl_protocol = get_single_child(xml_config_orgz, "wl", loc_data, pugiutil::ReqOpt::OPTIONAL); + pugi::xml_node xml_wl_protocol = get_single_child( + xml_config_orgz, "wl", loc_data, pugiutil::ReqOpt::OPTIONAL); if (xml_wl_protocol) { read_xml_wl_protocol(xml_wl_protocol, loc_data, config_protocol); } - - /* Throw an execption if the BL/WL protocols are different. We currently do not support it! */ - if (config_protocol.bl_protocol_type() != config_protocol.wl_protocol_type()) { + + /* Throw an execption if the BL/WL protocols are different. We currently do + * not support it! */ + if (config_protocol.bl_protocol_type() != + config_protocol.wl_protocol_type()) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_config_orgz), - "Expect same type of protocol for both BL and WL! Other combinations are not supported yet\n"); + "Expect same type of protocol for both BL and WL! Other " + "combinations are not supported yet\n"); } } } @@ -169,11 +186,12 @@ ConfigProtocol read_xml_config_protocol(pugi::xml_node& Node, ConfigProtocol config_protocol; /* Parse configuration protocol root node */ - pugi::xml_node xml_config = get_single_child(Node, "configuration_protocol", loc_data); + pugi::xml_node xml_config = + get_single_child(Node, "configuration_protocol", loc_data); - pugi::xml_node xml_config_orgz = get_single_child(xml_config, "organization", loc_data); + pugi::xml_node xml_config_orgz = + get_single_child(xml_config, "organization", loc_data); read_xml_config_organization(xml_config_orgz, loc_data, config_protocol); return config_protocol; } - diff --git a/libs/libarchopenfpga/src/read_xml_config_protocol.h b/libs/libarchopenfpga/src/read_xml_config_protocol.h index 5a26c3a01..c862cbda9 100644 --- a/libs/libarchopenfpga/src/read_xml_config_protocol.h +++ b/libs/libarchopenfpga/src/read_xml_config_protocol.h @@ -4,9 +4,9 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "pugixml_util.hpp" -#include "pugixml.hpp" #include "config_protocol.h" +#include "pugixml.hpp" +#include "pugixml_util.hpp" /******************************************************************** * Function declaration diff --git a/libs/libarchopenfpga/src/read_xml_openfpga_arch.cpp b/libs/libarchopenfpga/src/read_xml_openfpga_arch.cpp index ad0c88b4d..c83d7c1a6 100644 --- a/libs/libarchopenfpga/src/read_xml_openfpga_arch.cpp +++ b/libs/libarchopenfpga/src/read_xml_openfpga_arch.cpp @@ -14,18 +14,17 @@ /* Headers from libarchfpga */ #include "arch_error.h" -#include "read_xml_util.h" - -#include "read_xml_technology_library.h" -#include "read_xml_circuit_library.h" -#include "read_xml_simulation_setting.h" -#include "read_xml_config_protocol.h" -#include "read_xml_routing_circuit.h" -#include "read_xml_tile_annotation.h" -#include "read_xml_pb_type_annotation.h" -#include "read_xml_bitstream_setting.h" -#include "read_xml_openfpga_arch.h" #include "openfpga_arch_linker.h" +#include "read_xml_bitstream_setting.h" +#include "read_xml_circuit_library.h" +#include "read_xml_config_protocol.h" +#include "read_xml_openfpga_arch.h" +#include "read_xml_pb_type_annotation.h" +#include "read_xml_routing_circuit.h" +#include "read_xml_simulation_setting.h" +#include "read_xml_technology_library.h" +#include "read_xml_tile_annotation.h" +#include "read_xml_util.h" /******************************************************************** * Top-level function to parse an XML file and load data to : @@ -46,26 +45,31 @@ openfpga::Arch read_xml_openfpga_arch(const char* arch_file_name) { loc_data = pugiutil::load_xml(doc, arch_file_name); /* First node should be */ - auto xml_openfpga_arch = get_single_child(doc, "openfpga_architecture", loc_data); + auto xml_openfpga_arch = + get_single_child(doc, "openfpga_architecture", loc_data); - /* Parse circuit_models to circuit library - * under the node + /* Parse circuit_models to circuit library + * under the node */ - auto xml_circuit_models = get_single_child(xml_openfpga_arch, "circuit_library", loc_data); - openfpga_arch.circuit_lib = read_xml_circuit_library(xml_circuit_models, loc_data); + auto xml_circuit_models = + get_single_child(xml_openfpga_arch, "circuit_library", loc_data); + openfpga_arch.circuit_lib = + read_xml_circuit_library(xml_circuit_models, loc_data); /* Automatically identify the default models for circuit library */ openfpga_arch.circuit_lib.auto_detect_default_models(); /* Build the internal links for the circuit library */ openfpga_arch.circuit_lib.build_model_links(); - + /* Build the timing graph inside the circuit library */ openfpga_arch.circuit_lib.build_timing_graphs(); /* Parse technology library */ - auto xml_tech_lib = get_single_child(xml_openfpga_arch, "technology_library", loc_data); - openfpga_arch.tech_lib = read_xml_technology_library(xml_tech_lib, loc_data); + auto xml_tech_lib = + get_single_child(xml_openfpga_arch, "technology_library", loc_data); + openfpga_arch.tech_lib = + read_xml_technology_library(xml_tech_lib, loc_data); /* Build the internal link for technology library */ openfpga_arch.tech_lib.link_models_to_variations(); @@ -73,47 +77,49 @@ openfpga::Arch read_xml_openfpga_arch(const char* arch_file_name) { bind_circuit_model_to_technology_model(openfpga_arch); /* Parse configuration protocol to data structure */ - openfpga_arch.config_protocol = read_xml_config_protocol(xml_openfpga_arch, loc_data); + openfpga_arch.config_protocol = + read_xml_config_protocol(xml_openfpga_arch, loc_data); - /* Build the internal link between configuration protocol and circuit library */ + /* Build the internal link between configuration protocol and circuit + * library */ link_config_protocol_to_circuit_library(openfpga_arch); - /* Now, we can know the default configurable memory model + /* Now, we can know the default configurable memory model * Apply it to all the SRAM ports of circuit models */ - config_circuit_models_sram_port_to_default_sram_model(openfpga_arch.circuit_lib, - openfpga_arch.config_protocol.memory_model()); - + config_circuit_models_sram_port_to_default_sram_model( + openfpga_arch.circuit_lib, openfpga_arch.config_protocol.memory_model()); /* Parse the connection block circuit definition */ - openfpga_arch.cb_switch2circuit = read_xml_cb_switch_circuit(xml_openfpga_arch, loc_data, - openfpga_arch.circuit_lib); + openfpga_arch.cb_switch2circuit = read_xml_cb_switch_circuit( + xml_openfpga_arch, loc_data, openfpga_arch.circuit_lib); /* Parse the connection block circuit definition */ - openfpga_arch.cb_switch2circuit = read_xml_cb_switch_circuit(xml_openfpga_arch, loc_data, - openfpga_arch.circuit_lib); + openfpga_arch.cb_switch2circuit = read_xml_cb_switch_circuit( + xml_openfpga_arch, loc_data, openfpga_arch.circuit_lib); /* Parse the switch block circuit definition */ - openfpga_arch.sb_switch2circuit = read_xml_sb_switch_circuit(xml_openfpga_arch, loc_data, - openfpga_arch.circuit_lib); + openfpga_arch.sb_switch2circuit = read_xml_sb_switch_circuit( + xml_openfpga_arch, loc_data, openfpga_arch.circuit_lib); /* Parse the routing segment circuit definition */ - openfpga_arch.routing_seg2circuit = read_xml_routing_segment_circuit(xml_openfpga_arch, loc_data, - openfpga_arch.circuit_lib); + openfpga_arch.routing_seg2circuit = read_xml_routing_segment_circuit( + xml_openfpga_arch, loc_data, openfpga_arch.circuit_lib); /* Parse the direct circuit definition */ - openfpga_arch.arch_direct = read_xml_direct_circuit(xml_openfpga_arch, loc_data, - openfpga_arch.circuit_lib); + openfpga_arch.arch_direct = read_xml_direct_circuit( + xml_openfpga_arch, loc_data, openfpga_arch.circuit_lib); /* Parse the pb_type annotation */ - openfpga_arch.tile_annotations = read_xml_tile_annotations(xml_openfpga_arch, loc_data); + openfpga_arch.tile_annotations = + read_xml_tile_annotations(xml_openfpga_arch, loc_data); /* Parse the pb_type annotation */ - openfpga_arch.pb_type_annotations = read_xml_pb_type_annotations(xml_openfpga_arch, loc_data); + openfpga_arch.pb_type_annotations = + read_xml_pb_type_annotations(xml_openfpga_arch, loc_data); } catch (pugiutil::XmlError& e) { - archfpga_throw(arch_file_name, e.line(), - "%s", e.what()); + archfpga_throw(arch_file_name, e.line(), "%s", e.what()); } return openfpga_arch; @@ -122,7 +128,8 @@ openfpga::Arch read_xml_openfpga_arch(const char* arch_file_name) { /******************************************************************** * Top-level function to parse an XML file and load data to simulation settings *******************************************************************/ -openfpga::SimulationSetting read_xml_openfpga_simulation_settings(const char* sim_setting_file_name) { +openfpga::SimulationSetting read_xml_openfpga_simulation_settings( + const char* sim_setting_file_name) { vtr::ScopedStartFinishTimer timer("Read OpenFPGA simulation settings"); openfpga::SimulationSetting openfpga_sim_setting; @@ -137,23 +144,25 @@ openfpga::SimulationSetting read_xml_openfpga_simulation_settings(const char* si loc_data = pugiutil::load_xml(doc, sim_setting_file_name); /* Second node should be */ - auto xml_simulation_settings = get_single_child(doc, "openfpga_simulation_setting", loc_data); + auto xml_simulation_settings = + get_single_child(doc, "openfpga_simulation_setting", loc_data); /* Parse simulation settings to data structure */ - openfpga_sim_setting = read_xml_simulation_setting(xml_simulation_settings, loc_data); + openfpga_sim_setting = + read_xml_simulation_setting(xml_simulation_settings, loc_data); } catch (pugiutil::XmlError& e) { - archfpga_throw(sim_setting_file_name, e.line(), - "%s", e.what()); + archfpga_throw(sim_setting_file_name, e.line(), "%s", e.what()); } - return openfpga_sim_setting; + return openfpga_sim_setting; } /******************************************************************** * Top-level function to parse an XML file and load data to bitstream settings *******************************************************************/ -openfpga::BitstreamSetting read_xml_openfpga_bitstream_settings(const char* bitstream_setting_file_name) { +openfpga::BitstreamSetting read_xml_openfpga_bitstream_settings( + const char* bitstream_setting_file_name) { vtr::ScopedStartFinishTimer timer("Read OpenFPGA bitstream settings"); openfpga::BitstreamSetting openfpga_bitstream_setting; @@ -168,16 +177,16 @@ openfpga::BitstreamSetting read_xml_openfpga_bitstream_settings(const char* bits loc_data = pugiutil::load_xml(doc, bitstream_setting_file_name); /* Second node should be */ - auto xml_bitstream_settings = get_single_child(doc, "openfpga_bitstream_setting", loc_data); + auto xml_bitstream_settings = + get_single_child(doc, "openfpga_bitstream_setting", loc_data); /* Parse simulation settings to data structure */ - openfpga_bitstream_setting = read_xml_bitstream_setting(xml_bitstream_settings, loc_data); + openfpga_bitstream_setting = + read_xml_bitstream_setting(xml_bitstream_settings, loc_data); } catch (pugiutil::XmlError& e) { - archfpga_throw(bitstream_setting_file_name, e.line(), - "%s", e.what()); + archfpga_throw(bitstream_setting_file_name, e.line(), "%s", e.what()); } - return openfpga_bitstream_setting; + return openfpga_bitstream_setting; } - diff --git a/libs/libarchopenfpga/src/read_xml_openfpga_arch.h b/libs/libarchopenfpga/src/read_xml_openfpga_arch.h index 920ba20e1..1c2858263 100644 --- a/libs/libarchopenfpga/src/read_xml_openfpga_arch.h +++ b/libs/libarchopenfpga/src/read_xml_openfpga_arch.h @@ -5,17 +5,20 @@ * Include header files that are required by function declaration *******************************************************************/ #include + +#include "bitstream_setting.h" #include "openfpga_arch.h" #include "simulation_setting.h" -#include "bitstream_setting.h" /******************************************************************** * Function declaration *******************************************************************/ openfpga::Arch read_xml_openfpga_arch(const char* arch_file_name); -openfpga::SimulationSetting read_xml_openfpga_simulation_settings(const char* sim_setting_file_name); +openfpga::SimulationSetting read_xml_openfpga_simulation_settings( + const char* sim_setting_file_name); -openfpga::BitstreamSetting read_xml_openfpga_bitstream_settings(const char* bitstream_setting_file_name); +openfpga::BitstreamSetting read_xml_openfpga_bitstream_settings( + const char* bitstream_setting_file_name); #endif diff --git a/libs/libarchopenfpga/src/read_xml_pb_type_annotation.cpp b/libs/libarchopenfpga/src/read_xml_pb_type_annotation.cpp index f91dc99a8..8e2075bb6 100644 --- a/libs/libarchopenfpga/src/read_xml_pb_type_annotation.cpp +++ b/libs/libarchopenfpga/src/read_xml_pb_type_annotation.cpp @@ -13,47 +13,49 @@ #include "vtr_assert.h" /* Headers from openfpga util library */ -#include "openfpga_port_parser.h" #include "openfpga_pb_parser.h" +#include "openfpga_port_parser.h" /* Headers from libarchfpga */ #include "arch_error.h" +#include "read_xml_pb_type_annotation.h" #include "read_xml_util.h" -#include "read_xml_pb_type_annotation.h" - /******************************************************************** - * Parse XML description for an interconnection annotation + * Parse XML description for an interconnection annotation * under a XML node *******************************************************************/ -static -void read_xml_interc_annotation(pugi::xml_node& xml_interc, - const pugiutil::loc_data& loc_data, - openfpga::PbTypeAnnotation& pb_type_annotation) { +static void read_xml_interc_annotation( + pugi::xml_node& xml_interc, const pugiutil::loc_data& loc_data, + openfpga::PbTypeAnnotation& pb_type_annotation) { /* We have two mandatory XML attribute * 1. name of the interconnect - * 2. circuit model name of the interconnect + * 2. circuit model name of the interconnect */ - const std::string& name_attr = get_attribute(xml_interc, "name", loc_data).as_string(); - const std::string& circuit_model_name_attr = get_attribute(xml_interc, "circuit_model_name", loc_data).as_string(); + const std::string& name_attr = + get_attribute(xml_interc, "name", loc_data).as_string(); + const std::string& circuit_model_name_attr = + get_attribute(xml_interc, "circuit_model_name", loc_data).as_string(); - pb_type_annotation.add_interconnect_circuit_model_pair(name_attr, circuit_model_name_attr); + pb_type_annotation.add_interconnect_circuit_model_pair( + name_attr, circuit_model_name_attr); } /******************************************************************** - * Parse XML description for a pb_type port annotation + * Parse XML description for a pb_type port annotation * under a XML node *******************************************************************/ -static -void read_xml_pb_port_annotation(pugi::xml_node& xml_port, - const pugiutil::loc_data& loc_data, - openfpga::PbTypeAnnotation& pb_type_annotation) { +static void read_xml_pb_port_annotation( + pugi::xml_node& xml_port, const pugiutil::loc_data& loc_data, + openfpga::PbTypeAnnotation& pb_type_annotation) { /* We have two mandatory XML attribute * 1. name of the port * 2. name of the port to be binded in physical mode */ - const std::string& name_attr = get_attribute(xml_port, "name", loc_data).as_string(); - const std::string& physical_mode_port_attr = get_attribute(xml_port, "physical_mode_port", loc_data).as_string(); + const std::string& name_attr = + get_attribute(xml_port, "name", loc_data).as_string(); + const std::string& physical_mode_port_attr = + get_attribute(xml_port, "physical_mode_port", loc_data).as_string(); /* Split the physical mode port attributes with space */ openfpga::StringToken port_tokenizer(physical_mode_port_attr); @@ -61,82 +63,91 @@ void read_xml_pb_port_annotation(pugi::xml_node& xml_port, /* Parse the mode port using openfpga port parser */ for (const auto& physical_mode_port : physical_mode_ports) { - openfpga::PortParser port_parser(physical_mode_port); + openfpga::PortParser port_parser(physical_mode_port); pb_type_annotation.add_pb_type_port_pair(name_attr, port_parser.port()); } /* We have an optional attribute: physical_mode_pin_initial_offset * Split based on the number of physical pb_type ports that have been defined */ - const std::string& physical_pin_initial_offset_attr = get_attribute(xml_port, "physical_mode_pin_initial_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(); + const std::string& physical_pin_initial_offset_attr = + get_attribute(xml_port, "physical_mode_pin_initial_offset", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string(); if (false == physical_pin_initial_offset_attr.empty()) { /* Split the physical mode port attributes with space */ openfpga::StringToken offset_tokenizer(physical_pin_initial_offset_attr); const std::vector initial_offsets = offset_tokenizer.split(); - + /* Error out if the offset does not match the port definition */ if (physical_mode_ports.size() != initial_offsets.size()) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_port), - "Defined %lu physical mode ports but only %lu physical pin initial offset are defined! Expect size matching.\n", - physical_mode_ports.size(), initial_offsets.size()); + "Defined %lu physical mode ports but only %lu physical " + "pin initial offset are defined! Expect size matching.\n", + physical_mode_ports.size(), initial_offsets.size()); } for (size_t iport = 0; iport < physical_mode_ports.size(); ++iport) { - openfpga::PortParser port_parser(physical_mode_ports[iport]); - pb_type_annotation.set_physical_pin_initial_offset(name_attr, - port_parser.port(), - std::stoi(initial_offsets[iport])); + openfpga::PortParser port_parser(physical_mode_ports[iport]); + pb_type_annotation.set_physical_pin_initial_offset( + name_attr, port_parser.port(), std::stoi(initial_offsets[iport])); } } /* We have an optional attribute: physical_mode_pin_rotate_offset * Split based on the number of physical pb_type ports that have been defined */ - const std::string& physical_pin_rotate_offset_attr = get_attribute(xml_port, "physical_mode_pin_rotate_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(); + const std::string& physical_pin_rotate_offset_attr = + get_attribute(xml_port, "physical_mode_pin_rotate_offset", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string(); if (false == physical_pin_rotate_offset_attr.empty()) { /* Split the physical mode port attributes with space */ openfpga::StringToken offset_tokenizer(physical_pin_rotate_offset_attr); const std::vector rotate_offsets = offset_tokenizer.split(); - + /* Error out if the offset does not match the port definition */ if (physical_mode_ports.size() != rotate_offsets.size()) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_port), - "Defined %lu physical mode ports but only %lu physical pin rotate offset are defined! Expect size matching.\n", - physical_mode_ports.size(), rotate_offsets.size()); + "Defined %lu physical mode ports but only %lu physical " + "pin rotate offset are defined! Expect size matching.\n", + physical_mode_ports.size(), rotate_offsets.size()); } for (size_t iport = 0; iport < physical_mode_ports.size(); ++iport) { - openfpga::PortParser port_parser(physical_mode_ports[iport]); - pb_type_annotation.set_physical_pin_rotate_offset(name_attr, - port_parser.port(), - std::stoi(rotate_offsets[iport])); + openfpga::PortParser port_parser(physical_mode_ports[iport]); + pb_type_annotation.set_physical_pin_rotate_offset( + name_attr, port_parser.port(), std::stoi(rotate_offsets[iport])); } } /* We have an optional attribute: physical_mode_port_rotate_offset * Split based on the number of physical pb_type ports that have been defined */ - const std::string& physical_port_rotate_offset_attr = get_attribute(xml_port, "physical_mode_port_rotate_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(); + const std::string& physical_port_rotate_offset_attr = + get_attribute(xml_port, "physical_mode_port_rotate_offset", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string(); if (false == physical_port_rotate_offset_attr.empty()) { /* Split the physical mode port attributes with space */ openfpga::StringToken offset_tokenizer(physical_port_rotate_offset_attr); const std::vector rotate_offsets = offset_tokenizer.split(); - + /* Error out if the offset does not match the port definition */ if (physical_mode_ports.size() != rotate_offsets.size()) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_port), - "Defined %lu physical mode ports but only %lu physical port rotate offset are defined! Expect size matching.\n", - physical_mode_ports.size(), rotate_offsets.size()); + "Defined %lu physical mode ports but only %lu physical " + "port rotate offset are defined! Expect size matching.\n", + physical_mode_ports.size(), rotate_offsets.size()); } for (size_t iport = 0; iport < physical_mode_ports.size(); ++iport) { - openfpga::PortParser port_parser(physical_mode_ports[iport]); - pb_type_annotation.set_physical_port_rotate_offset(name_attr, - port_parser.port(), - std::stoi(rotate_offsets[iport])); + openfpga::PortParser port_parser(physical_mode_ports[iport]); + pb_type_annotation.set_physical_port_rotate_offset( + name_attr, port_parser.port(), std::stoi(rotate_offsets[iport])); } } } @@ -145,10 +156,9 @@ void read_xml_pb_port_annotation(pugi::xml_node& xml_port, * Parse mode_bits: convert from string to array of digits * We only allow the bit to either '0' or '1' *******************************************************************/ -static -std::vector parse_mode_bits(pugi::xml_node& xml_mode_bits, - const pugiutil::loc_data& loc_data, - const std::string& mode_bit_str) { +static std::vector parse_mode_bits(pugi::xml_node& xml_mode_bits, + const pugiutil::loc_data& loc_data, + const std::string& mode_bit_str) { std::vector mode_bits; for (const char& bit_char : mode_bit_str) { @@ -158,10 +168,11 @@ std::vector parse_mode_bits(pugi::xml_node& xml_mode_bits, mode_bits.push_back(1); } else { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_mode_bits), - "Unexpected '%c' character found in the mode bit '%s'! Only allow either '0' or '1'\n", + "Unexpected '%c' character found in the mode bit '%s'! " + "Only allow either '0' or '1'\n", bit_char, mode_bit_str.c_str()); } - } + } return mode_bits; } @@ -169,115 +180,146 @@ std::vector parse_mode_bits(pugi::xml_node& xml_mode_bits, /******************************************************************** * Parse XML description for a pb_type annotation under a XML node *******************************************************************/ -static -void read_xml_pb_type_annotation(pugi::xml_node& xml_pb_type, - const pugiutil::loc_data& loc_data, - std::vector& pb_type_annotations) { +static void read_xml_pb_type_annotation( + pugi::xml_node& xml_pb_type, const pugiutil::loc_data& loc_data, + std::vector& pb_type_annotations) { openfpga::PbTypeAnnotation pb_type_annotation; /* Find the name of pb_type */ - const std::string& name_attr = get_attribute(xml_pb_type, "name", loc_data).as_string(); - const std::string& physical_name_attr = get_attribute(xml_pb_type, "physical_pb_type_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(); + const std::string& name_attr = + get_attribute(xml_pb_type, "name", loc_data).as_string(); + const std::string& physical_name_attr = + get_attribute(xml_pb_type, "physical_pb_type_name", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string(); /* If both names are not empty, this is a operating pb_type */ - if ( (false == name_attr.empty()) - && (false == physical_name_attr.empty()) ) { + if ((false == name_attr.empty()) && (false == physical_name_attr.empty())) { /* Parse the attributes for operating pb_type */ openfpga::PbParser operating_pb_parser(name_attr); pb_type_annotation.set_operating_pb_type_name(operating_pb_parser.leaf()); if (0 < operating_pb_parser.parents().size()) { - pb_type_annotation.set_operating_parent_pb_type_names(operating_pb_parser.parents()); + pb_type_annotation.set_operating_parent_pb_type_names( + operating_pb_parser.parents()); } if (0 < operating_pb_parser.modes().size()) { - pb_type_annotation.set_operating_parent_mode_names(operating_pb_parser.modes()); + pb_type_annotation.set_operating_parent_mode_names( + operating_pb_parser.modes()); } openfpga::PbParser physical_pb_parser(physical_name_attr); pb_type_annotation.set_physical_pb_type_name(physical_pb_parser.leaf()); if (0 < physical_pb_parser.parents().size()) { - pb_type_annotation.set_physical_parent_pb_type_names(physical_pb_parser.parents()); + pb_type_annotation.set_physical_parent_pb_type_names( + physical_pb_parser.parents()); } if (0 < physical_pb_parser.modes().size()) { - pb_type_annotation.set_physical_parent_mode_names(physical_pb_parser.modes()); + pb_type_annotation.set_physical_parent_mode_names( + physical_pb_parser.modes()); } - } + } /* If there is only a name, this is a physical pb_type */ - if ( (false == name_attr.empty()) - && (true == physical_name_attr.empty()) ) { + if ((false == name_attr.empty()) && (true == physical_name_attr.empty())) { openfpga::PbParser physical_pb_parser(name_attr); pb_type_annotation.set_physical_pb_type_name(physical_pb_parser.leaf()); if (0 < physical_pb_parser.parents().size()) { - pb_type_annotation.set_physical_parent_pb_type_names(physical_pb_parser.parents()); + pb_type_annotation.set_physical_parent_pb_type_names( + physical_pb_parser.parents()); } if (0 < physical_pb_parser.modes().size()) { - pb_type_annotation.set_physical_parent_mode_names(physical_pb_parser.modes()); + pb_type_annotation.set_physical_parent_mode_names( + physical_pb_parser.modes()); } } /* Parse physical mode name which are applied to both pb_types */ - pb_type_annotation.set_physical_mode_name(get_attribute(xml_pb_type, "physical_mode_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string()); + pb_type_annotation.set_physical_mode_name( + get_attribute(xml_pb_type, "physical_mode_name", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string()); /* Parse idle mode name which are applied to both pb_types */ - pb_type_annotation.set_idle_mode_name(get_attribute(xml_pb_type, "idle_mode_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string()); + pb_type_annotation.set_idle_mode_name( + get_attribute(xml_pb_type, "idle_mode_name", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string()); /* Parse mode bits which are applied to both pb_types */ - std::vector mode_bit_data = parse_mode_bits(xml_pb_type, loc_data, get_attribute(xml_pb_type, "mode_bits", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string()); + std::vector mode_bit_data = + parse_mode_bits(xml_pb_type, loc_data, + get_attribute(xml_pb_type, "mode_bits", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string()); pb_type_annotation.set_mode_bits(mode_bit_data); - /* If this is a physical pb_type, circuit model name is an optional attribute, - * which is applicable to leaf pb_type in the hierarchy + /* If this is a physical pb_type, circuit model name is an optional attribute, + * which is applicable to leaf pb_type in the hierarchy */ if (true == pb_type_annotation.is_physical_pb_type()) { - pb_type_annotation.set_circuit_model_name(get_attribute(xml_pb_type, "circuit_model_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string()); + pb_type_annotation.set_circuit_model_name( + get_attribute(xml_pb_type, "circuit_model_name", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string()); } - /* If this is an operating pb_type, index factor and offset may be optional needed */ + /* If this is an operating pb_type, index factor and offset may be optional + * needed */ if (true == pb_type_annotation.is_operating_pb_type()) { - pb_type_annotation.set_physical_pb_type_index_factor(get_attribute(xml_pb_type, "physical_pb_type_index_factor", loc_data, pugiutil::ReqOpt::OPTIONAL).as_float(1.)); - pb_type_annotation.set_physical_pb_type_index_offset(get_attribute(xml_pb_type, "physical_pb_type_index_offset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(0)); + pb_type_annotation.set_physical_pb_type_index_factor( + get_attribute(xml_pb_type, "physical_pb_type_index_factor", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_float(1.)); + pb_type_annotation.set_physical_pb_type_index_offset( + get_attribute(xml_pb_type, "physical_pb_type_index_offset", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_int(0)); } /* Parse all the interconnect-to-circuit binding under this node * All the bindings are defined in child node */ - size_t num_intercs = count_children(xml_pb_type, "interconnect", loc_data, pugiutil::ReqOpt::OPTIONAL); + size_t num_intercs = count_children(xml_pb_type, "interconnect", loc_data, + pugiutil::ReqOpt::OPTIONAL); if (0 < num_intercs) { - pugi::xml_node xml_interc = get_first_child(xml_pb_type, "interconnect", loc_data); + pugi::xml_node xml_interc = + get_first_child(xml_pb_type, "interconnect", loc_data); while (xml_interc) { read_xml_interc_annotation(xml_interc, loc_data, pb_type_annotation); xml_interc = xml_interc.next_sibling(xml_interc.name()); - } + } } - /* Parse all the port-to-port binding from operating pb_type to physical pb_type under this node - * All the bindings are defined in child node + /* Parse all the port-to-port binding from operating pb_type to physical + * pb_type under this node All the bindings are defined in child node * This is only applicable to operating pb_type */ if (true == pb_type_annotation.is_operating_pb_type()) { - size_t num_ports = count_children(xml_pb_type, "port", loc_data, pugiutil::ReqOpt::OPTIONAL); + size_t num_ports = + count_children(xml_pb_type, "port", loc_data, pugiutil::ReqOpt::OPTIONAL); if (0 < num_ports) { pugi::xml_node xml_port = get_first_child(xml_pb_type, "port", loc_data); while (xml_port) { read_xml_pb_port_annotation(xml_port, loc_data, pb_type_annotation); xml_port = xml_port.next_sibling(xml_port.name()); - } + } } } - /* Finish parsing and add it to the vector */ + /* Finish parsing and add it to the vector */ pb_type_annotations.push_back(pb_type_annotation); } /******************************************************************** - * Top function to parse XML description about pb_type annotation + * Top function to parse XML description about pb_type annotation *******************************************************************/ -std::vector read_xml_pb_type_annotations(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data) { +std::vector read_xml_pb_type_annotations( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data) { std::vector pb_type_annotations; /* Parse configuration protocol root node */ - pugi::xml_node xml_annotations = get_single_child(Node, "pb_type_annotations", loc_data); + pugi::xml_node xml_annotations = + get_single_child(Node, "pb_type_annotations", loc_data); /* Iterate over the children under this node, * each child should be named after @@ -288,7 +330,7 @@ std::vector read_xml_pb_type_annotations(pugi::xml_n bad_tag(xml_pb_type, loc_data, xml_annotations, {"pb_type"}); } read_xml_pb_type_annotation(xml_pb_type, loc_data, pb_type_annotations); - } + } return pb_type_annotations; } diff --git a/libs/libarchopenfpga/src/read_xml_pb_type_annotation.h b/libs/libarchopenfpga/src/read_xml_pb_type_annotation.h index 98934a4b8..08f0c1efc 100644 --- a/libs/libarchopenfpga/src/read_xml_pb_type_annotation.h +++ b/libs/libarchopenfpga/src/read_xml_pb_type_annotation.h @@ -4,14 +4,14 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "pugixml_util.hpp" -#include "pugixml.hpp" #include "pb_type_annotation.h" +#include "pugixml.hpp" +#include "pugixml_util.hpp" /******************************************************************** * Function declaration *******************************************************************/ -std::vector read_xml_pb_type_annotations(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data); +std::vector read_xml_pb_type_annotations( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data); #endif diff --git a/libs/libarchopenfpga/src/read_xml_routing_circuit.cpp b/libs/libarchopenfpga/src/read_xml_routing_circuit.cpp index 5daef1310..1ac6675b8 100644 --- a/libs/libarchopenfpga/src/read_xml_routing_circuit.cpp +++ b/libs/libarchopenfpga/src/read_xml_routing_circuit.cpp @@ -14,28 +14,26 @@ /* Headers from libarchfpga */ #include "arch_error.h" -#include "read_xml_util.h" - #include "read_xml_routing_circuit.h" +#include "read_xml_util.h" /******************************************************************** * Find the circuit model id for a routing switch as defined in XML *******************************************************************/ -static -CircuitModelId find_routing_circuit_model(pugi::xml_node& xml_switch, - const pugiutil::loc_data& loc_data, - const CircuitLibrary& circuit_lib, - const std::string& switch_model_name, - const e_circuit_model_type& expected_circuit_model_type) { +static CircuitModelId find_routing_circuit_model( + pugi::xml_node& xml_switch, const pugiutil::loc_data& loc_data, + const CircuitLibrary& circuit_lib, const std::string& switch_model_name, + const e_circuit_model_type& expected_circuit_model_type) { /* Find the circuit model id in circuit library */ CircuitModelId switch_model = circuit_lib.model(switch_model_name); /* Ensure we have a valid circuit model id! */ if (CircuitModelId::INVALID() == switch_model) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch), - "Invalid circuit model name '%s'! Unable to find it in circuit library\n", - switch_model_name.c_str()); + archfpga_throw( + loc_data.filename_c_str(), loc_data.line(xml_switch), + "Invalid circuit model name '%s'! Unable to find it in circuit library\n", + switch_model_name.c_str()); } - /* Check the type of switch model, it must be a specific type!!! + /* Check the type of switch model, it must be a specific type!!! * For CB/SB switches, the type must be a multiplexer * For routing segments, the type must be a channel wire * TODO: decide where to put these checking codes @@ -44,23 +42,26 @@ CircuitModelId find_routing_circuit_model(pugi::xml_node& xml_switch, if (expected_circuit_model_type != circuit_lib.model_type(switch_model)) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch), "Circuit model '%s' must be a type of '%s'\n", - switch_model_name.c_str(), CIRCUIT_MODEL_TYPE_STRING[expected_circuit_model_type]); + switch_model_name.c_str(), + CIRCUIT_MODEL_TYPE_STRING[expected_circuit_model_type]); } - + return switch_model; } /******************************************************************** - * Parse XML codes about to an object of name-to-circuit mapping - * Note: this function should be called AFTER the parsing of circuit library!!! + * Parse XML codes about to an object of name-to-circuit + *mapping Note: this function should be called AFTER the parsing of circuit + *library!!! *******************************************************************/ -std::map read_xml_cb_switch_circuit(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data, - const CircuitLibrary& circuit_lib) { +std::map read_xml_cb_switch_circuit( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data, + const CircuitLibrary& circuit_lib) { std::map cb_switch2circuit; /* Parse cb switch list */ - pugi::xml_node xml_cb_switch = get_single_child(Node, "connection_block", loc_data); + pugi::xml_node xml_cb_switch = + get_single_child(Node, "connection_block", loc_data); /* Iterate over the children under this node, * each child should be named after switch @@ -70,18 +71,20 @@ std::map read_xml_cb_switch_circuit(pugi::xml_node& if (xml_switch.name() != std::string("switch")) { bad_tag(xml_switch, loc_data, xml_cb_switch, {"switch"}); } - /* Get the switch name */ - std::string switch_name = get_attribute(xml_switch, "name", loc_data).as_string(); + /* Get the switch name */ + std::string switch_name = + get_attribute(xml_switch, "name", loc_data).as_string(); - /* Get the switch circuit model name */ - std::string switch_model_name = get_attribute(xml_switch, "circuit_model_name", loc_data).as_string(); + /* Get the switch circuit model name */ + std::string switch_model_name = + get_attribute(xml_switch, "circuit_model_name", loc_data).as_string(); - CircuitModelId switch_model = find_routing_circuit_model(xml_switch, loc_data, - circuit_lib, switch_model_name, - CIRCUIT_MODEL_MUX); + CircuitModelId switch_model = find_routing_circuit_model( + xml_switch, loc_data, circuit_lib, switch_model_name, CIRCUIT_MODEL_MUX); /* Ensure that there is no duplicated switch names defined here */ - std::map::const_iterator it = cb_switch2circuit.find(switch_name); + std::map::const_iterator it = + cb_switch2circuit.find(switch_name); if (it != cb_switch2circuit.end()) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch), "Switch name '%s' has been defined more than once!\n", @@ -89,8 +92,8 @@ std::map read_xml_cb_switch_circuit(pugi::xml_node& } /* Pass all the check, we can add it to the map */ - cb_switch2circuit[switch_name] = switch_model; - } + cb_switch2circuit[switch_name] = switch_model; + } return cb_switch2circuit; } @@ -99,13 +102,14 @@ std::map read_xml_cb_switch_circuit(pugi::xml_node& * Parse XML codes about to an object of name-to-circuit mapping * Note: this function should be called AFTER the parsing of circuit library!!! *******************************************************************/ -std::map read_xml_sb_switch_circuit(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data, - const CircuitLibrary& circuit_lib) { +std::map read_xml_sb_switch_circuit( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data, + const CircuitLibrary& circuit_lib) { std::map sb_switch2circuit; /* Parse cb switch list */ - pugi::xml_node xml_sb_switch = get_single_child(Node, "switch_block", loc_data); + pugi::xml_node xml_sb_switch = + get_single_child(Node, "switch_block", loc_data); /* Iterate over the children under this node, * each child should be named after switch @@ -115,18 +119,20 @@ std::map read_xml_sb_switch_circuit(pugi::xml_node& if (xml_switch.name() != std::string("switch")) { bad_tag(xml_switch, loc_data, xml_sb_switch, {"switch"}); } - /* Get the switch name */ - std::string switch_name = get_attribute(xml_switch, "name", loc_data).as_string(); + /* Get the switch name */ + std::string switch_name = + get_attribute(xml_switch, "name", loc_data).as_string(); - /* Get the switch circuit model name */ - std::string switch_model_name = get_attribute(xml_switch, "circuit_model_name", loc_data).as_string(); + /* Get the switch circuit model name */ + std::string switch_model_name = + get_attribute(xml_switch, "circuit_model_name", loc_data).as_string(); - CircuitModelId switch_model = find_routing_circuit_model(xml_switch, loc_data, - circuit_lib, switch_model_name, - CIRCUIT_MODEL_MUX); + CircuitModelId switch_model = find_routing_circuit_model( + xml_switch, loc_data, circuit_lib, switch_model_name, CIRCUIT_MODEL_MUX); /* Ensure that there is no duplicated switch names defined here */ - std::map::const_iterator it = sb_switch2circuit.find(switch_name); + std::map::const_iterator it = + sb_switch2circuit.find(switch_name); if (it != sb_switch2circuit.end()) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch), "Switch name '%s' has been defined more than once!\n", @@ -134,23 +140,25 @@ std::map read_xml_sb_switch_circuit(pugi::xml_node& } /* Pass all the check, we can add it to the map */ - sb_switch2circuit[switch_name] = switch_model; - } + sb_switch2circuit[switch_name] = switch_model; + } return sb_switch2circuit; } /******************************************************************** - * Parse XML codes about to an object of name-to-circuit mapping - * Note: this function should be called AFTER the parsing of circuit library!!! + * Parse XML codes about to an object of name-to-circuit + *mapping Note: this function should be called AFTER the parsing of circuit + *library!!! *******************************************************************/ -std::map read_xml_routing_segment_circuit(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data, - const CircuitLibrary& circuit_lib) { +std::map read_xml_routing_segment_circuit( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data, + const CircuitLibrary& circuit_lib) { std::map seg2circuit; /* Parse cb switch list */ - pugi::xml_node xml_segments= get_single_child(Node, "routing_segment", loc_data); + pugi::xml_node xml_segments = + get_single_child(Node, "routing_segment", loc_data); /* Iterate over the children under this node, * each child should be named after switch @@ -160,18 +168,19 @@ std::map read_xml_routing_segment_circuit(pugi::xml if (xml_seg.name() != std::string("segment")) { bad_tag(xml_seg, loc_data, xml_segments, {"segment"}); } - /* Get the switch name */ + /* Get the switch name */ std::string seg_name = get_attribute(xml_seg, "name", loc_data).as_string(); - /* Get the routing segment circuit model name */ - std::string seg_model_name = get_attribute(xml_seg, "circuit_model_name", loc_data).as_string(); + /* Get the routing segment circuit model name */ + std::string seg_model_name = + get_attribute(xml_seg, "circuit_model_name", loc_data).as_string(); + + CircuitModelId seg_model = find_routing_circuit_model( + xml_seg, loc_data, circuit_lib, seg_model_name, CIRCUIT_MODEL_CHAN_WIRE); - CircuitModelId seg_model = find_routing_circuit_model(xml_seg, loc_data, - circuit_lib, seg_model_name, - CIRCUIT_MODEL_CHAN_WIRE); - /* Ensure that there is no duplicated seg names defined here */ - std::map::const_iterator it = seg2circuit.find(seg_name); + std::map::const_iterator it = + seg2circuit.find(seg_name); if (it != seg2circuit.end()) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_seg), "Segment name '%s' has been defined more than once!\n", @@ -179,8 +188,8 @@ std::map read_xml_routing_segment_circuit(pugi::xml } /* Pass all the check, we can add it to the map */ - seg2circuit[seg_name] = seg_model; - } + seg2circuit[seg_name] = seg_model; + } return seg2circuit; } @@ -188,8 +197,7 @@ std::map read_xml_routing_segment_circuit(pugi::xml /******************************************************************** * Convert string to the enumerate of direct type *******************************************************************/ -static -e_direct_type string_to_direct_type(const std::string& type_string) { +static e_direct_type string_to_direct_type(const std::string& type_string) { if (std::string("column") == type_string) { return INTER_COLUMN; } @@ -199,13 +207,13 @@ e_direct_type string_to_direct_type(const std::string& type_string) { } return NUM_DIRECT_TYPES; -} +} /******************************************************************** * Convert string to the enumerate of direct direction type *******************************************************************/ -static -e_direct_direction string_to_direct_direction(const std::string& type_string) { +static e_direct_direction string_to_direct_direction( + const std::string& type_string) { if (std::string("positive") == type_string) { return POSITIVE_DIR; } @@ -215,12 +223,12 @@ e_direct_direction string_to_direct_direction(const std::string& type_string) { } return NUM_DIRECT_DIRECTIONS; -} - +} /******************************************************************** - * Parse XML codes about to an object of name-to-circuit mapping - * Note: this function should be called AFTER the parsing of circuit library!!! + * Parse XML codes about to an object of name-to-circuit + *mapping Note: this function should be called AFTER the parsing of circuit + *library!!! *******************************************************************/ ArchDirect read_xml_direct_circuit(pugi::xml_node& Node, const pugiutil::loc_data& loc_data, @@ -228,7 +236,8 @@ ArchDirect read_xml_direct_circuit(pugi::xml_node& Node, ArchDirect arch_direct; /* Parse direct list, this is optional. May not be used */ - pugi::xml_node xml_directs= get_single_child(Node, "direct_connection", loc_data, pugiutil::ReqOpt::OPTIONAL); + pugi::xml_node xml_directs = get_single_child( + Node, "direct_connection", loc_data, pugiutil::ReqOpt::OPTIONAL); /* Not found, we can return */ if (!xml_directs) { return arch_direct; @@ -242,16 +251,17 @@ ArchDirect read_xml_direct_circuit(pugi::xml_node& Node, if (xml_direct.name() != std::string("direct")) { bad_tag(xml_direct, loc_data, xml_directs, {"direct"}); } - /* Get the switch name */ - std::string direct_name = get_attribute(xml_direct, "name", loc_data).as_string(); + /* Get the switch name */ + std::string direct_name = + get_attribute(xml_direct, "name", loc_data).as_string(); - /* Get the routing segment circuit model name */ - std::string direct_model_name = get_attribute(xml_direct, "circuit_model_name", loc_data).as_string(); + /* Get the routing segment circuit model name */ + std::string direct_model_name = + get_attribute(xml_direct, "circuit_model_name", loc_data).as_string(); + + CircuitModelId direct_model = find_routing_circuit_model( + xml_direct, loc_data, circuit_lib, direct_model_name, CIRCUIT_MODEL_WIRE); - CircuitModelId direct_model = find_routing_circuit_model(xml_direct, loc_data, - circuit_lib, direct_model_name, - CIRCUIT_MODEL_WIRE); - /* Add to the Arch direct database */ ArchDirectId direct = arch_direct.add_direct(direct_name); if (false == arch_direct.valid_direct_id(direct)) { @@ -262,7 +272,9 @@ ArchDirect read_xml_direct_circuit(pugi::xml_node& Node, arch_direct.set_circuit_model(direct, direct_model); /* Add more information*/ - std::string direct_type_name = get_attribute(xml_direct, "type", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string("none"); + std::string direct_type_name = + get_attribute(xml_direct, "type", loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_string("none"); /* If not defined, we go to the next */ if (std::string("none") == direct_type_name) { continue; @@ -271,32 +283,37 @@ ArchDirect read_xml_direct_circuit(pugi::xml_node& Node, e_direct_type direct_type = string_to_direct_type(direct_type_name); if (NUM_DIRECT_TYPES == direct_type) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_direct), - "Direct type '%s' is not support! Acceptable values are [column|row]\n", - direct_type_name.c_str()); + archfpga_throw( + loc_data.filename_c_str(), loc_data.line(xml_direct), + "Direct type '%s' is not support! Acceptable values are [column|row]\n", + direct_type_name.c_str()); } arch_direct.set_type(direct, direct_type); - std::string x_dir_name = get_attribute(xml_direct, "x_dir", loc_data).as_string(); - std::string y_dir_name = get_attribute(xml_direct, "y_dir", loc_data).as_string(); + std::string x_dir_name = + get_attribute(xml_direct, "x_dir", loc_data).as_string(); + std::string y_dir_name = + get_attribute(xml_direct, "y_dir", loc_data).as_string(); e_direct_direction x_dir = string_to_direct_direction(x_dir_name); e_direct_direction y_dir = string_to_direct_direction(y_dir_name); if (NUM_DIRECT_DIRECTIONS == x_dir) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_direct), - "Direct x-direction '%s' is not support! Acceptable values are [positive|column]\n", + "Direct x-direction '%s' is not support! Acceptable " + "values are [positive|column]\n", x_dir_name.c_str()); } if (NUM_DIRECT_DIRECTIONS == y_dir) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_direct), - "Direct y-direction '%s' is not support! Acceptable values are [positive|column]\n", + "Direct y-direction '%s' is not support! Acceptable " + "values are [positive|column]\n", y_dir_name.c_str()); } arch_direct.set_direction(direct, x_dir, y_dir); - } + } return arch_direct; } diff --git a/libs/libarchopenfpga/src/read_xml_routing_circuit.h b/libs/libarchopenfpga/src/read_xml_routing_circuit.h index 28d14710d..67a2b4663 100644 --- a/libs/libarchopenfpga/src/read_xml_routing_circuit.h +++ b/libs/libarchopenfpga/src/read_xml_routing_circuit.h @@ -4,32 +4,31 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include #include +#include -#include "pugixml_util.hpp" -#include "pugixml.hpp" -#include "circuit_library.h" #include "arch_direct.h" +#include "circuit_library.h" +#include "pugixml.hpp" +#include "pugixml_util.hpp" /******************************************************************** * Function declaration *******************************************************************/ -std::map read_xml_cb_switch_circuit(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data, - const CircuitLibrary& circuit_lib); +std::map read_xml_cb_switch_circuit( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data, + const CircuitLibrary& circuit_lib); -std::map read_xml_sb_switch_circuit(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data, - const CircuitLibrary& circuit_lib); +std::map read_xml_sb_switch_circuit( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data, + const CircuitLibrary& circuit_lib); -std::map read_xml_routing_segment_circuit(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data, - const CircuitLibrary& circuit_lib); +std::map read_xml_routing_segment_circuit( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data, + const CircuitLibrary& circuit_lib); ArchDirect read_xml_direct_circuit(pugi::xml_node& Node, const pugiutil::loc_data& loc_data, const CircuitLibrary& circuit_lib); - #endif diff --git a/libs/libarchopenfpga/src/read_xml_simulation_setting.cpp b/libs/libarchopenfpga/src/read_xml_simulation_setting.cpp index a76f2f2ff..114549bc7 100644 --- a/libs/libarchopenfpga/src/read_xml_simulation_setting.cpp +++ b/libs/libarchopenfpga/src/read_xml_simulation_setting.cpp @@ -17,15 +17,14 @@ /* Headers from libarchfpga */ #include "arch_error.h" -#include "read_xml_util.h" - #include "read_xml_simulation_setting.h" +#include "read_xml_util.h" /******************************************************************** * Convert string to the enumerate of simulation accuracy type *******************************************************************/ -static -e_sim_accuracy_type string_to_sim_accuracy_type(const std::string& type_string) { +static e_sim_accuracy_type string_to_sim_accuracy_type( + const std::string& type_string) { for (size_t itype = 0; itype < NUM_SIM_ACCURACY_TYPES; ++itype) { if (std::string(SIM_ACCURACY_TYPE_STRING[itype]) == type_string) { return static_cast(itype); @@ -36,92 +35,123 @@ e_sim_accuracy_type string_to_sim_accuracy_type(const std::string& type_string) } /******************************************************************** - * Parse XML codes of a line under to an object of simulation setting + * Parse XML codes of a line under to an object of + *simulation setting *******************************************************************/ -static -void read_xml_operating_clock_override_setting(pugi::xml_node& xml_clock_override_setting, - const pugiutil::loc_data& loc_data, - openfpga::SimulationSetting& sim_setting) { - std::string clock_name = get_attribute(xml_clock_override_setting, "name", loc_data).as_string(); +static void read_xml_operating_clock_override_setting( + pugi::xml_node& xml_clock_override_setting, + const pugiutil::loc_data& loc_data, + openfpga::SimulationSetting& sim_setting) { + std::string clock_name = + get_attribute(xml_clock_override_setting, "name", loc_data).as_string(); - /* Create a new clock override object in the sim_setting object with the given name */ + /* Create a new clock override object in the sim_setting object with the given + * name */ SimulationClockId clock_id = sim_setting.create_clock(clock_name); - + /* Report if the clock creation failed, this is due to a conflicts in naming*/ if (false == sim_setting.valid_clock_id(clock_id)) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_clock_override_setting), - "Fail to create simulation clock '%s', it may share the same name as other simulation clock definition!\n", + archfpga_throw(loc_data.filename_c_str(), + loc_data.line(xml_clock_override_setting), + "Fail to create simulation clock '%s', it may share the " + "same name as other simulation clock definition!\n", clock_name.c_str()); } /* Parse port information */ - openfpga::PortParser clock_port_parser(get_attribute(xml_clock_override_setting, "port", loc_data).as_string()); + openfpga::PortParser clock_port_parser( + get_attribute(xml_clock_override_setting, "port", loc_data).as_string()); sim_setting.set_clock_port(clock_id, clock_port_parser.port()); /* Parse frequency information */ - sim_setting.set_clock_frequency(clock_id, get_attribute(xml_clock_override_setting, "frequency", loc_data).as_float(0.)); + sim_setting.set_clock_frequency( + clock_id, get_attribute(xml_clock_override_setting, "frequency", loc_data) + .as_float(0.)); } /******************************************************************** - * Parse XML codes of a line under to an object of simulation setting + * Parse XML codes of a line under to an object of + *simulation setting *******************************************************************/ -static -void read_xml_programming_clock_override_setting(pugi::xml_node& xml_clock_override_setting, - const pugiutil::loc_data& loc_data, - openfpga::SimulationSetting& sim_setting) { - std::string clock_name = get_attribute(xml_clock_override_setting, "name", loc_data).as_string(); +static void read_xml_programming_clock_override_setting( + pugi::xml_node& xml_clock_override_setting, + const pugiutil::loc_data& loc_data, + openfpga::SimulationSetting& sim_setting) { + std::string clock_name = + get_attribute(xml_clock_override_setting, "name", loc_data).as_string(); - /* Create a new clock override object in the sim_setting object with the given name */ + /* Create a new clock override object in the sim_setting object with the given + * name */ SimulationClockId clock_id = sim_setting.create_clock(clock_name); - + /* Report if the clock creation failed, this is due to a conflicts in naming*/ if (false == sim_setting.valid_clock_id(clock_id)) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_clock_override_setting), - "Fail to create simulation clock '%s', it may share the same name as other simulation clock definition!\n", + archfpga_throw(loc_data.filename_c_str(), + loc_data.line(xml_clock_override_setting), + "Fail to create simulation clock '%s', it may share the " + "same name as other simulation clock definition!\n", clock_name.c_str()); } /* Parse port information */ - openfpga::PortParser clock_port_parser(get_attribute(xml_clock_override_setting, "port", loc_data).as_string()); + openfpga::PortParser clock_port_parser( + get_attribute(xml_clock_override_setting, "port", loc_data).as_string()); sim_setting.set_clock_port(clock_id, clock_port_parser.port()); /* Parse frequency information */ - std::string clock_freq_str = get_attribute(xml_clock_override_setting, "frequency", loc_data).as_string(); + std::string clock_freq_str = + get_attribute(xml_clock_override_setting, "frequency", loc_data) + .as_string(); if (std::string("auto") != clock_freq_str) { - sim_setting.set_clock_frequency(clock_id, get_attribute(xml_clock_override_setting, "frequency", loc_data).as_float(0.)); + sim_setting.set_clock_frequency( + clock_id, get_attribute(xml_clock_override_setting, "frequency", loc_data) + .as_float(0.)); } sim_setting.set_clock_is_programming(clock_id, true); - sim_setting.set_clock_is_shift_register(clock_id, get_attribute(xml_clock_override_setting, "is_shift_register", loc_data).as_bool(false)); + sim_setting.set_clock_is_shift_register( + clock_id, + get_attribute(xml_clock_override_setting, "is_shift_register", loc_data) + .as_bool(false)); } /******************************************************************** * Parse XML codes of a to an object of simulation setting *******************************************************************/ -static -void read_xml_clock_setting(pugi::xml_node& xml_clock_setting, - const pugiutil::loc_data& loc_data, - openfpga::SimulationSetting& sim_setting) { +static void read_xml_clock_setting(pugi::xml_node& xml_clock_setting, + const pugiutil::loc_data& loc_data, + openfpga::SimulationSetting& sim_setting) { /* Parse operating clock setting */ - pugi::xml_node xml_operating_clock_setting = get_single_child(xml_clock_setting, "operating", loc_data); + pugi::xml_node xml_operating_clock_setting = + get_single_child(xml_clock_setting, "operating", loc_data); - sim_setting.set_default_operating_clock_frequency(get_attribute(xml_operating_clock_setting, "frequency", loc_data).as_float(0.)); + sim_setting.set_default_operating_clock_frequency( + get_attribute(xml_operating_clock_setting, "frequency", loc_data) + .as_float(0.)); /* Parse number of clock cycles to be used in simulation * Valid keywords is "auto" or other integer larger than 0 */ - std::string num_cycles_str = get_attribute(xml_operating_clock_setting, "num_cycles", loc_data).as_string(); + std::string num_cycles_str = + get_attribute(xml_operating_clock_setting, "num_cycles", loc_data) + .as_string(); if (std::string("auto") == num_cycles_str) { sim_setting.set_num_clock_cycles(0); - } else if (0 < get_attribute(xml_operating_clock_setting, "num_cycles", loc_data).as_int(0.)) { - sim_setting.set_num_clock_cycles(get_attribute(xml_operating_clock_setting, "num_cycles", loc_data).as_int(0)); + } else if (0 < + get_attribute(xml_operating_clock_setting, "num_cycles", loc_data) + .as_int(0.)) { + sim_setting.set_num_clock_cycles( + get_attribute(xml_operating_clock_setting, "num_cycles", loc_data) + .as_int(0)); } else { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_operating_clock_setting), + archfpga_throw(loc_data.filename_c_str(), + loc_data.line(xml_operating_clock_setting), "Invalid defined under "); } - sim_setting.set_operating_clock_frequency_slack(get_attribute(xml_operating_clock_setting, "slack", loc_data).as_float(0.)); + sim_setting.set_operating_clock_frequency_slack( + get_attribute(xml_operating_clock_setting, "slack", loc_data).as_float(0.)); /* Iterate over multiple operating clock settings and parse one by one */ for (pugi::xml_node xml_clock : xml_operating_clock_setting.children()) { @@ -130,12 +160,15 @@ void read_xml_clock_setting(pugi::xml_node& xml_clock_setting, bad_tag(xml_clock, loc_data, xml_operating_clock_setting, {"clock"}); } read_xml_operating_clock_override_setting(xml_clock, loc_data, sim_setting); - } + } /* Parse programming clock setting */ - pugi::xml_node xml_programming_clock_setting = get_single_child(xml_clock_setting, "programming", loc_data); + pugi::xml_node xml_programming_clock_setting = + get_single_child(xml_clock_setting, "programming", loc_data); - sim_setting.set_programming_clock_frequency(get_attribute(xml_programming_clock_setting, "frequency", loc_data).as_float(0.)); + sim_setting.set_programming_clock_frequency( + get_attribute(xml_programming_clock_setting, "frequency", loc_data) + .as_float(0.)); /* Iterate over multiple operating clock settings and parse one by one */ for (pugi::xml_node xml_clock : xml_programming_clock_setting.children()) { @@ -143,153 +176,191 @@ void read_xml_clock_setting(pugi::xml_node& xml_clock_setting, if (xml_clock.name() != std::string("clock")) { bad_tag(xml_clock, loc_data, xml_programming_clock_setting, {"clock"}); } - read_xml_programming_clock_override_setting(xml_clock, loc_data, sim_setting); - } + read_xml_programming_clock_override_setting(xml_clock, loc_data, + sim_setting); + } } /******************************************************************** * Parse XML codes of a to an object of simulation setting *******************************************************************/ -static -void read_xml_simulator_option(pugi::xml_node& xml_sim_option, - const pugiutil::loc_data& loc_data, - openfpga::SimulationSetting& sim_setting) { +static void read_xml_simulator_option( + pugi::xml_node& xml_sim_option, const pugiutil::loc_data& loc_data, + openfpga::SimulationSetting& sim_setting) { + pugi::xml_node xml_operating_condition = + get_single_child(xml_sim_option, "operating_condition", loc_data); + sim_setting.set_simulation_temperature( + get_attribute(xml_operating_condition, "temperature", loc_data) + .as_float(0.)); - pugi::xml_node xml_operating_condition = get_single_child(xml_sim_option, "operating_condition", loc_data); - sim_setting.set_simulation_temperature(get_attribute(xml_operating_condition, "temperature", loc_data).as_float(0.)); + pugi::xml_node xml_output_log = + get_single_child(xml_sim_option, "output_log", loc_data); + sim_setting.set_verbose_output( + get_attribute(xml_output_log, "verbose", loc_data).as_bool(false)); + sim_setting.set_capacitance_output( + get_attribute(xml_output_log, "captab", loc_data).as_bool(false)); - pugi::xml_node xml_output_log = get_single_child(xml_sim_option, "output_log", loc_data); - sim_setting.set_verbose_output(get_attribute(xml_output_log, "verbose", loc_data).as_bool(false)); - sim_setting.set_capacitance_output(get_attribute(xml_output_log, "captab", loc_data).as_bool(false)); - - pugi::xml_node xml_accuracy = get_single_child(xml_sim_option, "accuracy", loc_data); + pugi::xml_node xml_accuracy = + get_single_child(xml_sim_option, "accuracy", loc_data); /* Find the type of accuracy */ const char* type_attr = get_attribute(xml_accuracy, "type", loc_data).value(); /* Translate the type of design technology to enumerate */ - e_sim_accuracy_type accuracy_type = string_to_sim_accuracy_type(std::string(type_attr)); + e_sim_accuracy_type accuracy_type = + string_to_sim_accuracy_type(std::string(type_attr)); if (NUM_SIM_ACCURACY_TYPES == accuracy_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_accuracy), - "Invalid 'type' attribute '%s'\n", - type_attr); + "Invalid 'type' attribute '%s'\n", type_attr); } sim_setting.set_simulation_accuracy_type(accuracy_type); - sim_setting.set_simulation_accuracy(get_attribute(xml_accuracy, "value", loc_data).as_float(0.)); + sim_setting.set_simulation_accuracy( + get_attribute(xml_accuracy, "value", loc_data).as_float(0.)); /* Validate the accuracy value */ if (SIM_ACCURACY_FRAC == sim_setting.simulation_accuracy_type()) { - if (false == sim_setting.valid_signal_threshold(sim_setting.simulation_accuracy())) { + if (false == + sim_setting.valid_signal_threshold(sim_setting.simulation_accuracy())) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_accuracy), - "Invalid 'value' attribute '%f', which should be in the range of (0,1)\n", + "Invalid 'value' attribute '%f', which should be in the " + "range of (0,1)\n", sim_setting.simulation_accuracy()); } } - pugi::xml_node xml_runtime = get_single_child(xml_sim_option, "runtime", loc_data); - sim_setting.set_fast_simulation(get_attribute(xml_runtime, "fast_simulation", loc_data).as_bool(false)); + pugi::xml_node xml_runtime = + get_single_child(xml_sim_option, "runtime", loc_data); + sim_setting.set_fast_simulation( + get_attribute(xml_runtime, "fast_simulation", loc_data).as_bool(false)); } - /******************************************************************** * Parse XML codes of a to an object of simulation setting *******************************************************************/ -static -void read_xml_monte_carlo(pugi::xml_node& xml_mc, - const pugiutil::loc_data& loc_data, - openfpga::SimulationSetting& sim_setting) { - sim_setting.set_monte_carlo_simulation_points(get_attribute(xml_mc, "num_simulation_points", loc_data).as_int(0)); +static void read_xml_monte_carlo(pugi::xml_node& xml_mc, + const pugiutil::loc_data& loc_data, + openfpga::SimulationSetting& sim_setting) { + sim_setting.set_monte_carlo_simulation_points( + get_attribute(xml_mc, "num_simulation_points", loc_data).as_int(0)); } /******************************************************************** * Parse XML codes of a to an object of simulation setting *******************************************************************/ -static -void read_xml_measurement_setting(pugi::xml_node& xml_measurement, - const pugiutil::loc_data& loc_data, - openfpga::SimulationSetting& sim_setting) { +static void read_xml_measurement_setting( + pugi::xml_node& xml_measurement, const pugiutil::loc_data& loc_data, + openfpga::SimulationSetting& sim_setting) { pugi::xml_node xml_slew = get_single_child(xml_measurement, "slew", loc_data); pugi::xml_node xml_slew_rise = get_single_child(xml_slew, "rise", loc_data); - sim_setting.set_measure_slew_upper_threshold(SIM_SIGNAL_RISE, get_attribute(xml_slew_rise, "upper_thres_pct", loc_data).as_float(0.)); - sim_setting.set_measure_slew_lower_threshold(SIM_SIGNAL_RISE, get_attribute(xml_slew_rise, "lower_thres_pct", loc_data).as_float(0.)); + sim_setting.set_measure_slew_upper_threshold( + SIM_SIGNAL_RISE, + get_attribute(xml_slew_rise, "upper_thres_pct", loc_data).as_float(0.)); + sim_setting.set_measure_slew_lower_threshold( + SIM_SIGNAL_RISE, + get_attribute(xml_slew_rise, "lower_thres_pct", loc_data).as_float(0.)); pugi::xml_node xml_slew_fall = get_single_child(xml_slew, "fall", loc_data); - sim_setting.set_measure_slew_upper_threshold(SIM_SIGNAL_FALL, get_attribute(xml_slew_fall, "upper_thres_pct", loc_data).as_float(0.)); - sim_setting.set_measure_slew_lower_threshold(SIM_SIGNAL_FALL, get_attribute(xml_slew_fall, "lower_thres_pct", loc_data).as_float(0.)); + sim_setting.set_measure_slew_upper_threshold( + SIM_SIGNAL_FALL, + get_attribute(xml_slew_fall, "upper_thres_pct", loc_data).as_float(0.)); + sim_setting.set_measure_slew_lower_threshold( + SIM_SIGNAL_FALL, + get_attribute(xml_slew_fall, "lower_thres_pct", loc_data).as_float(0.)); - pugi::xml_node xml_delay = get_single_child(xml_measurement, "delay", loc_data); + pugi::xml_node xml_delay = + get_single_child(xml_measurement, "delay", loc_data); pugi::xml_node xml_delay_rise = get_single_child(xml_delay, "rise", loc_data); - sim_setting.set_measure_delay_input_threshold(SIM_SIGNAL_RISE, get_attribute(xml_delay_rise, "input_thres_pct", loc_data).as_float(0.)); - sim_setting.set_measure_delay_output_threshold(SIM_SIGNAL_RISE, get_attribute(xml_delay_rise, "output_thres_pct", loc_data).as_float(0.)); + sim_setting.set_measure_delay_input_threshold( + SIM_SIGNAL_RISE, + get_attribute(xml_delay_rise, "input_thres_pct", loc_data).as_float(0.)); + sim_setting.set_measure_delay_output_threshold( + SIM_SIGNAL_RISE, + get_attribute(xml_delay_rise, "output_thres_pct", loc_data).as_float(0.)); pugi::xml_node xml_delay_fall = get_single_child(xml_delay, "fall", loc_data); - sim_setting.set_measure_delay_input_threshold(SIM_SIGNAL_FALL, get_attribute(xml_delay_fall, "input_thres_pct", loc_data).as_float(0.)); - sim_setting.set_measure_delay_output_threshold(SIM_SIGNAL_FALL, get_attribute(xml_delay_fall, "output_thres_pct", loc_data).as_float(0.)); + sim_setting.set_measure_delay_input_threshold( + SIM_SIGNAL_FALL, + get_attribute(xml_delay_fall, "input_thres_pct", loc_data).as_float(0.)); + sim_setting.set_measure_delay_output_threshold( + SIM_SIGNAL_FALL, + get_attribute(xml_delay_fall, "output_thres_pct", loc_data).as_float(0.)); } /******************************************************************** - * Parse XML codes of a inside to an object of simulation setting + * Parse XML codes of a inside to an object of simulation + *setting *******************************************************************/ -static -void read_xml_stimulus_clock(pugi::xml_node& xml_stimuli_clock, - const pugiutil::loc_data& loc_data, - openfpga::SimulationSetting& sim_setting, - const e_sim_signal_type& signal_type) { +static void read_xml_stimulus_clock(pugi::xml_node& xml_stimuli_clock, + const pugiutil::loc_data& loc_data, + openfpga::SimulationSetting& sim_setting, + const e_sim_signal_type& signal_type) { /* Find the type of accuracy */ - const char* type_attr = get_attribute(xml_stimuli_clock, "slew_type", loc_data).value(); + const char* type_attr = + get_attribute(xml_stimuli_clock, "slew_type", loc_data).value(); /* Translate the type of design technology to enumerate */ - e_sim_accuracy_type accuracy_type = string_to_sim_accuracy_type(std::string(type_attr)); + e_sim_accuracy_type accuracy_type = + string_to_sim_accuracy_type(std::string(type_attr)); if (NUM_SIM_ACCURACY_TYPES == accuracy_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_stimuli_clock), - "Invalid 'type' attribute '%s'\n", - type_attr); + "Invalid 'type' attribute '%s'\n", type_attr); } sim_setting.set_stimuli_clock_slew_type(signal_type, accuracy_type); - sim_setting.set_stimuli_clock_slew(signal_type, get_attribute(xml_stimuli_clock, "slew_time", loc_data).as_float(0.)); + sim_setting.set_stimuli_clock_slew( + signal_type, + get_attribute(xml_stimuli_clock, "slew_time", loc_data).as_float(0.)); /* Validate the accuracy value */ if (SIM_ACCURACY_FRAC == sim_setting.stimuli_clock_slew_type(signal_type)) { - if (false == sim_setting.valid_signal_threshold(sim_setting.stimuli_clock_slew(signal_type))) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_stimuli_clock), - "Invalid 'value' attribute '%f', which should be in the range of (0,1)\n", + if (false == sim_setting.valid_signal_threshold( + sim_setting.stimuli_clock_slew(signal_type))) { + archfpga_throw(loc_data.filename_c_str(), + loc_data.line(xml_stimuli_clock), + "Invalid 'value' attribute '%f', which should be in the " + "range of (0,1)\n", sim_setting.stimuli_clock_slew(signal_type)); } } } /******************************************************************** - * Parse XML codes of a inside to an object of simulation setting + * Parse XML codes of a inside to an object of simulation + *setting *******************************************************************/ -static -void read_xml_stimulus_input(pugi::xml_node& xml_stimuli_input, - const pugiutil::loc_data& loc_data, - openfpga::SimulationSetting& sim_setting, - const e_sim_signal_type& signal_type) { +static void read_xml_stimulus_input(pugi::xml_node& xml_stimuli_input, + const pugiutil::loc_data& loc_data, + openfpga::SimulationSetting& sim_setting, + const e_sim_signal_type& signal_type) { /* Find the type of accuracy */ - const char* type_attr = get_attribute(xml_stimuli_input, "slew_type", loc_data).value(); + const char* type_attr = + get_attribute(xml_stimuli_input, "slew_type", loc_data).value(); /* Translate the type of design technology to enumerate */ - e_sim_accuracy_type accuracy_type = string_to_sim_accuracy_type(std::string(type_attr)); + e_sim_accuracy_type accuracy_type = + string_to_sim_accuracy_type(std::string(type_attr)); if (NUM_SIM_ACCURACY_TYPES == accuracy_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_stimuli_input), - "Invalid 'type' attribute '%s'\n", - type_attr); + "Invalid 'type' attribute '%s'\n", type_attr); } sim_setting.set_stimuli_input_slew_type(signal_type, accuracy_type); - sim_setting.set_stimuli_input_slew(signal_type, get_attribute(xml_stimuli_input, "slew_time", loc_data).as_float(0.)); + sim_setting.set_stimuli_input_slew( + signal_type, + get_attribute(xml_stimuli_input, "slew_time", loc_data).as_float(0.)); /* Validate the accuracy value */ if (SIM_ACCURACY_FRAC == sim_setting.stimuli_input_slew_type(signal_type)) { - if (false == sim_setting.valid_signal_threshold(sim_setting.stimuli_input_slew(signal_type))) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_stimuli_input), - "Invalid 'value' attribute '%f', which should be in the range of (0,1)\n", + if (false == sim_setting.valid_signal_threshold( + sim_setting.stimuli_input_slew(signal_type))) { + archfpga_throw(loc_data.filename_c_str(), + loc_data.line(xml_stimuli_input), + "Invalid 'value' attribute '%f', which should be in the " + "range of (0,1)\n", sim_setting.stimuli_input_slew(signal_type)); } } @@ -298,48 +369,56 @@ void read_xml_stimulus_input(pugi::xml_node& xml_stimuli_input, /******************************************************************** * Parse XML codes of a to an object of simulation setting *******************************************************************/ -static -void read_xml_stimulus(pugi::xml_node& xml_stimulus, - const pugiutil::loc_data& loc_data, - openfpga::SimulationSetting& sim_setting) { +static void read_xml_stimulus(pugi::xml_node& xml_stimulus, + const pugiutil::loc_data& loc_data, + openfpga::SimulationSetting& sim_setting) { pugi::xml_node xml_clock = get_single_child(xml_stimulus, "clock", loc_data); pugi::xml_node xml_clock_rise = get_single_child(xml_clock, "rise", loc_data); - read_xml_stimulus_clock(xml_clock_rise, loc_data, sim_setting, SIM_SIGNAL_RISE); + read_xml_stimulus_clock(xml_clock_rise, loc_data, sim_setting, + SIM_SIGNAL_RISE); pugi::xml_node xml_clock_fall = get_single_child(xml_clock, "fall", loc_data); - read_xml_stimulus_clock(xml_clock_fall, loc_data, sim_setting, SIM_SIGNAL_FALL); + read_xml_stimulus_clock(xml_clock_fall, loc_data, sim_setting, + SIM_SIGNAL_FALL); pugi::xml_node xml_input = get_single_child(xml_stimulus, "input", loc_data); pugi::xml_node xml_input_rise = get_single_child(xml_input, "rise", loc_data); - read_xml_stimulus_input(xml_input_rise, loc_data, sim_setting, SIM_SIGNAL_RISE); + read_xml_stimulus_input(xml_input_rise, loc_data, sim_setting, + SIM_SIGNAL_RISE); pugi::xml_node xml_input_fall = get_single_child(xml_input, "fall", loc_data); - read_xml_stimulus_input(xml_input_fall, loc_data, sim_setting, SIM_SIGNAL_FALL); + read_xml_stimulus_input(xml_input_fall, loc_data, sim_setting, + SIM_SIGNAL_FALL); } /******************************************************************** - * Parse XML codes about to an object of technology library + * Parse XML codes about to an object of + *technology library *******************************************************************/ -openfpga::SimulationSetting read_xml_simulation_setting(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data) { +openfpga::SimulationSetting read_xml_simulation_setting( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data) { openfpga::SimulationSetting sim_setting; /* Parse clock settings */ - pugi::xml_node xml_clock_setting = get_single_child(Node, "clock_setting", loc_data); + pugi::xml_node xml_clock_setting = + get_single_child(Node, "clock_setting", loc_data); read_xml_clock_setting(xml_clock_setting, loc_data, sim_setting); /* Parse simulator options */ - pugi::xml_node xml_simulator_option = get_single_child(Node, "simulator_option", loc_data); + pugi::xml_node xml_simulator_option = + get_single_child(Node, "simulator_option", loc_data); read_xml_simulator_option(xml_simulator_option, loc_data, sim_setting); /* Parse Monte carlo simulation options */ - pugi::xml_node xml_mc = get_single_child(Node, "monte_carlo", loc_data, pugiutil::ReqOpt::OPTIONAL); + pugi::xml_node xml_mc = + get_single_child(Node, "monte_carlo", loc_data, pugiutil::ReqOpt::OPTIONAL); if (xml_mc) { read_xml_monte_carlo(xml_mc, loc_data, sim_setting); } /* Parse measurement settings */ - pugi::xml_node xml_measurement = get_single_child(Node, "measurement_setting", loc_data); + pugi::xml_node xml_measurement = + get_single_child(Node, "measurement_setting", loc_data); read_xml_measurement_setting(xml_measurement, loc_data, sim_setting); /* Parse stimulus settings */ diff --git a/libs/libarchopenfpga/src/read_xml_simulation_setting.h b/libs/libarchopenfpga/src/read_xml_simulation_setting.h index df6f2856c..fdc831b4f 100644 --- a/libs/libarchopenfpga/src/read_xml_simulation_setting.h +++ b/libs/libarchopenfpga/src/read_xml_simulation_setting.h @@ -4,15 +4,15 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "pugixml_util.hpp" #include "pugixml.hpp" +#include "pugixml_util.hpp" #include "simulation_setting.h" /******************************************************************** * Function declaration *******************************************************************/ -openfpga::SimulationSetting read_xml_simulation_setting(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data); +openfpga::SimulationSetting read_xml_simulation_setting( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data); #endif diff --git a/libs/libarchopenfpga/src/read_xml_technology_library.cpp b/libs/libarchopenfpga/src/read_xml_technology_library.cpp index 9c5c2b132..e36f1afdf 100644 --- a/libs/libarchopenfpga/src/read_xml_technology_library.cpp +++ b/libs/libarchopenfpga/src/read_xml_technology_library.cpp @@ -14,15 +14,14 @@ /* Headers from libarchfpga */ #include "arch_error.h" -#include "read_xml_util.h" - #include "read_xml_technology_library.h" +#include "read_xml_util.h" /******************************************************************** * Convert string to the enumerate of device model type *******************************************************************/ -static -e_tech_lib_model_type string_to_device_model_type(const std::string& type_string) { +static e_tech_lib_model_type string_to_device_model_type( + const std::string& type_string) { for (size_t itype = 0; itype < NUM_TECH_LIB_MODEL_TYPES; ++itype) { if (std::string(TECH_LIB_MODEL_TYPE_STRING[itype]) == type_string) { return static_cast(itype); @@ -35,8 +34,7 @@ e_tech_lib_model_type string_to_device_model_type(const std::string& type_string /******************************************************************** * Convert string to the enumerate of technology library type *******************************************************************/ -static -e_tech_lib_type string_to_tech_lib_type(const std::string& type_string) { +static e_tech_lib_type string_to_tech_lib_type(const std::string& type_string) { for (size_t itype = 0; itype < NUM_TECH_LIB_TYPES; ++itype) { if (std::string(TECH_LIB_TYPE_STRING[itype]) == type_string) { return static_cast(itype); @@ -47,152 +45,187 @@ e_tech_lib_type string_to_tech_lib_type(const std::string& type_string) { } /******************************************************************** - * Parse XML codes of a under a device model definiton + * Parse XML codes of a under a device model definiton * to an object of technology library *******************************************************************/ -static -void read_xml_device_model_lib_settings(pugi::xml_node& xml_device_model_lib, - const pugiutil::loc_data& loc_data, - TechnologyLibrary& tech_lib, - TechnologyModelId& device_model) { +static void read_xml_device_model_lib_settings( + pugi::xml_node& xml_device_model_lib, const pugiutil::loc_data& loc_data, + TechnologyLibrary& tech_lib, TechnologyModelId& device_model) { /* Parse the type of model library */ - const char* type_attr = get_attribute(xml_device_model_lib, "type", loc_data).value(); + const char* type_attr = + get_attribute(xml_device_model_lib, "type", loc_data).value(); /* Translate the type of design technology to enumerate */ - e_tech_lib_type device_model_lib_type = string_to_tech_lib_type(std::string(type_attr)); + e_tech_lib_type device_model_lib_type = + string_to_tech_lib_type(std::string(type_attr)); if (NUM_TECH_LIB_TYPES == device_model_lib_type) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_device_model_lib), - "Invalid 'type' attribute '%s'\n", - type_attr); + archfpga_throw(loc_data.filename_c_str(), + loc_data.line(xml_device_model_lib), + "Invalid 'type' attribute '%s'\n", type_attr); } tech_lib.set_model_lib_type(device_model, device_model_lib_type); - /* Parse the type of process corner, this is ONLY applicable to industry library */ + /* Parse the type of process corner, this is ONLY applicable to industry + * library */ if (TECH_LIB_INDUSTRY == tech_lib.model_lib_type(device_model)) { - tech_lib.set_model_corner(device_model, get_attribute(xml_device_model_lib, "corner", loc_data).as_string()); + tech_lib.set_model_corner( + device_model, + get_attribute(xml_device_model_lib, "corner", loc_data).as_string()); } /* Parse the model reference */ - tech_lib.set_model_ref(device_model, get_attribute(xml_device_model_lib, "ref", loc_data).as_string()); + tech_lib.set_model_ref( + device_model, + get_attribute(xml_device_model_lib, "ref", loc_data).as_string()); /* Parse the lib path */ - tech_lib.set_model_lib_path(device_model, get_attribute(xml_device_model_lib, "path", loc_data).as_string()); + tech_lib.set_model_lib_path( + device_model, + get_attribute(xml_device_model_lib, "path", loc_data).as_string()); } /******************************************************************** * Parse XML codes of design parameters under a device model * to an object of technology library *******************************************************************/ -static -void read_xml_device_model_design_settings(pugi::xml_node& xml_device_model_design, - const pugiutil::loc_data& loc_data, - TechnologyLibrary& tech_lib, - TechnologyModelId& device_model) { +static void read_xml_device_model_design_settings( + pugi::xml_node& xml_device_model_design, const pugiutil::loc_data& loc_data, + TechnologyLibrary& tech_lib, TechnologyModelId& device_model) { /* Parse the vdd to be used in circuit design */ - tech_lib.set_model_vdd(device_model, get_attribute(xml_device_model_design, "vdd", loc_data).as_float(0.)); + tech_lib.set_model_vdd( + device_model, + get_attribute(xml_device_model_design, "vdd", loc_data).as_float(0.)); /* Parse the width ratio between PMOS and NMOS transistor */ - tech_lib.set_model_pn_ratio(device_model, get_attribute(xml_device_model_design, "pn_ratio", loc_data).as_float(0.)); + tech_lib.set_model_pn_ratio( + device_model, + get_attribute(xml_device_model_design, "pn_ratio", loc_data).as_float(0.)); } /******************************************************************** * Parse XML codes of transistor models under a device model * to an object of technology library *******************************************************************/ -static -void read_xml_device_transistor(pugi::xml_node& xml_device_transistor, - const pugiutil::loc_data& loc_data, - TechnologyLibrary& tech_lib, - TechnologyModelId& device_model, - const e_tech_lib_transistor_type& transistor_type) { +static void read_xml_device_transistor( + pugi::xml_node& xml_device_transistor, const pugiutil::loc_data& loc_data, + TechnologyLibrary& tech_lib, TechnologyModelId& device_model, + const e_tech_lib_transistor_type& transistor_type) { /* Parse the transistor model name */ - tech_lib.set_transistor_model_name(device_model, transistor_type, - get_attribute(xml_device_transistor, "name", loc_data).as_string()); + tech_lib.set_transistor_model_name( + device_model, transistor_type, + get_attribute(xml_device_transistor, "name", loc_data).as_string()); /* Parse the transistor channel length */ - tech_lib.set_transistor_model_chan_length(device_model, transistor_type, - get_attribute(xml_device_transistor, "chan_length", loc_data).as_float(0.)); + tech_lib.set_transistor_model_chan_length( + device_model, transistor_type, + get_attribute(xml_device_transistor, "chan_length", loc_data).as_float(0.)); /* Parse the transistor minimum width */ - tech_lib.set_transistor_model_min_width(device_model, transistor_type, - get_attribute(xml_device_transistor, "min_width", loc_data).as_float(0.)); + tech_lib.set_transistor_model_min_width( + device_model, transistor_type, + get_attribute(xml_device_transistor, "min_width", loc_data).as_float(0.)); - /* Parse the transistor maximum width, by default we consider the same as minimum width */ - tech_lib.set_transistor_model_max_width(device_model, transistor_type, - get_attribute(xml_device_transistor, "max_width", loc_data, pugiutil::ReqOpt::OPTIONAL).as_float(0.)); + /* Parse the transistor maximum width, by default we consider the same as + * minimum width */ + tech_lib.set_transistor_model_max_width( + device_model, transistor_type, + get_attribute(xml_device_transistor, "max_width", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_float(0.)); /* If the max_width is default value, we set it to be the same as min_width */ - if (0. == tech_lib.transistor_model_max_width(device_model, transistor_type)) { - tech_lib.set_transistor_model_max_width(device_model, transistor_type, tech_lib.transistor_model_min_width(device_model, transistor_type)); + if (0. == + tech_lib.transistor_model_max_width(device_model, transistor_type)) { + tech_lib.set_transistor_model_max_width( + device_model, transistor_type, + tech_lib.transistor_model_min_width(device_model, transistor_type)); } /* Parse the transistor variation name */ - tech_lib.set_transistor_model_variation_name(device_model, transistor_type, - get_attribute(xml_device_transistor, "variation", loc_data).as_string()); + tech_lib.set_transistor_model_variation_name( + device_model, transistor_type, + get_attribute(xml_device_transistor, "variation", loc_data).as_string()); } /******************************************************************** * Parse XML codes of RRAM models under a device model * to an object of technology library *******************************************************************/ -static -void read_xml_device_rram(pugi::xml_node& xml_device_rram, - const pugiutil::loc_data& loc_data, - TechnologyLibrary& tech_lib, - TechnologyModelId& device_model) { +static void read_xml_device_rram(pugi::xml_node& xml_device_rram, + const pugiutil::loc_data& loc_data, + TechnologyLibrary& tech_lib, + TechnologyModelId& device_model) { /* Parse the LRS and HRS resistance */ - tech_lib.set_rram_rlrs(device_model, get_attribute(xml_device_rram, "rlrs", loc_data).as_float(0.)); - tech_lib.set_rram_rhrs(device_model, get_attribute(xml_device_rram, "rhrs", loc_data).as_float(0.)); + tech_lib.set_rram_rlrs( + device_model, + get_attribute(xml_device_rram, "rlrs", loc_data).as_float(0.)); + tech_lib.set_rram_rhrs( + device_model, + get_attribute(xml_device_rram, "rhrs", loc_data).as_float(0.)); /* Parse the RRAM variation name */ - tech_lib.set_rram_variation_name(device_model, get_attribute(xml_device_rram, "variation", loc_data).as_string()); + tech_lib.set_rram_variation_name( + device_model, + get_attribute(xml_device_rram, "variation", loc_data).as_string()); } /******************************************************************** * Parse XML codes of a to an object of technology library *******************************************************************/ -static -void read_xml_device_model(pugi::xml_node& xml_device_model, - const pugiutil::loc_data& loc_data, - TechnologyLibrary& tech_lib) { - /* Get the name of this device_model node and add a device to the technology library */ - TechnologyModelId device_model = tech_lib.add_model(get_attribute(xml_device_model, "name", loc_data).as_string()); +static void read_xml_device_model(pugi::xml_node& xml_device_model, + const pugiutil::loc_data& loc_data, + TechnologyLibrary& tech_lib) { + /* Get the name of this device_model node and add a device to the technology + * library */ + TechnologyModelId device_model = tech_lib.add_model( + get_attribute(xml_device_model, "name", loc_data).as_string()); /* Find the type of device model*/ - const char* type_attr = get_attribute(xml_device_model, "type", loc_data).value(); + const char* type_attr = + get_attribute(xml_device_model, "type", loc_data).value(); /* Translate the type of design technology to enumerate */ - e_tech_lib_model_type device_model_type = string_to_device_model_type(std::string(type_attr)); + e_tech_lib_model_type device_model_type = + string_to_device_model_type(std::string(type_attr)); if (NUM_TECH_LIB_MODEL_TYPES == device_model_type) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_device_model), - "Invalid 'type' attribute '%s'\n", - type_attr); + "Invalid 'type' attribute '%s'\n", type_attr); } tech_lib.set_model_type(device_model, device_model_type); /* Model library -relate attributes */ - auto xml_device_model_lib = get_single_child(xml_device_model, "lib", loc_data); - read_xml_device_model_lib_settings(xml_device_model_lib, loc_data, tech_lib, device_model); + auto xml_device_model_lib = + get_single_child(xml_device_model, "lib", loc_data); + read_xml_device_model_lib_settings(xml_device_model_lib, loc_data, tech_lib, + device_model); - /* Model design -relate attributes, this is ONLY applicable to transistor models */ + /* Model design -relate attributes, this is ONLY applicable to transistor + * models */ if (TECH_LIB_MODEL_TRANSISTOR == tech_lib.model_type(device_model)) { - auto xml_device_model_design = get_single_child(xml_device_model, "design", loc_data); - read_xml_device_model_design_settings(xml_device_model_design, loc_data, tech_lib, device_model); + auto xml_device_model_design = + get_single_child(xml_device_model, "design", loc_data); + read_xml_device_model_design_settings(xml_device_model_design, loc_data, + tech_lib, device_model); } - /* Transistor -relate attributes, this is ONLY applicable to transistor models */ + /* Transistor -relate attributes, this is ONLY applicable to transistor models + */ if (TECH_LIB_MODEL_TRANSISTOR == tech_lib.model_type(device_model)) { - auto xml_device_model_pmos = get_single_child(xml_device_model, "pmos", loc_data); - read_xml_device_transistor(xml_device_model_pmos, loc_data, tech_lib, device_model, TECH_LIB_TRANSISTOR_PMOS); + auto xml_device_model_pmos = + get_single_child(xml_device_model, "pmos", loc_data); + read_xml_device_transistor(xml_device_model_pmos, loc_data, tech_lib, + device_model, TECH_LIB_TRANSISTOR_PMOS); - auto xml_device_model_nmos = get_single_child(xml_device_model, "nmos", loc_data); - read_xml_device_transistor(xml_device_model_nmos, loc_data, tech_lib, device_model, TECH_LIB_TRANSISTOR_NMOS); + auto xml_device_model_nmos = + get_single_child(xml_device_model, "nmos", loc_data); + read_xml_device_transistor(xml_device_model_nmos, loc_data, tech_lib, + device_model, TECH_LIB_TRANSISTOR_NMOS); } /* RRAM -relate attributes, this is ONLY applicable to RRAM models */ if (TECH_LIB_MODEL_RRAM == tech_lib.model_type(device_model)) { - auto xml_device_rram = get_single_child(xml_device_model, "rram", loc_data); + auto xml_device_rram = get_single_child(xml_device_model, "rram", loc_data); read_xml_device_rram(xml_device_rram, loc_data, tech_lib, device_model); } } @@ -200,24 +233,27 @@ void read_xml_device_model(pugi::xml_node& xml_device_model, /******************************************************************** * Parse XML codes of a to an object of technology library *******************************************************************/ -static -void read_xml_device_variation(pugi::xml_node& xml_device_variation, - const pugiutil::loc_data& loc_data, - TechnologyLibrary& tech_lib) { +static void read_xml_device_variation(pugi::xml_node& xml_device_variation, + const pugiutil::loc_data& loc_data, + TechnologyLibrary& tech_lib) { /* Get the name of this variation and add it to the technology library */ - TechnologyVariationId variation = tech_lib.add_variation(get_attribute(xml_device_variation, "name", loc_data).as_string()); + TechnologyVariationId variation = tech_lib.add_variation( + get_attribute(xml_device_variation, "name", loc_data).as_string()); - tech_lib.set_variation_abs_value(variation, get_attribute(xml_device_variation, "abs_deviation", loc_data).as_float(0.)); - tech_lib.set_variation_num_sigma(variation, get_attribute(xml_device_variation, "num_sigma", loc_data).as_int(0.)); + tech_lib.set_variation_abs_value( + variation, get_attribute(xml_device_variation, "abs_deviation", loc_data) + .as_float(0.)); + tech_lib.set_variation_num_sigma( + variation, + get_attribute(xml_device_variation, "num_sigma", loc_data).as_int(0.)); } /******************************************************************** * Parse XML codes of a to an object of technology library *******************************************************************/ -static -void read_xml_device_lib(pugi::xml_node& xml_device_lib, - const pugiutil::loc_data& loc_data, - TechnologyLibrary& tech_lib) { +static void read_xml_device_lib(pugi::xml_node& xml_device_lib, + const pugiutil::loc_data& loc_data, + TechnologyLibrary& tech_lib) { /* Iterate over the children under this node, * each child should be named after */ @@ -227,16 +263,15 @@ void read_xml_device_lib(pugi::xml_node& xml_device_lib, bad_tag(xml_device_model, loc_data, xml_device_lib, {"device_model"}); } read_xml_device_model(xml_device_model, loc_data, tech_lib); - } + } } /******************************************************************** * Parse XML codes of a to an object of technology library *******************************************************************/ -static -void read_xml_variation_lib(pugi::xml_node& xml_variation_lib, - const pugiutil::loc_data& loc_data, - TechnologyLibrary& tech_lib) { +static void read_xml_variation_lib(pugi::xml_node& xml_variation_lib, + const pugiutil::loc_data& loc_data, + TechnologyLibrary& tech_lib) { /* Iterate over the children under this node, * each child should be named after */ @@ -246,14 +281,14 @@ void read_xml_variation_lib(pugi::xml_node& xml_variation_lib, bad_tag(xml_device_variation, loc_data, xml_variation_lib, {"variation"}); } read_xml_device_variation(xml_device_variation, loc_data, tech_lib); - } + } } /******************************************************************** * Parse XML codes about to an object of technology library *******************************************************************/ -TechnologyLibrary read_xml_technology_library(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data) { +TechnologyLibrary read_xml_technology_library( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data) { TechnologyLibrary tech_lib; /* Iterate over the children under this node, @@ -263,20 +298,25 @@ TechnologyLibrary read_xml_technology_library(pugi::xml_node& Node, */ size_t num_device_lib = count_children(Node, "device_library", loc_data); if (1 != num_device_lib) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(Node), - "Expect only 1 defined under "); + archfpga_throw( + loc_data.filename_c_str(), loc_data.line(Node), + "Expect only 1 defined under "); } - - pugi::xml_node xml_device_lib = get_first_child(Node, "device_library", loc_data); + + pugi::xml_node xml_device_lib = + get_first_child(Node, "device_library", loc_data); read_xml_device_lib(xml_device_lib, loc_data, tech_lib); - size_t num_variation_lib = count_children(Node, "variation_library", loc_data); + size_t num_variation_lib = + count_children(Node, "variation_library", loc_data); if (1 != num_variation_lib) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(Node), - "Expect only 1 defined under "); + archfpga_throw( + loc_data.filename_c_str(), loc_data.line(Node), + "Expect only 1 defined under "); } - pugi::xml_node xml_variation_lib = get_first_child(Node, "variation_library", loc_data); + pugi::xml_node xml_variation_lib = + get_first_child(Node, "variation_library", loc_data); read_xml_variation_lib(xml_variation_lib, loc_data, tech_lib); return tech_lib; diff --git a/libs/libarchopenfpga/src/read_xml_technology_library.h b/libs/libarchopenfpga/src/read_xml_technology_library.h index bbb65c122..7216287eb 100644 --- a/libs/libarchopenfpga/src/read_xml_technology_library.h +++ b/libs/libarchopenfpga/src/read_xml_technology_library.h @@ -4,14 +4,14 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "pugixml_util.hpp" #include "pugixml.hpp" +#include "pugixml_util.hpp" #include "technology_library.h" /******************************************************************** * Function declaration *******************************************************************/ -TechnologyLibrary read_xml_technology_library(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data); +TechnologyLibrary read_xml_technology_library( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data); #endif diff --git a/libs/libarchopenfpga/src/read_xml_tile_annotation.cpp b/libs/libarchopenfpga/src/read_xml_tile_annotation.cpp index 4f1a42745..219c562f4 100644 --- a/libs/libarchopenfpga/src/read_xml_tile_annotation.cpp +++ b/libs/libarchopenfpga/src/read_xml_tile_annotation.cpp @@ -17,30 +17,31 @@ #include "read_xml_util.h" /* Headers from libopenfpgautil */ -#include "openfpga_tokenizer.h" #include "openfpga_port_parser.h" - +#include "openfpga_tokenizer.h" #include "read_xml_tile_annotation.h" /******************************************************************** - * Parse XML description for an interconnection annotation + * Parse XML description for an interconnection annotation * under a XML node *******************************************************************/ -static -void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile, - const pugiutil::loc_data& loc_data, - openfpga::TileAnnotation& tile_annotation) { - /* We have mandatory XML attributes: - * - name of the port +static void read_xml_tile_global_port_annotation( + pugi::xml_node& xml_tile, const pugiutil::loc_data& loc_data, + openfpga::TileAnnotation& tile_annotation) { + /* We have mandatory XML attributes: + * - name of the port */ - const std::string& name_attr = get_attribute(xml_tile, "name", loc_data).as_string(); + const std::string& name_attr = + get_attribute(xml_tile, "name", loc_data).as_string(); - TileGlobalPortId tile_global_port_id = tile_annotation.create_global_port(name_attr); + TileGlobalPortId tile_global_port_id = + tile_annotation.create_global_port(name_attr); /* Report any duplicated port names */ if (TileGlobalPortId::INVALID() == tile_global_port_id) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile), - "Invalid port name '%s' which is defined more than once in the global port list!\n", + "Invalid port name '%s' which is defined more than once in " + "the global port list!\n", name_attr.c_str()); } @@ -53,59 +54,79 @@ void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile, bad_tag(xml_tile_port, loc_data, xml_tile, {"tile"}); } /* Parse the name of the tiles and ports */ - const std::string& tile_name_attr = get_attribute(xml_tile_port, "name", loc_data).as_string(); - const std::string& port_name_attr = get_attribute(xml_tile_port, "port", loc_data).as_string(); + const std::string& tile_name_attr = + get_attribute(xml_tile_port, "name", loc_data).as_string(); + const std::string& port_name_attr = + get_attribute(xml_tile_port, "port", loc_data).as_string(); /* Extract the tile port information */ openfpga::PortParser tile_port_parser(port_name_attr); - - /* Parse tile coordinates */ - vtr::Point tile_coord(get_attribute(xml_tile_port, "x", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-1), - get_attribute(xml_tile_port, "y", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-1)); - /* Add tile port information */ - tile_annotation.add_global_port_tile_information(tile_global_port_id, - tile_name_attr, - tile_port_parser.port(), - tile_coord); - } + /* Parse tile coordinates */ + vtr::Point tile_coord( + get_attribute(xml_tile_port, "x", loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_int(-1), + get_attribute(xml_tile_port, "y", loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_int(-1)); + + /* Add tile port information */ + tile_annotation.add_global_port_tile_information( + tile_global_port_id, tile_name_attr, tile_port_parser.port(), tile_coord); + } /* Check: Must have at least one global port tile information */ - if (true == tile_annotation.global_port_tile_names(tile_global_port_id).empty()) { + if (true == + tile_annotation.global_port_tile_names(tile_global_port_id).empty()) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile), - "Invalid tile annotation for global port '%s'! At least 1 tile port definition is expected!\n", + "Invalid tile annotation for global port '%s'! At least 1 " + "tile port definition is expected!\n", name_attr.c_str()); } /* Get is_clock attributes */ - tile_annotation.set_global_port_is_clock(tile_global_port_id, get_attribute(xml_tile, "is_clock", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + tile_annotation.set_global_port_is_clock( + tile_global_port_id, + get_attribute(xml_tile, "is_clock", loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); /* Get is_set attributes */ - tile_annotation.set_global_port_is_set(tile_global_port_id, get_attribute(xml_tile, "is_set", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + tile_annotation.set_global_port_is_set( + tile_global_port_id, + get_attribute(xml_tile, "is_set", loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); /* Get is_reset attributes */ - tile_annotation.set_global_port_is_reset(tile_global_port_id, get_attribute(xml_tile, "is_reset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + tile_annotation.set_global_port_is_reset( + tile_global_port_id, + get_attribute(xml_tile, "is_reset", loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_bool(false)); /* Get default_value attributes */ - tile_annotation.set_global_port_default_value(tile_global_port_id, get_attribute(xml_tile, "default_val", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(0)); + tile_annotation.set_global_port_default_value( + tile_global_port_id, + get_attribute(xml_tile, "default_val", loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_int(0)); /* Ensure valid port attributes */ - if (false == tile_annotation.valid_global_port_attributes(tile_global_port_id)) { + if (false == + tile_annotation.valid_global_port_attributes(tile_global_port_id)) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile), - "Invalid port attributes for '%s'! A port can only be clock or set or reset.\n", + "Invalid port attributes for '%s'! A port can only be clock " + "or set or reset.\n", name_attr.c_str()); } } /******************************************************************** - * Top function to parse XML description about tile annotation + * Top function to parse XML description about tile annotation *******************************************************************/ -openfpga::TileAnnotation read_xml_tile_annotations(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data) { +openfpga::TileAnnotation read_xml_tile_annotations( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data) { openfpga::TileAnnotation tile_annotations; /* Parse configuration protocol root node */ - pugi::xml_node xml_annotations = get_single_child(Node, "tile_annotations", loc_data, pugiutil::ReqOpt::OPTIONAL); + pugi::xml_node xml_annotations = get_single_child( + Node, "tile_annotations", loc_data, pugiutil::ReqOpt::OPTIONAL); /* Not found, we can return */ if (!xml_annotations) { @@ -120,8 +141,9 @@ openfpga::TileAnnotation read_xml_tile_annotations(pugi::xml_node& Node, if (xml_tile_global_port.name() != std::string("global_port")) { bad_tag(xml_tile_global_port, loc_data, xml_annotations, {"global_port"}); } - read_xml_tile_global_port_annotation(xml_tile_global_port, loc_data, tile_annotations); - } + read_xml_tile_global_port_annotation(xml_tile_global_port, loc_data, + tile_annotations); + } return tile_annotations; } diff --git a/libs/libarchopenfpga/src/read_xml_tile_annotation.h b/libs/libarchopenfpga/src/read_xml_tile_annotation.h index 0c32684e8..5fba0db5b 100644 --- a/libs/libarchopenfpga/src/read_xml_tile_annotation.h +++ b/libs/libarchopenfpga/src/read_xml_tile_annotation.h @@ -4,14 +4,14 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "pugixml_util.hpp" #include "pugixml.hpp" +#include "pugixml_util.hpp" #include "tile_annotation.h" /******************************************************************** * Function declaration *******************************************************************/ -openfpga::TileAnnotation read_xml_tile_annotations(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data); +openfpga::TileAnnotation read_xml_tile_annotations( + pugi::xml_node& Node, const pugiutil::loc_data& loc_data); #endif diff --git a/libs/libarchopenfpga/src/simulation_setting.cpp b/libs/libarchopenfpga/src/simulation_setting.cpp index ebbc50fc6..b6ff0c411 100644 --- a/libs/libarchopenfpga/src/simulation_setting.cpp +++ b/libs/libarchopenfpga/src/simulation_setting.cpp @@ -1,7 +1,7 @@ -#include "vtr_assert.h" - #include "simulation_setting.h" +#include "vtr_assert.h" + /* namespace openfpga begins */ namespace openfpga { @@ -36,7 +36,8 @@ std::vector SimulationSetting::programming_clocks() const { return prog_clks; } -std::vector SimulationSetting::programming_shift_register_clocks() const { +std::vector +SimulationSetting::programming_shift_register_clocks() const { std::vector prog_clks; for (const SimulationClockId& clk : clocks()) { if (clock_is_programming(clk) && clock_is_shift_register(clk)) { @@ -49,9 +50,7 @@ std::vector SimulationSetting::programming_shift_register_clo /************************************************************************ * Constructors ***********************************************************************/ -SimulationSetting::SimulationSetting() { - return; -} +SimulationSetting::SimulationSetting() { return; } /************************************************************************ * Public Accessors @@ -68,27 +67,32 @@ size_t SimulationSetting::num_simulation_clock_cycles() const { return clock_ids_.size(); } -std::string SimulationSetting::clock_name(const SimulationClockId& clock_id) const { +std::string SimulationSetting::clock_name( + const SimulationClockId& clock_id) const { VTR_ASSERT(valid_clock_id(clock_id)); return clock_names_[clock_id]; } -BasicPort SimulationSetting::clock_port(const SimulationClockId& clock_id) const { +BasicPort SimulationSetting::clock_port( + const SimulationClockId& clock_id) const { VTR_ASSERT(valid_clock_id(clock_id)); return clock_ports_[clock_id]; } -float SimulationSetting::clock_frequency(const SimulationClockId& clock_id) const { +float SimulationSetting::clock_frequency( + const SimulationClockId& clock_id) const { VTR_ASSERT(valid_clock_id(clock_id)); return clock_frequencies_[clock_id]; } -bool SimulationSetting::clock_is_programming(const SimulationClockId& clock_id) const { +bool SimulationSetting::clock_is_programming( + const SimulationClockId& clock_id) const { VTR_ASSERT(valid_clock_id(clock_id)); return clock_is_programming_[clock_id]; } -bool SimulationSetting::clock_is_shift_register(const SimulationClockId& clock_id) const { +bool SimulationSetting::clock_is_shift_register( + const SimulationClockId& clock_id) const { VTR_ASSERT(valid_clock_id(clock_id)); return clock_is_shift_register_[clock_id]; } @@ -97,9 +101,7 @@ bool SimulationSetting::auto_select_num_clock_cycles() const { return 0 == num_clock_cycles_; } -size_t SimulationSetting::num_clock_cycles() const { - return num_clock_cycles_; -} +size_t SimulationSetting::num_clock_cycles() const { return num_clock_cycles_; } float SimulationSetting::operating_clock_frequency_slack() const { return operating_clock_frequency_slack_; @@ -109,9 +111,7 @@ float SimulationSetting::simulation_temperature() const { return simulation_temperature_; } -bool SimulationSetting::verbose_output() const { - return verbose_output_; -} +bool SimulationSetting::verbose_output() const { return verbose_output_; } bool SimulationSetting::capacitance_output() const { return capacitance_output_; @@ -125,9 +125,7 @@ float SimulationSetting::simulation_accuracy() const { return simulation_accuracy_; } -bool SimulationSetting::fast_simulation() const { - return fast_simulation_; -} +bool SimulationSetting::fast_simulation() const { return fast_simulation_; } bool SimulationSetting::run_monte_carlo_simulation() const { return 0 == monte_carlo_simulation_points_; @@ -137,56 +135,71 @@ size_t SimulationSetting::monte_carlo_simulation_points() const { return monte_carlo_simulation_points_; } -float SimulationSetting::measure_slew_upper_threshold(const e_sim_signal_type& signal_type) const { - VTR_ASSERT (true == valid_signal_threshold(slew_upper_thresholds_[signal_type])); +float SimulationSetting::measure_slew_upper_threshold( + const e_sim_signal_type& signal_type) const { + VTR_ASSERT(true == + valid_signal_threshold(slew_upper_thresholds_[signal_type])); return slew_upper_thresholds_[signal_type]; } -float SimulationSetting::measure_slew_lower_threshold(const e_sim_signal_type& signal_type) const { - VTR_ASSERT (true == valid_signal_threshold(slew_lower_thresholds_[signal_type])); +float SimulationSetting::measure_slew_lower_threshold( + const e_sim_signal_type& signal_type) const { + VTR_ASSERT(true == + valid_signal_threshold(slew_lower_thresholds_[signal_type])); return slew_lower_thresholds_[signal_type]; } -float SimulationSetting::measure_delay_input_threshold(const e_sim_signal_type& signal_type) const { - VTR_ASSERT (true == valid_signal_threshold(delay_input_thresholds_[signal_type])); +float SimulationSetting::measure_delay_input_threshold( + const e_sim_signal_type& signal_type) const { + VTR_ASSERT(true == + valid_signal_threshold(delay_input_thresholds_[signal_type])); return delay_input_thresholds_[signal_type]; } -float SimulationSetting::measure_delay_output_threshold(const e_sim_signal_type& signal_type) const { - VTR_ASSERT (true == valid_signal_threshold(delay_output_thresholds_[signal_type])); +float SimulationSetting::measure_delay_output_threshold( + const e_sim_signal_type& signal_type) const { + VTR_ASSERT(true == + valid_signal_threshold(delay_output_thresholds_[signal_type])); return delay_output_thresholds_[signal_type]; } -e_sim_accuracy_type SimulationSetting::stimuli_clock_slew_type(const e_sim_signal_type& signal_type) const { +e_sim_accuracy_type SimulationSetting::stimuli_clock_slew_type( + const e_sim_signal_type& signal_type) const { return clock_slew_types_[signal_type]; } -float SimulationSetting::stimuli_clock_slew(const e_sim_signal_type& signal_type) const { +float SimulationSetting::stimuli_clock_slew( + const e_sim_signal_type& signal_type) const { return clock_slews_[signal_type]; } -e_sim_accuracy_type SimulationSetting::stimuli_input_slew_type(const e_sim_signal_type& signal_type) const { +e_sim_accuracy_type SimulationSetting::stimuli_input_slew_type( + const e_sim_signal_type& signal_type) const { return input_slew_types_[signal_type]; } -float SimulationSetting::stimuli_input_slew(const e_sim_signal_type& signal_type) const { +float SimulationSetting::stimuli_input_slew( + const e_sim_signal_type& signal_type) const { return input_slews_[signal_type]; } /************************************************************************ * Public Mutators ***********************************************************************/ -void SimulationSetting::set_default_operating_clock_frequency(const float& clock_freq) { +void SimulationSetting::set_default_operating_clock_frequency( + const float& clock_freq) { default_clock_frequencies_.set_x(clock_freq); } -void SimulationSetting::set_programming_clock_frequency(const float& clock_freq) { +void SimulationSetting::set_programming_clock_frequency( + const float& clock_freq) { default_clock_frequencies_.set_y(clock_freq); } SimulationClockId SimulationSetting::create_clock(const std::string& name) { /* Ensure a unique name for the clock definition */ - std::map::iterator it = clock_name2ids_.find(name); + std::map::iterator it = + clock_name2ids_.find(name); if (it != clock_name2ids_.end()) { return SimulationClockId::INVALID(); } @@ -218,14 +231,14 @@ void SimulationSetting::set_clock_frequency(const SimulationClockId& clock_id, clock_frequencies_[clock_id] = frequency; } -void SimulationSetting::set_clock_is_programming(const SimulationClockId& clock_id, - const float& is_prog) { +void SimulationSetting::set_clock_is_programming( + const SimulationClockId& clock_id, const float& is_prog) { VTR_ASSERT(valid_clock_id(clock_id)); clock_is_programming_[clock_id] = is_prog; } -void SimulationSetting::set_clock_is_shift_register(const SimulationClockId& clock_id, - const float& is_sr) { +void SimulationSetting::set_clock_is_shift_register( + const SimulationClockId& clock_id, const float& is_sr) { VTR_ASSERT(valid_clock_id(clock_id)); clock_is_shift_register_[clock_id] = is_sr; } @@ -234,7 +247,8 @@ void SimulationSetting::set_num_clock_cycles(const size_t& num_clk_cycles) { num_clock_cycles_ = num_clk_cycles; } -void SimulationSetting::set_operating_clock_frequency_slack(const float& op_clk_freq_slack) { +void SimulationSetting::set_operating_clock_frequency_slack( + const float& op_clk_freq_slack) { operating_clock_frequency_slack_ = op_clk_freq_slack; } @@ -250,7 +264,8 @@ void SimulationSetting::set_capacitance_output(const bool& cap_output) { capacitance_output_ = cap_output; } -void SimulationSetting::set_simulation_accuracy_type(const e_sim_accuracy_type& type) { +void SimulationSetting::set_simulation_accuracy_type( + const e_sim_accuracy_type& type) { VTR_ASSERT(NUM_SIM_ACCURACY_TYPES != type); simulation_accuracy_type_ = type; } @@ -263,57 +278,58 @@ void SimulationSetting::set_fast_simulation(const bool& fast_sim) { fast_simulation_ = fast_sim; } -void SimulationSetting::set_monte_carlo_simulation_points(const size_t& num_mc_points) { +void SimulationSetting::set_monte_carlo_simulation_points( + const size_t& num_mc_points) { monte_carlo_simulation_points_ = num_mc_points; } -void SimulationSetting::set_measure_slew_upper_threshold(const e_sim_signal_type& signal_type, - const float& upper_thres) { +void SimulationSetting::set_measure_slew_upper_threshold( + const e_sim_signal_type& signal_type, const float& upper_thres) { VTR_ASSERT(NUM_SIM_SIGNAL_TYPES != signal_type); - VTR_ASSERT (true == valid_signal_threshold(upper_thres)); + VTR_ASSERT(true == valid_signal_threshold(upper_thres)); slew_upper_thresholds_[signal_type] = upper_thres; } -void SimulationSetting::set_measure_slew_lower_threshold(const e_sim_signal_type& signal_type, - const float& lower_thres) { +void SimulationSetting::set_measure_slew_lower_threshold( + const e_sim_signal_type& signal_type, const float& lower_thres) { VTR_ASSERT(NUM_SIM_SIGNAL_TYPES != signal_type); - VTR_ASSERT (true == valid_signal_threshold(lower_thres)); + VTR_ASSERT(true == valid_signal_threshold(lower_thres)); slew_lower_thresholds_[signal_type] = lower_thres; } -void SimulationSetting::set_measure_delay_input_threshold(const e_sim_signal_type& signal_type, - const float& input_thres) { +void SimulationSetting::set_measure_delay_input_threshold( + const e_sim_signal_type& signal_type, const float& input_thres) { VTR_ASSERT(NUM_SIM_SIGNAL_TYPES != signal_type); - VTR_ASSERT (true == valid_signal_threshold(input_thres)); + VTR_ASSERT(true == valid_signal_threshold(input_thres)); delay_input_thresholds_[signal_type] = input_thres; } -void SimulationSetting::set_measure_delay_output_threshold(const e_sim_signal_type& signal_type, - const float& output_thres) { +void SimulationSetting::set_measure_delay_output_threshold( + const e_sim_signal_type& signal_type, const float& output_thres) { VTR_ASSERT(NUM_SIM_SIGNAL_TYPES != signal_type); - VTR_ASSERT (true == valid_signal_threshold(output_thres)); + VTR_ASSERT(true == valid_signal_threshold(output_thres)); delay_output_thresholds_[signal_type] = output_thres; } -void SimulationSetting::set_stimuli_clock_slew_type(const e_sim_signal_type& signal_type, - const e_sim_accuracy_type& slew_type) { +void SimulationSetting::set_stimuli_clock_slew_type( + const e_sim_signal_type& signal_type, const e_sim_accuracy_type& slew_type) { VTR_ASSERT(NUM_SIM_SIGNAL_TYPES != signal_type); clock_slew_types_[signal_type] = slew_type; } -void SimulationSetting::set_stimuli_clock_slew(const e_sim_signal_type& signal_type, - const float& clock_slew) { +void SimulationSetting::set_stimuli_clock_slew( + const e_sim_signal_type& signal_type, const float& clock_slew) { clock_slews_[signal_type] = clock_slew; } -void SimulationSetting::set_stimuli_input_slew_type(const e_sim_signal_type& signal_type, - const e_sim_accuracy_type& input_type) { +void SimulationSetting::set_stimuli_input_slew_type( + const e_sim_signal_type& signal_type, const e_sim_accuracy_type& input_type) { VTR_ASSERT(NUM_SIM_SIGNAL_TYPES != signal_type); input_slew_types_[signal_type] = input_type; } -void SimulationSetting::set_stimuli_input_slew(const e_sim_signal_type& signal_type, - const float& input_slew) { +void SimulationSetting::set_stimuli_input_slew( + const e_sim_signal_type& signal_type, const float& input_slew) { input_slews_[signal_type] = input_slew; } @@ -324,13 +340,16 @@ bool SimulationSetting::valid_signal_threshold(const float& threshold) const { return (0. < threshold) && (threshold < 1); } -bool SimulationSetting::valid_clock_id(const SimulationClockId& clock_id) const { - return ( size_t(clock_id) < clock_ids_.size() ) && ( clock_id == clock_ids_[clock_id] ); +bool SimulationSetting::valid_clock_id( + const SimulationClockId& clock_id) const { + return (size_t(clock_id) < clock_ids_.size()) && + (clock_id == clock_ids_[clock_id]); } -bool SimulationSetting::constrained_clock(const SimulationClockId& clock_id) const { +bool SimulationSetting::constrained_clock( + const SimulationClockId& clock_id) const { VTR_ASSERT(valid_clock_id(clock_id)); return 0. != clock_frequencies_[clock_id]; } -} /* namespace openfpga ends */ +} // namespace openfpga diff --git a/libs/libarchopenfpga/src/simulation_setting.h b/libs/libarchopenfpga/src/simulation_setting.h index 532380b26..45c738ffc 100644 --- a/libs/libarchopenfpga/src/simulation_setting.h +++ b/libs/libarchopenfpga/src/simulation_setting.h @@ -3,34 +3,33 @@ /******************************************************************** * This file include the declaration of simulation settings - * which are used by OpenFPGA + * which are used by OpenFPGA *******************************************************************/ -#include #include #include +#include -#include "vtr_vector.h" -#include "vtr_geometry.h" - -#include "openfpga_port.h" - -#include "simulation_setting_fwd.h" +#include "openfpga_port.h" +#include "simulation_setting_fwd.h" +#include "vtr_geometry.h" +#include "vtr_vector.h" /******************************************************************** * Types of signal type in measurement and stimuli *******************************************************************/ enum e_sim_signal_type { - SIM_SIGNAL_RISE, + SIM_SIGNAL_RISE, SIM_SIGNAL_FALL, NUM_SIM_SIGNAL_TYPES }; /* Strings correspond to each delay type */ -constexpr std::array SIM_SIGNAL_TYPE_STRING = {{"rise", "fall"}}; +constexpr std::array SIM_SIGNAL_TYPE_STRING = + {{"rise", "fall"}}; /******************************************************************** * Types of simulation accuracy type * 1. Fraction to the operating clock frequency - * 2. Absolute value + * 2. Absolute value *******************************************************************/ enum e_sim_accuracy_type { SIM_ACCURACY_FRAC, @@ -38,7 +37,8 @@ enum e_sim_accuracy_type { NUM_SIM_ACCURACY_TYPES }; /* Strings correspond to each accuracy type */ -constexpr std::array SIM_ACCURACY_TYPE_STRING = {{"frac", "abs"}}; +constexpr std::array + SIM_ACCURACY_TYPE_STRING = {{"frac", "abs"}}; /* namespace openfpga begins */ namespace openfpga { @@ -54,223 +54,233 @@ namespace openfpga { * *******************************************************************/ class SimulationSetting { - public: /* Types */ - typedef vtr::vector::const_iterator simulation_clock_iterator; - /* Create range */ - typedef vtr::Range simulation_clock_range; - public: /* Constructors */ - SimulationSetting(); - public: /* Accessors: aggregates */ - simulation_clock_range clocks() const; - std::vector operating_clocks() const; - std::vector programming_clocks() const; - std::vector programming_shift_register_clocks() const; - public: /* Public Accessors */ - float default_operating_clock_frequency() const; - float programming_clock_frequency() const; - size_t num_simulation_clock_cycles() const; - std::string clock_name(const SimulationClockId& clock_id) const; - BasicPort clock_port(const SimulationClockId& clock_id) const; - float clock_frequency(const SimulationClockId& clock_id) const; - bool clock_is_programming(const SimulationClockId& clock_id) const; - bool clock_is_shift_register(const SimulationClockId& clock_id) const; - bool auto_select_num_clock_cycles() const; - size_t num_clock_cycles() const; - float operating_clock_frequency_slack() const; - float simulation_temperature() const; - bool verbose_output() const; - bool capacitance_output() const; - e_sim_accuracy_type simulation_accuracy_type() const; - float simulation_accuracy() const; - bool fast_simulation() const; - bool run_monte_carlo_simulation() const; - size_t monte_carlo_simulation_points() const; - float measure_slew_upper_threshold(const e_sim_signal_type& signal_type) const; - float measure_slew_lower_threshold(const e_sim_signal_type& signal_type) const; - float measure_delay_input_threshold(const e_sim_signal_type& signal_type) const; - float measure_delay_output_threshold(const e_sim_signal_type& signal_type) const; - e_sim_accuracy_type stimuli_clock_slew_type(const e_sim_signal_type& signal_type) const; - float stimuli_clock_slew(const e_sim_signal_type& signal_type) const; - e_sim_accuracy_type stimuli_input_slew_type(const e_sim_signal_type& signal_type) const; - float stimuli_input_slew(const e_sim_signal_type& signal_type) const; - public: /* Public Mutators */ - void set_default_operating_clock_frequency(const float& clock_freq); - void set_programming_clock_frequency(const float& clock_freq); - /* Add a new simulation clock with - * - a given name - * - a given port description - * - a default zero frequency which can be overwritten by - * the operating_clock_frequency() - */ - SimulationClockId create_clock(const std::string& name); - void set_clock_port(const SimulationClockId& clock_id, - const BasicPort& port); - void set_clock_frequency(const SimulationClockId& clock_id, - const float& frequency); - void set_clock_is_programming(const SimulationClockId& clock_id, - const float& is_prog); - void set_clock_is_shift_register(const SimulationClockId& clock_id, - const float& is_sr); - void set_num_clock_cycles(const size_t& num_clk_cycles); - void set_operating_clock_frequency_slack(const float& op_clk_freq_slack); - void set_simulation_temperature(const float& sim_temp); - void set_verbose_output(const bool& verbose_output); - void set_capacitance_output(const bool& cap_output); - void set_simulation_accuracy_type(const e_sim_accuracy_type& type); - void set_simulation_accuracy(const float& accuracy); - void set_fast_simulation(const bool& fast_sim); - void set_monte_carlo_simulation_points(const size_t& num_mc_points); - void set_measure_slew_upper_threshold(const e_sim_signal_type& signal_type, - const float& upper_thres); - void set_measure_slew_lower_threshold(const e_sim_signal_type& signal_type, - const float& lower_thres); - void set_measure_delay_input_threshold(const e_sim_signal_type& signal_type, - const float& input_thres); - void set_measure_delay_output_threshold(const e_sim_signal_type& signal_type, - const float& output_thres); - void set_stimuli_clock_slew_type(const e_sim_signal_type& signal_type, - const e_sim_accuracy_type& slew_type); - void set_stimuli_clock_slew(const e_sim_signal_type& signal_type, - const float& clock_slew); - void set_stimuli_input_slew_type(const e_sim_signal_type& signal_type, - const e_sim_accuracy_type& slew_type); - void set_stimuli_input_slew(const e_sim_signal_type& signal_type, - const float& input_slew); - public: /* Public Validators */ - bool valid_signal_threshold(const float& threshold) const; - bool valid_clock_id(const SimulationClockId& clock_id) const; - /** @brief Validate if a given clock is constrained or not */ - bool constrained_clock(const SimulationClockId& clock_id) const; - private: /* Internal data */ - /* Operating clock frequency: the default clock frequency to be applied to users' implemetation on FPGA - * This will be stored in the x() part of vtr::Point - * Programming clock frequency: the clock frequency to be applied to configuration protocol of FPGA - * This will be stored in the y() part of vtr::Point - */ - vtr::Point default_clock_frequencies_; + public: /* Types */ + typedef vtr::vector::const_iterator + simulation_clock_iterator; + /* Create range */ + typedef vtr::Range simulation_clock_range; - /* Multiple simulation clocks with detailed information - * Each clock has - * - a unique id - * - a unique name - * - a unique port definition which is supposed - * to match the clock port definition in OpenFPGA documentation - * - a frequency which is only applicable to this clock name - */ - vtr::vector clock_ids_; - vtr::vector clock_names_; - vtr::vector clock_ports_; - vtr::vector clock_frequencies_; - vtr::vector clock_is_programming_; - vtr::vector clock_is_shift_register_; + public: /* Constructors */ + SimulationSetting(); - /* Fast name-to-id lookup */ - std::map clock_name2ids_; + public: /* Accessors: aggregates */ + simulation_clock_range clocks() const; + std::vector operating_clocks() const; + std::vector programming_clocks() const; + std::vector programming_shift_register_clocks() const; - /* Number of clock cycles to be used in simulation - * If the value is 0, the clock cycles can be automatically - * inferred from the signal activities of users' implementation - */ - size_t num_clock_cycles_; - - /* Slack or margin to be added to clock frequency - * if the operating clock frequency is automatically - * detemined by VPR's routing results - */ - float operating_clock_frequency_slack_; + public: /* Public Accessors */ + float default_operating_clock_frequency() const; + float programming_clock_frequency() const; + size_t num_simulation_clock_cycles() const; + std::string clock_name(const SimulationClockId& clock_id) const; + BasicPort clock_port(const SimulationClockId& clock_id) const; + float clock_frequency(const SimulationClockId& clock_id) const; + bool clock_is_programming(const SimulationClockId& clock_id) const; + bool clock_is_shift_register(const SimulationClockId& clock_id) const; + bool auto_select_num_clock_cycles() const; + size_t num_clock_cycles() const; + float operating_clock_frequency_slack() const; + float simulation_temperature() const; + bool verbose_output() const; + bool capacitance_output() const; + e_sim_accuracy_type simulation_accuracy_type() const; + float simulation_accuracy() const; + bool fast_simulation() const; + bool run_monte_carlo_simulation() const; + size_t monte_carlo_simulation_points() const; + float measure_slew_upper_threshold( + const e_sim_signal_type& signal_type) const; + float measure_slew_lower_threshold( + const e_sim_signal_type& signal_type) const; + float measure_delay_input_threshold( + const e_sim_signal_type& signal_type) const; + float measure_delay_output_threshold( + const e_sim_signal_type& signal_type) const; + e_sim_accuracy_type stimuli_clock_slew_type( + const e_sim_signal_type& signal_type) const; + float stimuli_clock_slew(const e_sim_signal_type& signal_type) const; + e_sim_accuracy_type stimuli_input_slew_type( + const e_sim_signal_type& signal_type) const; + float stimuli_input_slew(const e_sim_signal_type& signal_type) const; - /* Operating temperature to be use in simulation */ - float simulation_temperature_; + public: /* Public Mutators */ + void set_default_operating_clock_frequency(const float& clock_freq); + void set_programming_clock_frequency(const float& clock_freq); + /* Add a new simulation clock with + * - a given name + * - a given port description + * - a default zero frequency which can be overwritten by + * the operating_clock_frequency() + */ + SimulationClockId create_clock(const std::string& name); + void set_clock_port(const SimulationClockId& clock_id, const BasicPort& port); + void set_clock_frequency(const SimulationClockId& clock_id, + const float& frequency); + void set_clock_is_programming(const SimulationClockId& clock_id, + const float& is_prog); + void set_clock_is_shift_register(const SimulationClockId& clock_id, + const float& is_sr); + void set_num_clock_cycles(const size_t& num_clk_cycles); + void set_operating_clock_frequency_slack(const float& op_clk_freq_slack); + void set_simulation_temperature(const float& sim_temp); + void set_verbose_output(const bool& verbose_output); + void set_capacitance_output(const bool& cap_output); + void set_simulation_accuracy_type(const e_sim_accuracy_type& type); + void set_simulation_accuracy(const float& accuracy); + void set_fast_simulation(const bool& fast_sim); + void set_monte_carlo_simulation_points(const size_t& num_mc_points); + void set_measure_slew_upper_threshold(const e_sim_signal_type& signal_type, + const float& upper_thres); + void set_measure_slew_lower_threshold(const e_sim_signal_type& signal_type, + const float& lower_thres); + void set_measure_delay_input_threshold(const e_sim_signal_type& signal_type, + const float& input_thres); + void set_measure_delay_output_threshold(const e_sim_signal_type& signal_type, + const float& output_thres); + void set_stimuli_clock_slew_type(const e_sim_signal_type& signal_type, + const e_sim_accuracy_type& slew_type); + void set_stimuli_clock_slew(const e_sim_signal_type& signal_type, + const float& clock_slew); + void set_stimuli_input_slew_type(const e_sim_signal_type& signal_type, + const e_sim_accuracy_type& slew_type); + void set_stimuli_input_slew(const e_sim_signal_type& signal_type, + const float& input_slew); - /* Options support by simulators - * verbose_output: This is an option to turn on verbose output in simulators - * Simulation runtime can be slow when this option is on - * for large FPGA fabrics! - * capacitance_output: Show capacitance of each nodes in the log file - * This is an option provided by SPICE simulators - * Simulation runtime can be slow when this option is on - * for large FPGA fabrics! - * accuracy_type: type of accuracy to be used in simulation - * See the definition in enumeration e_sim_accuracy_type - * Simulation runtime can be slow when a high accuracy is enable - * for large FPGA fabrics! - * accuracy: the absolute value of accuracy to be used in simulation. - * If fractional accuarcy is specified, the value will be determined by - * the maximum operating frequency after VPR routing finished - * If absolute accuracy is specified, the value will be given by users - */ - bool verbose_output_; - bool capacitance_output_; - e_sim_accuracy_type simulation_accuracy_type_; - float simulation_accuracy_; + public: /* Public Validators */ + bool valid_signal_threshold(const float& threshold) const; + bool valid_clock_id(const SimulationClockId& clock_id) const; + /** @brief Validate if a given clock is constrained or not */ + bool constrained_clock(const SimulationClockId& clock_id) const; - /* Enable fast simulation - * Note: this may impact the accuracy of simulation results - */ - bool fast_simulation_; + private: /* Internal data */ + /* Operating clock frequency: the default clock frequency to be applied to + * users' implemetation on FPGA This will be stored in the x() part of + * vtr::Point Programming clock frequency: the clock frequency to be applied + * to configuration protocol of FPGA This will be stored in the y() part of + * vtr::Point + */ + vtr::Point default_clock_frequencies_; - /* Number of simulation points to be used in Monte Carlo simulation - * If a zero is given, monte carlo simulation will not be applied - * The larger number of simulation points is used, the slower runtime will be - */ - size_t monte_carlo_simulation_points_; + /* Multiple simulation clocks with detailed information + * Each clock has + * - a unique id + * - a unique name + * - a unique port definition which is supposed + * to match the clock port definition in OpenFPGA documentation + * - a frequency which is only applicable to this clock name + */ + vtr::vector clock_ids_; + vtr::vector clock_names_; + vtr::vector clock_ports_; + vtr::vector clock_frequencies_; + vtr::vector clock_is_programming_; + vtr::vector clock_is_shift_register_; - /* The thresholds (in percentage) to be used in the measuring signal slews - * Thresholds related to rising edge will be stored in the first element - * Thresholds related to falling edge will be stored in the second element - */ - std::array slew_upper_thresholds_; - std::array slew_lower_thresholds_; + /* Fast name-to-id lookup */ + std::map clock_name2ids_; - /* The thresholds (in percentage) to be used in the measuring signal delays - * Thresholds related to rising edge will be stored in the first element - * Thresholds related to falling edge will be stored in the second element - * - * An example of delay measurement in rising edge - * from 50% of input signal to 50% of output signal - * (delay_input_threshold=0.5; delay_output_threshold=0.5) - * - * Input signal - * - * 50% of full swing of input signal - * ^ +-------------------------- - * |/ - * +----------------+ - * / | | - * -------+ | | - * v | - * rise delay | - * | - * Output signal | - * | +-------- - * |/ - * + - * /| - * -------------------------+ | - * v - * 50% of full swing of output signal - */ - std::array delay_input_thresholds_; - std::array delay_output_thresholds_; + /* Number of clock cycles to be used in simulation + * If the value is 0, the clock cycles can be automatically + * inferred from the signal activities of users' implementation + */ + size_t num_clock_cycles_; - /* Stimulus to be given to each type of port. - * We support two types of ports: - * 1. clock ports - * 2. regular input ports - * - * Slew time related to rising edge will be stored in the first element - * Slew time related to falling edge will be stored in the second element - * - * accuracy_type: type of accuracy to be used in simulation - * Fractional accuracy will be determined by the clock frequency - * to be defined by user in the clock_setting - */ - std::array clock_slew_types_; - std::array clock_slews_; - std::array input_slew_types_; - std::array input_slews_; + /* Slack or margin to be added to clock frequency + * if the operating clock frequency is automatically + * detemined by VPR's routing results + */ + float operating_clock_frequency_slack_; + + /* Operating temperature to be use in simulation */ + float simulation_temperature_; + + /* Options support by simulators + * verbose_output: This is an option to turn on verbose output in + * simulators Simulation runtime can be slow when this option is on for large + * FPGA fabrics! capacitance_output: Show capacitance of each nodes in the log + * file This is an option provided by SPICE simulators Simulation runtime can + * be slow when this option is on for large FPGA fabrics! accuracy_type: type + * of accuracy to be used in simulation See the definition in enumeration + * e_sim_accuracy_type Simulation runtime can be slow when a high accuracy is + * enable for large FPGA fabrics! accuracy: the absolute value of + * accuracy to be used in simulation. If fractional accuarcy is specified, the + * value will be determined by the maximum operating frequency after VPR + * routing finished If absolute accuracy is specified, the value will be given + * by users + */ + bool verbose_output_; + bool capacitance_output_; + e_sim_accuracy_type simulation_accuracy_type_; + float simulation_accuracy_; + + /* Enable fast simulation + * Note: this may impact the accuracy of simulation results + */ + bool fast_simulation_; + + /* Number of simulation points to be used in Monte Carlo simulation + * If a zero is given, monte carlo simulation will not be applied + * The larger number of simulation points is used, the slower runtime will be + */ + size_t monte_carlo_simulation_points_; + + /* The thresholds (in percentage) to be used in the measuring signal slews + * Thresholds related to rising edge will be stored in the first element + * Thresholds related to falling edge will be stored in the second element + */ + std::array slew_upper_thresholds_; + std::array slew_lower_thresholds_; + + /* The thresholds (in percentage) to be used in the measuring signal delays + * Thresholds related to rising edge will be stored in the first element + * Thresholds related to falling edge will be stored in the second element + * + * An example of delay measurement in rising edge + * from 50% of input signal to 50% of output signal + * (delay_input_threshold=0.5; delay_output_threshold=0.5) + * + * Input signal + * + * 50% of full swing of input signal + * ^ +-------------------------- + * |/ + * +----------------+ + * / | | + * -------+ | | + * v | + * rise delay | + * | + * Output signal | + * | +-------- + * |/ + * + + * /| + * -------------------------+ | + * v + * 50% of full swing of output signal + */ + std::array delay_input_thresholds_; + std::array delay_output_thresholds_; + + /* Stimulus to be given to each type of port. + * We support two types of ports: + * 1. clock ports + * 2. regular input ports + * + * Slew time related to rising edge will be stored in the first element + * Slew time related to falling edge will be stored in the second element + * + * accuracy_type: type of accuracy to be used in simulation + * Fractional accuracy will be determined by the clock + * frequency to be defined by user in the clock_setting + */ + std::array clock_slew_types_; + std::array clock_slews_; + std::array input_slew_types_; + std::array input_slews_; }; -} /* namespace openfpga ends */ +} // namespace openfpga #endif diff --git a/libs/libarchopenfpga/src/simulation_setting_fwd.h b/libs/libarchopenfpga/src/simulation_setting_fwd.h index 24d9c8dc3..f11434d1f 100644 --- a/libs/libarchopenfpga/src/simulation_setting_fwd.h +++ b/libs/libarchopenfpga/src/simulation_setting_fwd.h @@ -1,11 +1,11 @@ /************************************************************************ - * A header file for SimulationSetting class, including critical data declaration - * Please include this file only for using any SimulationSetting data structure - * Refer to simulation_setting.h for more details + * A header file for SimulationSetting class, including critical data + *declaration Please include this file only for using any SimulationSetting data + *structure Refer to simulation_setting.h for more details ***********************************************************************/ /************************************************************************ - * Create strong id for Simulation Clock to avoid illegal type casting + * Create strong id for Simulation Clock to avoid illegal type casting ***********************************************************************/ #ifndef SIMULATION_SETTING_FWD_H #define SIMULATION_SETTING_FWD_H diff --git a/libs/libarchopenfpga/src/technology_library.cpp b/libs/libarchopenfpga/src/technology_library.cpp index aa97abe80..3f15f8219 100644 --- a/libs/libarchopenfpga/src/technology_library.cpp +++ b/libs/libarchopenfpga/src/technology_library.cpp @@ -1,7 +1,7 @@ -#include "vtr_assert.h" - #include "technology_library.h" +#include "vtr_assert.h" + /************************************************************************ * Member functions for class TechnologyLibrary ***********************************************************************/ @@ -9,9 +9,7 @@ /************************************************************************ * Constructors ***********************************************************************/ -TechnologyLibrary::TechnologyLibrary() { - return; -} +TechnologyLibrary::TechnologyLibrary() { return; } /************************************************************************ * Public Accessors : aggregates @@ -20,12 +18,15 @@ TechnologyLibrary::technology_model_range TechnologyLibrary::models() const { return vtr::make_range(model_ids_.begin(), model_ids_.end()); } -TechnologyLibrary::technology_variation_range TechnologyLibrary::variations() const { +TechnologyLibrary::technology_variation_range TechnologyLibrary::variations() + const { return vtr::make_range(variation_ids_.begin(), variation_ids_.end()); } -/* Find technology models in the same type (defined by users) and return a list of ids */ -std::vector TechnologyLibrary::models_by_type(const enum e_tech_lib_model_type& type) const { +/* Find technology models in the same type (defined by users) and return a list + * of ids */ +std::vector TechnologyLibrary::models_by_type( + const enum e_tech_lib_model_type& type) const { std::vector type_ids; for (auto id : models()) { /* Skip unmatched types */ @@ -42,10 +43,11 @@ std::vector TechnologyLibrary::models_by_type(const enum e_te * Public Accessors : Basic data query on technology models ***********************************************************************/ /* Access the name of a technology model */ -std::string TechnologyLibrary::model_name(const TechnologyModelId& model_id) const { +std::string TechnologyLibrary::model_name( + const TechnologyModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return model_names_[model_id]; + return model_names_[model_id]; } /* Access the id of a technology model by name, @@ -53,216 +55,235 @@ std::string TechnologyLibrary::model_name(const TechnologyModelId& model_id) con * Otherwise, return an invalid id */ TechnologyModelId TechnologyLibrary::model(const std::string& name) const { - std::map::const_iterator it = model_name2ids_.find(name); + std::map::const_iterator it = + model_name2ids_.find(name); if (it == model_name2ids_.end()) { return TechnologyModelId::INVALID(); } - return model_name2ids_.at(name); + return model_name2ids_.at(name); } /* Access the type of a technology model */ -enum e_tech_lib_model_type TechnologyLibrary::model_type(const TechnologyModelId& model_id) const { +enum e_tech_lib_model_type TechnologyLibrary::model_type( + const TechnologyModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return model_types_[model_id]; + return model_types_[model_id]; } /* Access the model type of a technology model */ -enum e_tech_lib_type TechnologyLibrary::model_lib_type(const TechnologyModelId& model_id) const { +enum e_tech_lib_type TechnologyLibrary::model_lib_type( + const TechnologyModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return model_lib_types_[model_id]; + return model_lib_types_[model_id]; } /* Access the process corner name of a technology model */ -std::string TechnologyLibrary::model_corner(const TechnologyModelId& model_id) const { +std::string TechnologyLibrary::model_corner( + const TechnologyModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return model_corners_[model_id]; + return model_corners_[model_id]; } /* Access the model reference name of a technology model */ -std::string TechnologyLibrary::model_ref(const TechnologyModelId& model_id) const { +std::string TechnologyLibrary::model_ref( + const TechnologyModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return model_refs_[model_id]; + return model_refs_[model_id]; } /* Access the path of library for a technology model */ -std::string TechnologyLibrary::model_lib_path(const TechnologyModelId& model_id) const { +std::string TechnologyLibrary::model_lib_path( + const TechnologyModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); - return model_lib_paths_[model_id]; + return model_lib_paths_[model_id]; } /* Access the VDD of a technology model - * Note: This is ONLY applicable to transistor model + * Note: This is ONLY applicable to transistor model */ float TechnologyLibrary::model_vdd(const TechnologyModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* This is only applicable to transistor model */ VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id)); - return model_vdds_[model_id]; + return model_vdds_[model_id]; } /* Access the width ratio between PMOS and NMOS for a technology model - * Note: This is ONLY applicable to transistor model + * Note: This is ONLY applicable to transistor model */ -float TechnologyLibrary::model_pn_ratio(const TechnologyModelId& model_id) const { +float TechnologyLibrary::model_pn_ratio( + const TechnologyModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* This is only applicable to transistor model */ VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id)); - return model_pn_ratios_[model_id]; + return model_pn_ratios_[model_id]; } /************************************************************************ * Public Accessors : Basic data query on transistors ***********************************************************************/ -/* Access the model name of a transistor (either PMOS or NMOS) for a technology model - * Note: This is ONLY applicable to transistor model +/* Access the model name of a transistor (either PMOS or NMOS) for a technology + * model Note: This is ONLY applicable to transistor model */ -std::string TechnologyLibrary::transistor_model_name(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type) const { +std::string TechnologyLibrary::transistor_model_name( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* This is only applicable to transistor model */ VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id)); - return transistor_model_names_[model_id][transistor_type]; + return transistor_model_names_[model_id][transistor_type]; } -/* Access the channel length of a transistor (either PMOS or NMOS) for a technology model - * Note: This is ONLY applicable to transistor model +/* Access the channel length of a transistor (either PMOS or NMOS) for a + * technology model Note: This is ONLY applicable to transistor model */ -float TechnologyLibrary::transistor_model_chan_length(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type) const { +float TechnologyLibrary::transistor_model_chan_length( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* This is only applicable to transistor model */ VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id)); - return transistor_model_chan_lengths_[model_id][transistor_type]; + return transistor_model_chan_lengths_[model_id][transistor_type]; } -/* Access the minimum width of a transistor (either PMOS or NMOS) for a technology model - * Note: This is ONLY applicable to transistor model +/* Access the minimum width of a transistor (either PMOS or NMOS) for a + * technology model Note: This is ONLY applicable to transistor model */ -float TechnologyLibrary::transistor_model_min_width(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type) const { +float TechnologyLibrary::transistor_model_min_width( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* This is only applicable to transistor model */ VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id)); - return transistor_model_min_widths_[model_id][transistor_type]; + return transistor_model_min_widths_[model_id][transistor_type]; } -/* Access the maximum width of a transistor (either PMOS or NMOS) for a technology model - * Note: This is ONLY applicable to transistor model +/* Access the maximum width of a transistor (either PMOS or NMOS) for a + * technology model Note: This is ONLY applicable to transistor model */ -float TechnologyLibrary::transistor_model_max_width(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type) const { +float TechnologyLibrary::transistor_model_max_width( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* This is only applicable to transistor model */ VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id)); - return transistor_model_max_widths_[model_id][transistor_type]; + return transistor_model_max_widths_[model_id][transistor_type]; } -/* Access the minimum width of a transistor (either PMOS or NMOS) for a technology model - * Note: This is ONLY applicable to transistor model +/* Access the minimum width of a transistor (either PMOS or NMOS) for a + * technology model Note: This is ONLY applicable to transistor model */ -TechnologyVariationId TechnologyLibrary::transistor_model_variation(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type) const { +TechnologyVariationId TechnologyLibrary::transistor_model_variation( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* This is only applicable to transistor model */ VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id)); - return transistor_model_variation_ids_[model_id][transistor_type]; + return transistor_model_variation_ids_[model_id][transistor_type]; } /************************************************************************ * Public Accessors : Basic data query on RRAM models ***********************************************************************/ /* Access the Low Resistence of a RRAM for a technology model - * Note: This is ONLY applicable to RRAM model + * Note: This is ONLY applicable to RRAM model */ float TechnologyLibrary::rram_rlrs(const TechnologyModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* This is only applicable to transistor model */ VTR_ASSERT(TECH_LIB_MODEL_RRAM == model_type(model_id)); - return rram_resistances_[model_id].x(); + return rram_resistances_[model_id].x(); } /* Access the High Resistence of a RRAM for a technology model - * Note: This is ONLY applicable to RRAM model + * Note: This is ONLY applicable to RRAM model */ float TechnologyLibrary::rram_rhrs(const TechnologyModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* This is only applicable to transistor model */ VTR_ASSERT(TECH_LIB_MODEL_RRAM == model_type(model_id)); - return rram_resistances_[model_id].y(); + return rram_resistances_[model_id].y(); } /* Access the Variation id of a RRAM for a technology model - * Note: This is ONLY applicable to RRAM model + * Note: This is ONLY applicable to RRAM model */ -TechnologyVariationId TechnologyLibrary::rram_variation(const TechnologyModelId& model_id) const { +TechnologyVariationId TechnologyLibrary::rram_variation( + const TechnologyModelId& model_id) const { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* This is only applicable to RRAM model */ VTR_ASSERT(TECH_LIB_MODEL_RRAM == model_type(model_id)); - return rram_variation_ids_[model_id]; + return rram_variation_ids_[model_id]; } /************************************************************************ * Public Accessors : Basic data query on technology variations ***********************************************************************/ /* Access the name of a technology variation */ -std::string TechnologyLibrary::variation_name(const TechnologyVariationId& variation_id) const { +std::string TechnologyLibrary::variation_name( + const TechnologyVariationId& variation_id) const { /* validate the variation_id */ VTR_ASSERT(valid_variation_id(variation_id)); - return variation_names_[variation_id]; + return variation_names_[variation_id]; } /* Access the id of a technology variation by name * If the name is valid, we return a valid id * Otherwise, return an invalid id */ -TechnologyVariationId TechnologyLibrary::variation(const std::string& name) const { - std::map::const_iterator it = variation_name2ids_.find(name); +TechnologyVariationId TechnologyLibrary::variation( + const std::string& name) const { + std::map::const_iterator it = + variation_name2ids_.find(name); if (it != variation_name2ids_.end()) { return TechnologyVariationId::INVALID(); } - return variation_name2ids_.at(name); + return variation_name2ids_.at(name); } /* Access the abs value of a technology variation */ -float TechnologyLibrary::variation_abs_value(const TechnologyVariationId& variation_id) const { +float TechnologyLibrary::variation_abs_value( + const TechnologyVariationId& variation_id) const { /* validate the variation_id */ VTR_ASSERT(valid_variation_id(variation_id)); - return variation_abs_values_[variation_id]; + return variation_abs_values_[variation_id]; } /* Access the abs value of a technology variation */ -size_t TechnologyLibrary::variation_num_sigma(const TechnologyVariationId& variation_id) const { +size_t TechnologyLibrary::variation_num_sigma( + const TechnologyVariationId& variation_id) const { /* validate the variation_id */ VTR_ASSERT(valid_variation_id(variation_id)); - return variation_num_sigmas_[variation_id]; + return variation_num_sigmas_[variation_id]; } /************************************************************************ * Public Mutators: model-related ***********************************************************************/ -/* Add a new model to the library, return an id - * This function will check if the name has already been used inside the data structure. - * If used, it will return an invalid id +/* Add a new model to the library, return an id + * This function will check if the name has already been used inside the data + * structure. If used, it will return an invalid id */ TechnologyModelId TechnologyLibrary::add_model(const std::string& name) { - std::map::iterator it = model_name2ids_.find(name); + std::map::iterator it = + model_name2ids_.find(name); if (it != model_name2ids_.end()) { return TechnologyModelId::INVALID(); } @@ -284,7 +305,9 @@ TechnologyModelId TechnologyLibrary::add_model(const std::string& name) { transistor_model_min_widths_.emplace_back(); transistor_model_max_widths_.emplace_back(); transistor_model_variation_names_.emplace_back(); - transistor_model_variation_ids_.push_back(std::array{TechnologyVariationId::INVALID(), TechnologyVariationId::INVALID()}); + transistor_model_variation_ids_.push_back( + std::array{TechnologyVariationId::INVALID(), + TechnologyVariationId::INVALID()}); rram_resistances_.emplace_back(); rram_variation_names_.emplace_back(); @@ -292,13 +315,13 @@ TechnologyModelId TechnologyLibrary::add_model(const std::string& name) { /* Register in the name-to-id map */ model_name2ids_[name] = model; - + return model; } /* Set the model type of a model in the library */ -void TechnologyLibrary::set_model_type(const TechnologyModelId& model_id, - const e_tech_lib_model_type& type) { +void TechnologyLibrary::set_model_type(const TechnologyModelId& model_id, + const e_tech_lib_model_type& type) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); model_types_[model_id] = type; @@ -306,8 +329,8 @@ void TechnologyLibrary::set_model_type(const TechnologyModelId& model_id, } /* Set the model type of a device model in the library */ -void TechnologyLibrary::set_model_lib_type(const TechnologyModelId& model_id, - const e_tech_lib_type& model_lib_type) { +void TechnologyLibrary::set_model_lib_type( + const TechnologyModelId& model_id, const e_tech_lib_type& model_lib_type) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); model_lib_types_[model_id] = model_lib_type; @@ -315,8 +338,8 @@ void TechnologyLibrary::set_model_lib_type(const TechnologyModelId& model_id, } /* Set the process corner of a model in the library */ -void TechnologyLibrary::set_model_corner(const TechnologyModelId& model_id, - const std::string& corner) { +void TechnologyLibrary::set_model_corner(const TechnologyModelId& model_id, + const std::string& corner) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); model_corners_[model_id] = corner; @@ -324,7 +347,7 @@ void TechnologyLibrary::set_model_corner(const TechnologyModelId& model_id, } /* Set the string used to model reference of a model in the library */ -void TechnologyLibrary::set_model_ref(const TechnologyModelId& model_id, +void TechnologyLibrary::set_model_ref(const TechnologyModelId& model_id, const std::string& model_ref) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); @@ -333,7 +356,7 @@ void TechnologyLibrary::set_model_ref(const TechnologyModelId& model_id, } /* Set the library file path of a model in the library */ -void TechnologyLibrary::set_model_lib_path(const TechnologyModelId& model_id, +void TechnologyLibrary::set_model_lib_path(const TechnologyModelId& model_id, const std::string& lib_path) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); @@ -341,11 +364,11 @@ void TechnologyLibrary::set_model_lib_path(const TechnologyModelId& model_id, return; } -/* Set the operating voltage of a model in the library +/* Set the operating voltage of a model in the library * This is ONLY applicable to transistors */ -void TechnologyLibrary::set_model_vdd(const TechnologyModelId& model_id, - const float& vdd) { +void TechnologyLibrary::set_model_vdd(const TechnologyModelId& model_id, + const float& vdd) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id)); @@ -353,11 +376,11 @@ void TechnologyLibrary::set_model_vdd(const TechnologyModelId& model_id, return; } -/* Set the width ratio between PMOS and NMOS of a model in the library +/* Set the width ratio between PMOS and NMOS of a model in the library * This is ONLY applicable to transistors */ -void TechnologyLibrary::set_model_pn_ratio(const TechnologyModelId& model_id, - const float& pn_ratio) { +void TechnologyLibrary::set_model_pn_ratio(const TechnologyModelId& model_id, + const float& pn_ratio) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id)); @@ -368,12 +391,13 @@ void TechnologyLibrary::set_model_pn_ratio(const TechnologyModelId& model_id, /************************************************************************ * Public Mutators: transistor-related ***********************************************************************/ -/* Set the model name for either PMOS or NMOS of a model in the library +/* Set the model name for either PMOS or NMOS of a model in the library * This is ONLY applicable to transistors */ -void TechnologyLibrary::set_transistor_model_name(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type, - const std::string& model_name) { +void TechnologyLibrary::set_transistor_model_name( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type, + const std::string& model_name) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id)); @@ -381,12 +405,12 @@ void TechnologyLibrary::set_transistor_model_name(const TechnologyModelId& model return; } -/* Set the channel length for either PMOS or NMOS of a model in the library +/* Set the channel length for either PMOS or NMOS of a model in the library * This is ONLY applicable to transistors */ -void TechnologyLibrary::set_transistor_model_chan_length(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type, - const float& chan_length) { +void TechnologyLibrary::set_transistor_model_chan_length( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type, const float& chan_length) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id)); @@ -394,12 +418,12 @@ void TechnologyLibrary::set_transistor_model_chan_length(const TechnologyModelId return; } -/* Set the minimum width for either PMOS or NMOS of a model in the library +/* Set the minimum width for either PMOS or NMOS of a model in the library * This is ONLY applicable to transistors */ -void TechnologyLibrary::set_transistor_model_min_width(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type, - const float& min_width) { +void TechnologyLibrary::set_transistor_model_min_width( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type, const float& min_width) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id)); @@ -407,12 +431,12 @@ void TechnologyLibrary::set_transistor_model_min_width(const TechnologyModelId& return; } -/* Set the maximum width for either PMOS or NMOS of a model in the library +/* Set the maximum width for either PMOS or NMOS of a model in the library * This is ONLY applicable to transistors */ -void TechnologyLibrary::set_transistor_model_max_width(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type, - const float& max_width) { +void TechnologyLibrary::set_transistor_model_max_width( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type, const float& max_width) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id)); @@ -420,12 +444,13 @@ void TechnologyLibrary::set_transistor_model_max_width(const TechnologyModelId& return; } -/* Set the variation name for either PMOS or NMOS of a model in the library +/* Set the variation name for either PMOS or NMOS of a model in the library * This is ONLY applicable to transistors */ -void TechnologyLibrary::set_transistor_model_variation_name(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type, - const std::string& variation_name) { +void TechnologyLibrary::set_transistor_model_variation_name( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type, + const std::string& variation_name) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); VTR_ASSERT(TECH_LIB_MODEL_TRANSISTOR == model_type(model_id)); @@ -436,10 +461,10 @@ void TechnologyLibrary::set_transistor_model_variation_name(const TechnologyMode /************************************************************************ * Public Mutators: RRAM-related ***********************************************************************/ -/* Set the Low Resistance State (LRS) resistance for a RRAM model in the library +/* Set the Low Resistance State (LRS) resistance for a RRAM model in the library * This is ONLY applicable to RRAM models */ -void TechnologyLibrary::set_rram_rlrs(const TechnologyModelId& model_id, +void TechnologyLibrary::set_rram_rlrs(const TechnologyModelId& model_id, const float& rlrs) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); @@ -448,10 +473,10 @@ void TechnologyLibrary::set_rram_rlrs(const TechnologyModelId& model_id, return; } -/* Set the High Resistance State (HRS) resistance for a RRAM model in the library - * This is ONLY applicable to RRAM models +/* Set the High Resistance State (HRS) resistance for a RRAM model in the + * library This is ONLY applicable to RRAM models */ -void TechnologyLibrary::set_rram_rhrs(const TechnologyModelId& model_id, +void TechnologyLibrary::set_rram_rhrs(const TechnologyModelId& model_id, const float& rhrs) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); @@ -460,11 +485,11 @@ void TechnologyLibrary::set_rram_rhrs(const TechnologyModelId& model_id, return; } -/* Set the variation name for a RRAM model in the library +/* Set the variation name for a RRAM model in the library * This is ONLY applicable to RRAM models */ -void TechnologyLibrary::set_rram_variation_name(const TechnologyModelId& model_id, - const std::string& variation_name) { +void TechnologyLibrary::set_rram_variation_name( + const TechnologyModelId& model_id, const std::string& variation_name) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); VTR_ASSERT(TECH_LIB_MODEL_RRAM == model_type(model_id)); @@ -475,18 +500,21 @@ void TechnologyLibrary::set_rram_variation_name(const TechnologyModelId& model_i /************************************************************************ * Public Mutators: variation-related ***********************************************************************/ -/* Add a new variation to the library, return an id - * This function will check if the name has already been used inside the data structure. - * If used, it will return an invalid id +/* Add a new variation to the library, return an id + * This function will check if the name has already been used inside the data + * structure. If used, it will return an invalid id */ -TechnologyVariationId TechnologyLibrary::add_variation(const std::string& name) { - std::map::iterator it = variation_name2ids_.find(name); +TechnologyVariationId TechnologyLibrary::add_variation( + const std::string& name) { + std::map::iterator it = + variation_name2ids_.find(name); if (it != variation_name2ids_.end()) { return TechnologyVariationId::INVALID(); } /* This is a legal name. we can create a new id */ - TechnologyVariationId variation = TechnologyVariationId(variation_ids_.size()); + TechnologyVariationId variation = + TechnologyVariationId(variation_ids_.size()); variation_ids_.push_back(variation); variation_names_.push_back(name); variation_abs_values_.push_back(0.); @@ -494,12 +522,13 @@ TechnologyVariationId TechnologyLibrary::add_variation(const std::string& name) /* Register in the name-to-id map */ variation_name2ids_[name] = variation; - + return variation; } /* Set the absolute value of a variation */ -void TechnologyLibrary::set_variation_abs_value(const TechnologyVariationId& variation_id, const float& abs_value) { +void TechnologyLibrary::set_variation_abs_value( + const TechnologyVariationId& variation_id, const float& abs_value) { /* validate the variation_id */ VTR_ASSERT(valid_variation_id(variation_id)); variation_abs_values_[variation_id] = abs_value; @@ -507,7 +536,8 @@ void TechnologyLibrary::set_variation_abs_value(const TechnologyVariationId& var } /* Set the number of sigma of a variation */ -void TechnologyLibrary::set_variation_num_sigma(const TechnologyVariationId& variation_id, const size_t& num_sigma) { +void TechnologyLibrary::set_variation_num_sigma( + const TechnologyVariationId& variation_id, const size_t& num_sigma) { /* validate the variation_id */ VTR_ASSERT(valid_variation_id(variation_id)); variation_num_sigmas_[variation_id] = num_sigma; @@ -522,23 +552,29 @@ void TechnologyLibrary::set_variation_num_sigma(const TechnologyVariationId& var */ void TechnologyLibrary::link_models_to_variations() { for (const TechnologyModelId& model : models()) { - /* For transistors, find the variation name for each model and build a link */ + /* For transistors, find the variation name for each model and build a link + */ if (TECH_LIB_MODEL_TRANSISTOR == model_type(model)) { - /* PMOS transistor, if a variation name is specified, we try to build a link - * Otherwise, we assign any invalid id */ - const std::string& pmos_var_name = transistor_model_variation_names_[model][TECH_LIB_TRANSISTOR_PMOS]; - transistor_model_variation_ids_[model][TECH_LIB_TRANSISTOR_PMOS] = variation(pmos_var_name); + /* PMOS transistor, if a variation name is specified, we try to build a + * link Otherwise, we assign any invalid id */ + const std::string& pmos_var_name = + transistor_model_variation_names_[model][TECH_LIB_TRANSISTOR_PMOS]; + transistor_model_variation_ids_[model][TECH_LIB_TRANSISTOR_PMOS] = + variation(pmos_var_name); - /* NMOS transistor, if a variation name is specified, we try to build a link - * Otherwise, we assign any invalid id + /* NMOS transistor, if a variation name is specified, we try to build a + * link Otherwise, we assign any invalid id */ - const std::string& nmos_var_name = transistor_model_variation_names_[model][TECH_LIB_TRANSISTOR_NMOS]; - transistor_model_variation_ids_[model][TECH_LIB_TRANSISTOR_NMOS] = variation(nmos_var_name); + const std::string& nmos_var_name = + transistor_model_variation_names_[model][TECH_LIB_TRANSISTOR_NMOS]; + transistor_model_variation_ids_[model][TECH_LIB_TRANSISTOR_NMOS] = + variation(nmos_var_name); /* Finish for transistors, go to the next */ continue; - } + } - /* Reach here it means an RRAM model, we find the variation name and try to build a link */ + /* Reach here it means an RRAM model, we find the variation name and try to + * build a link */ VTR_ASSERT(TECH_LIB_MODEL_RRAM == model_type(model)); const std::string& rram_var_name = rram_variation_names_[model]; rram_variation_ids_[model] = variation(rram_var_name); @@ -547,13 +583,17 @@ void TechnologyLibrary::link_models_to_variations() { } /************************************************************************ - * Internal invalidators/validators + * Internal invalidators/validators ***********************************************************************/ /* Validators */ -bool TechnologyLibrary::valid_model_id(const TechnologyModelId& model_id) const { - return ( size_t(model_id) < model_ids_.size() ) && ( model_id == model_ids_[model_id] ); +bool TechnologyLibrary::valid_model_id( + const TechnologyModelId& model_id) const { + return (size_t(model_id) < model_ids_.size()) && + (model_id == model_ids_[model_id]); } -bool TechnologyLibrary::valid_variation_id(const TechnologyVariationId& variation_id) const { - return ( size_t(variation_id) < variation_ids_.size() ) && ( variation_id == variation_ids_[variation_id] ); +bool TechnologyLibrary::valid_variation_id( + const TechnologyVariationId& variation_id) const { + return (size_t(variation_id) < variation_ids_.size()) && + (variation_id == variation_ids_[variation_id]); } diff --git a/libs/libarchopenfpga/src/technology_library.h b/libs/libarchopenfpga/src/technology_library.h index ba90eff1d..501bc7fb7 100644 --- a/libs/libarchopenfpga/src/technology_library.h +++ b/libs/libarchopenfpga/src/technology_library.h @@ -4,24 +4,23 @@ /******************************************************************** * This file include the declaration of technology library *******************************************************************/ -#include -#include #include +#include +#include /* Headers from vtrutil library */ -#include "vtr_vector.h" -#include "vtr_geometry.h" - #include "technology_library_fwd.h" +#include "vtr_geometry.h" +#include "vtr_vector.h" /******************************************************************** * Types for technology library attributes - * Industrial library: the .lib file which define technology + * Industrial library: the .lib file which define technology * This is ubiquitous in commercial vendors * For industry library, we allow users to define * process corners. - * Academia library: the .pm file which define technology - * This is mainly used in PTM-like technology library + * Academia library: the .pm file which define technology + * This is mainly used in PTM-like technology library * PTM is the Predictive Technology Model provided by the Arizona * State University (ASU). Available at ptm.asu.edu *******************************************************************/ @@ -31,33 +30,36 @@ enum e_tech_lib_type { NUM_TECH_LIB_TYPES }; /* Strings correspond to each technology library type */ -constexpr std::array TECH_LIB_TYPE_STRING = {{"industry", "academia"}}; +constexpr std::array TECH_LIB_TYPE_STRING = { + {"industry", "academia"}}; /******************************************************************** * Types of model which may be defined in a technology library - * 1. transistor + * 1. transistor * 2. RRAM *******************************************************************/ enum e_tech_lib_model_type { - TECH_LIB_MODEL_TRANSISTOR, - TECH_LIB_MODEL_RRAM, + TECH_LIB_MODEL_TRANSISTOR, + TECH_LIB_MODEL_RRAM, NUM_TECH_LIB_MODEL_TYPES }; /* Strings correspond to transistor type */ -constexpr std::array TECH_LIB_MODEL_TYPE_STRING = {{"transistor", "rram"}}; +constexpr std::array + TECH_LIB_MODEL_TYPE_STRING = {{"transistor", "rram"}}; /******************************************************************** * Types of transistors which may be defined in a technology library - * 1. NMOS transistor - * 2. PMOS transistor + * 1. NMOS transistor + * 2. PMOS transistor *******************************************************************/ enum e_tech_lib_transistor_type { - TECH_LIB_TRANSISTOR_PMOS, - TECH_LIB_TRANSISTOR_NMOS, + TECH_LIB_TRANSISTOR_PMOS, + TECH_LIB_TRANSISTOR_NMOS, NUM_TECH_LIB_TRANSISTOR_TYPES }; /* Strings correspond to transistor type */ -constexpr std::array TECH_LIB_TRANSISTOR_TYPE_STRING = {{"pmos", "nmos"}}; +constexpr std::array + TECH_LIB_TRANSISTOR_TYPE_STRING = {{"pmos", "nmos"}}; /******************************************************************** * A data structure to describe technology library @@ -72,214 +74,247 @@ constexpr std::array TECH_LIB_TRANSI * *******************************************************************/ class TechnologyLibrary { - public: /* Types */ - typedef vtr::vector::const_iterator technology_model_iterator; - typedef vtr::vector::const_iterator technology_variation_iterator; - /* Create range */ - typedef vtr::Range technology_model_range; - typedef vtr::Range technology_variation_range; - public: /* Constructors */ - TechnologyLibrary(); - public: /* Accessors: aggregates */ - technology_model_range models() const; - technology_variation_range variations() const; - std::vector models_by_type(const enum e_tech_lib_model_type& type) const; - public: /* Public Accessors: Basic data query on models */ - std::string model_name(const TechnologyModelId& model_id) const; - TechnologyModelId model(const std::string& name) const; - enum e_tech_lib_model_type model_type(const TechnologyModelId& model_id) const; - enum e_tech_lib_type model_lib_type(const TechnologyModelId& model_id) const; - std::string model_corner(const TechnologyModelId& model_id) const; - std::string model_ref(const TechnologyModelId& model_id) const; - std::string model_lib_path(const TechnologyModelId& model_id) const; - float model_vdd(const TechnologyModelId& model_id) const; - float model_pn_ratio(const TechnologyModelId& model_id) const; - public: /* Public Accessors: Basic data query on transistors */ - std::string transistor_model_name(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type) const; - float transistor_model_chan_length(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type) const; - float transistor_model_min_width(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type) const; - float transistor_model_max_width(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type) const; - TechnologyVariationId transistor_model_variation(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type) const; - public: /* Public Accessors: Basic data query on RRAM models */ - float rram_rlrs(const TechnologyModelId& model_id) const; - float rram_rhrs(const TechnologyModelId& model_id) const; - TechnologyVariationId rram_variation(const TechnologyModelId& model_id) const; - public: /* Public Accessors: Basic data query on variations */ - std::string variation_name(const TechnologyVariationId& variation_id) const; - TechnologyVariationId variation(const std::string& name) const; - float variation_abs_value(const TechnologyVariationId& variation_id) const; - size_t variation_num_sigma(const TechnologyVariationId& variation_id) const; - public: /* Public Mutators: model-related */ - TechnologyModelId add_model(const std::string& name); - void set_model_type(const TechnologyModelId& model_id, - const e_tech_lib_model_type& type); - void set_model_lib_type(const TechnologyModelId& model_id, - const e_tech_lib_type& lib_type); - void set_model_corner(const TechnologyModelId& model_id, - const std::string& corner); - void set_model_ref(const TechnologyModelId& model_id, - const std::string& model_ref); - void set_model_lib_path(const TechnologyModelId& model_id, - const std::string& lib_path); - void set_model_vdd(const TechnologyModelId& model_id, - const float& vdd); - void set_model_pn_ratio(const TechnologyModelId& model_id, - const float& pn_ratio); - public: /* Public Mutators: transistor-related */ - void set_transistor_model_name(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type, - const std::string& model_name); - void set_transistor_model_chan_length(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type, - const float& chan_length); - void set_transistor_model_min_width(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type, - const float& min_width); - void set_transistor_model_max_width(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type, - const float& max_width); - void set_transistor_model_variation_name(const TechnologyModelId& model_id, - const e_tech_lib_transistor_type& transistor_type, - const std::string& variation_name); - public: /* Public Mutators: RRAM-related */ - void set_rram_rlrs(const TechnologyModelId& model_id, - const float& rlrs); - void set_rram_rhrs(const TechnologyModelId& model_id, - const float& rhrs); - void set_rram_variation_name(const TechnologyModelId& model_id, - const std::string& variation_name); - public: /* Public Mutators: variation-related */ - TechnologyVariationId add_variation(const std::string& name); - void set_variation_abs_value(const TechnologyVariationId& variation_id, const float& abs_value); - void set_variation_num_sigma(const TechnologyVariationId& variation_id, const size_t& num_sigma); - public: /* Public Mutators: linkers */ - void link_models_to_variations(); - public: /* Public invalidators/validators */ - bool valid_model_id(const TechnologyModelId& model_id) const; - bool valid_variation_id(const TechnologyVariationId& variation_id) const; - private: /* Internal data */ - /* Transistor-related fundamental information */ - /* Unique identifier for each model - * A model could be either transistors (1 pair of PMOS and NMOS) or RRAMs - */ - vtr::vector model_ids_; + public: /* Types */ + typedef vtr::vector::const_iterator + technology_model_iterator; + typedef vtr::vector::const_iterator + technology_variation_iterator; + /* Create range */ + typedef vtr::Range technology_model_range; + typedef vtr::Range technology_variation_range; - /* Unique name for each model. This is defined by XML file */ - vtr::vector model_names_; + public: /* Constructors */ + TechnologyLibrary(); - /* Type of each model, either transistors or RRAMs */ - vtr::vector model_types_; + public: /* Accessors: aggregates */ + technology_model_range models() const; + technology_variation_range variations() const; + std::vector models_by_type( + const enum e_tech_lib_model_type& type) const; - /* Type of models of each model, either industry or academia - * This will lead to different ways when include these models - * For industry models, we use .lib to include library - * For academia models, we use .include to include library - */ - vtr::vector model_lib_types_; + public: /* Public Accessors: Basic data query on models */ + std::string model_name(const TechnologyModelId& model_id) const; + TechnologyModelId model(const std::string& name) const; + enum e_tech_lib_model_type model_type( + const TechnologyModelId& model_id) const; + enum e_tech_lib_type model_lib_type(const TechnologyModelId& model_id) const; + std::string model_corner(const TechnologyModelId& model_id) const; + std::string model_ref(const TechnologyModelId& model_id) const; + std::string model_lib_path(const TechnologyModelId& model_id) const; + float model_vdd(const TechnologyModelId& model_id) const; + float model_pn_ratio(const TechnologyModelId& model_id) const; - /* Name of process corner to be used for each model - * Users can define any string for the process corner they are going to use - * But the corner name should be consistent with their library files - * When this is enabled, the corner name will be added when - * include the models - * For example, for a industry model, .lib - */ - vtr::vector model_corners_; + public: /* Public Accessors: Basic data query on transistors */ + std::string transistor_model_name( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type) const; + float transistor_model_chan_length( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type) const; + float transistor_model_min_width( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type) const; + float transistor_model_max_width( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type) const; + TechnologyVariationId transistor_model_variation( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type) const; - /* The string used to instanciate the model models - * This will really depend on the type of models - * For most industry models, we can use 'M' to instanciate a transisitor - * For some academia models, we have to use 'X' to do so - */ - vtr::vector model_refs_; + public: /* Public Accessors: Basic data query on RRAM models */ + float rram_rlrs(const TechnologyModelId& model_id) const; + float rram_rhrs(const TechnologyModelId& model_id) const; + TechnologyVariationId rram_variation(const TechnologyModelId& model_id) const; - /* The path to the transistor models - * This is going to be the when include the library files - * See the example in the comments about process corner - */ - vtr::vector model_lib_paths_; + public: /* Public Accessors: Basic data query on variations */ + std::string variation_name(const TechnologyVariationId& variation_id) const; + TechnologyVariationId variation(const std::string& name) const; + float variation_abs_value(const TechnologyVariationId& variation_id) const; + size_t variation_num_sigma(const TechnologyVariationId& variation_id) const; - /* Operating voltage for the models. Unit: [V] */ - vtr::vector model_vdds_; + public: /* Public Mutators: model-related */ + TechnologyModelId add_model(const std::string& name); + void set_model_type(const TechnologyModelId& model_id, + const e_tech_lib_model_type& type); + void set_model_lib_type(const TechnologyModelId& model_id, + const e_tech_lib_type& lib_type); + void set_model_corner(const TechnologyModelId& model_id, + const std::string& corner); + void set_model_ref(const TechnologyModelId& model_id, + const std::string& model_ref); + void set_model_lib_path(const TechnologyModelId& model_id, + const std::string& lib_path); + void set_model_vdd(const TechnologyModelId& model_id, const float& vdd); + void set_model_pn_ratio(const TechnologyModelId& model_id, + const float& pn_ratio); - /* The width ratio between PMOS and NMOS for a model group - * This really depend the transistor technology - * We recommend users to characterize driving strengths of - * PMOS and NMOS using SPICE simulators - */ - vtr::vector model_pn_ratios_; + public: /* Public Mutators: transistor-related */ + void set_transistor_model_name( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type, + const std::string& model_name); + void set_transistor_model_chan_length( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type, + const float& chan_length); + void set_transistor_model_min_width( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type, const float& min_width); + void set_transistor_model_max_width( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type, const float& max_width); + void set_transistor_model_variation_name( + const TechnologyModelId& model_id, + const e_tech_lib_transistor_type& transistor_type, + const std::string& variation_name); - /* The model name is the name that is defined in your library file. - * For example, your NMOS transistor may be defined as - * .model nch - * in some BSIM models. In this case, nch will be the model name - * - * In the rest of these transistor-level parameters, we follow the same organization: - * PMOS data will be stored in the first element of the array - * NMOS data will be stored in the second element of the array - */ - vtr::vector> transistor_model_names_; + public: /* Public Mutators: RRAM-related */ + void set_rram_rlrs(const TechnologyModelId& model_id, const float& rlrs); + void set_rram_rhrs(const TechnologyModelId& model_id, const float& rhrs); + void set_rram_variation_name(const TechnologyModelId& model_id, + const std::string& variation_name); - /* The channel length of a transistor. - * This should be defined by your technology vendor - * For example, a 22nm technology, the channel length is around 22nm - */ - vtr::vector> transistor_model_chan_lengths_; + public: /* Public Mutators: variation-related */ + TechnologyVariationId add_variation(const std::string& name); + void set_variation_abs_value(const TechnologyVariationId& variation_id, + const float& abs_value); + void set_variation_num_sigma(const TechnologyVariationId& variation_id, + const size_t& num_sigma); - /* The minimum width of a transistor. - * This should be defined by your technology vendor - */ - vtr::vector> transistor_model_min_widths_; + public: /* Public Mutators: linkers */ + void link_models_to_variations(); - /* The maximum width of a transistor. - * This should be defined by your technology vendor - * The maximum width of a transistor will be used to size your transistors - * If the required width in circuit models in larger then the max width, - * multiple transistor bin will be instanciated. - * For FinFET, the maximum width should be the same as min_width - */ - vtr::vector> transistor_model_max_widths_; + public: /* Public invalidators/validators */ + bool valid_model_id(const TechnologyModelId& model_id) const; + bool valid_variation_id(const TechnologyVariationId& variation_id) const; - /* The variation name and id binded to PMOS and NMOS transistor - * We expect users to provide the exact name of variation defined in this technology library - * the name and id will be automatically matched by using function link_model_to_variation() - */ - vtr::vector> transistor_model_variation_names_; - vtr::vector> transistor_model_variation_ids_; + private: /* Internal data */ + /* Transistor-related fundamental information */ + /* Unique identifier for each model + * A model could be either transistors (1 pair of PMOS and NMOS) or RRAMs + */ + vtr::vector model_ids_; - /* ReRAM-related fundamental information: - * Low Resistance State (LRS) resistance will be stored in the x() part of vtr::Point - * High Resistance State (HRS) resistance will be stored in the y() part of vtr::Point - * Unit: [Ohm] - */ - vtr::vector> rram_resistances_; + /* Unique name for each model. This is defined by XML file */ + vtr::vector model_names_; - /* The variation name and id binded to this RRAM - * We expect users to provide the exact name of variation defined in this technology library - * the name and id will be automatically matched by using function link_model_to_variation() - */ - vtr::vector rram_variation_names_; - vtr::vector rram_variation_ids_; - - /* Unique identifier for each process variation */ - vtr::vector variation_ids_; - vtr::vector variation_names_; - - /* Absoluate and standard deviation of a process variation - * These are used to apply manual process variations - * in case your technology vender does not provide any - */ - vtr::vector variation_abs_values_; - vtr::vector variation_num_sigmas_; + /* Type of each model, either transistors or RRAMs */ + vtr::vector model_types_; - /* Fast name-to-id lookup */ - std::map model_name2ids_; - std::map variation_name2ids_; + /* Type of models of each model, either industry or academia + * This will lead to different ways when include these models + * For industry models, we use .lib to include library + * For academia models, we use .include to include library + */ + vtr::vector model_lib_types_; + + /* Name of process corner to be used for each model + * Users can define any string for the process corner they are going to use + * But the corner name should be consistent with their library files + * When this is enabled, the corner name will be added when + * include the models + * For example, for a industry model, .lib + */ + vtr::vector model_corners_; + + /* The string used to instanciate the model models + * This will really depend on the type of models + * For most industry models, we can use 'M' to instanciate a transisitor + * For some academia models, we have to use 'X' to do so + */ + vtr::vector model_refs_; + + /* The path to the transistor models + * This is going to be the when include the library files + * See the example in the comments about process corner + */ + vtr::vector model_lib_paths_; + + /* Operating voltage for the models. Unit: [V] */ + vtr::vector model_vdds_; + + /* The width ratio between PMOS and NMOS for a model group + * This really depend the transistor technology + * We recommend users to characterize driving strengths of + * PMOS and NMOS using SPICE simulators + */ + vtr::vector model_pn_ratios_; + + /* The model name is the name that is defined in your library file. + * For example, your NMOS transistor may be defined as + * .model nch + * in some BSIM models. In this case, nch will be the model name + * + * In the rest of these transistor-level parameters, we follow the same + * organization: PMOS data will be stored in the first element of the array + * NMOS data will be stored in the second element of the array + */ + vtr::vector> + transistor_model_names_; + + /* The channel length of a transistor. + * This should be defined by your technology vendor + * For example, a 22nm technology, the channel length is around 22nm + */ + vtr::vector> + transistor_model_chan_lengths_; + + /* The minimum width of a transistor. + * This should be defined by your technology vendor + */ + vtr::vector> + transistor_model_min_widths_; + + /* The maximum width of a transistor. + * This should be defined by your technology vendor + * The maximum width of a transistor will be used to size your transistors + * If the required width in circuit models in larger then the max width, + * multiple transistor bin will be instanciated. + * For FinFET, the maximum width should be the same as min_width + */ + vtr::vector> + transistor_model_max_widths_; + + /* The variation name and id binded to PMOS and NMOS transistor + * We expect users to provide the exact name of variation defined in this + * technology library the name and id will be automatically matched by using + * function link_model_to_variation() + */ + vtr::vector> + transistor_model_variation_names_; + vtr::vector> + transistor_model_variation_ids_; + + /* ReRAM-related fundamental information: + * Low Resistance State (LRS) resistance will be stored in the x() part of + * vtr::Point High Resistance State (HRS) resistance will be stored in the y() + * part of vtr::Point Unit: [Ohm] + */ + vtr::vector> rram_resistances_; + + /* The variation name and id binded to this RRAM + * We expect users to provide the exact name of variation defined in this + * technology library the name and id will be automatically matched by using + * function link_model_to_variation() + */ + vtr::vector rram_variation_names_; + vtr::vector rram_variation_ids_; + + /* Unique identifier for each process variation */ + vtr::vector variation_ids_; + vtr::vector variation_names_; + + /* Absoluate and standard deviation of a process variation + * These are used to apply manual process variations + * in case your technology vender does not provide any + */ + vtr::vector variation_abs_values_; + vtr::vector variation_num_sigmas_; + + /* Fast name-to-id lookup */ + std::map model_name2ids_; + std::map variation_name2ids_; }; #endif diff --git a/libs/libarchopenfpga/src/technology_library_fwd.h b/libs/libarchopenfpga/src/technology_library_fwd.h index b222fab1d..2ced07d29 100644 --- a/libs/libarchopenfpga/src/technology_library_fwd.h +++ b/libs/libarchopenfpga/src/technology_library_fwd.h @@ -1,11 +1,11 @@ /************************************************************************ - * A header file for TechnologyLibrary class, including critical data declaration - * Please include this file only for using any TechnologyLibrary data structure - * Refer to circuit_library.h for more details + * A header file for TechnologyLibrary class, including critical data + *declaration Please include this file only for using any TechnologyLibrary data + *structure Refer to circuit_library.h for more details ***********************************************************************/ /************************************************************************ - * Create strong id for TechnologyDevice to avoid illegal type casting + * Create strong id for TechnologyDevice to avoid illegal type casting ***********************************************************************/ #ifndef TECHNOLOGY_LIBRARY_FWD_H #define TECHNOLOGY_LIBRARY_FWD_H diff --git a/libs/libarchopenfpga/src/tile_annotation.cpp b/libs/libarchopenfpga/src/tile_annotation.cpp index a1268aefa..cf8712ab8 100644 --- a/libs/libarchopenfpga/src/tile_annotation.cpp +++ b/libs/libarchopenfpga/src/tile_annotation.cpp @@ -1,19 +1,17 @@ /************************************************************************ * Member functions for class TileAnnotation ***********************************************************************/ -#include "vtr_assert.h" - #include "tile_annotation.h" +#include "vtr_assert.h" + /* namespace openfpga begins */ namespace openfpga { /************************************************************************ * Constructors ***********************************************************************/ -TileAnnotation::TileAnnotation() { - return; -} +TileAnnotation::TileAnnotation() { return; } /************************************************************************ * Public Accessors : aggregates @@ -25,42 +23,50 @@ TileAnnotation::global_port_range TileAnnotation::global_ports() const { /************************************************************************ * Public Accessors ***********************************************************************/ -std::string TileAnnotation::global_port_name(const TileGlobalPortId& global_port_id) const { +std::string TileAnnotation::global_port_name( + const TileGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_names_[global_port_id]; } -std::vector TileAnnotation::global_port_tile_names(const TileGlobalPortId& global_port_id) const { +std::vector TileAnnotation::global_port_tile_names( + const TileGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_tile_names_[global_port_id]; } -std::vector TileAnnotation::global_port_tile_ports(const TileGlobalPortId& global_port_id) const { +std::vector TileAnnotation::global_port_tile_ports( + const TileGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_tile_ports_[global_port_id]; } -std::vector> TileAnnotation::global_port_tile_coordinates(const TileGlobalPortId& global_port_id) const { +std::vector> TileAnnotation::global_port_tile_coordinates( + const TileGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_tile_coordinates_[global_port_id]; } -bool TileAnnotation::global_port_is_clock(const TileGlobalPortId& global_port_id) const { +bool TileAnnotation::global_port_is_clock( + const TileGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_is_clock_[global_port_id]; } -bool TileAnnotation::global_port_is_set(const TileGlobalPortId& global_port_id) const { +bool TileAnnotation::global_port_is_set( + const TileGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_is_set_[global_port_id]; } -bool TileAnnotation::global_port_is_reset(const TileGlobalPortId& global_port_id) const { +bool TileAnnotation::global_port_is_reset( + const TileGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_is_reset_[global_port_id]; } -size_t TileAnnotation::global_port_default_value(const TileGlobalPortId& global_port_id) const { +size_t TileAnnotation::global_port_default_value( + const TileGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_default_values_[global_port_id]; } @@ -68,9 +74,11 @@ size_t TileAnnotation::global_port_default_value(const TileGlobalPortId& global_ /************************************************************************ * Public Mutators ***********************************************************************/ -TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name) { +TileGlobalPortId TileAnnotation::create_global_port( + const std::string& port_name) { /* Ensure that the name is unique */ - std::map::iterator it = global_port_name2ids_.find(port_name); + std::map::iterator it = + global_port_name2ids_.find(port_name); if (it != global_port_name2ids_.end()) { return TileGlobalPortId::INVALID(); } @@ -93,49 +101,51 @@ TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name return port_id; } -void TileAnnotation::add_global_port_tile_information(const TileGlobalPortId& global_port_id, - const std::string& tile_name, - const BasicPort& tile_port, - const vtr::Point& tile_coord) { +void TileAnnotation::add_global_port_tile_information( + const TileGlobalPortId& global_port_id, const std::string& tile_name, + const BasicPort& tile_port, const vtr::Point& tile_coord) { VTR_ASSERT(valid_global_port_id(global_port_id)); global_port_tile_names_[global_port_id].push_back(tile_name); global_port_tile_ports_[global_port_id].push_back(tile_port); global_port_tile_coordinates_[global_port_id].push_back(tile_coord); } -void TileAnnotation::set_global_port_is_clock(const TileGlobalPortId& global_port_id, - const bool& is_clock) { +void TileAnnotation::set_global_port_is_clock( + const TileGlobalPortId& global_port_id, const bool& is_clock) { VTR_ASSERT(valid_global_port_id(global_port_id)); global_port_is_clock_[global_port_id] = is_clock; } -void TileAnnotation::set_global_port_is_set(const TileGlobalPortId& global_port_id, - const bool& is_set) { +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)); global_port_is_set_[global_port_id] = is_set; } -void TileAnnotation::set_global_port_is_reset(const TileGlobalPortId& global_port_id, - const bool& is_reset) { +void TileAnnotation::set_global_port_is_reset( + const TileGlobalPortId& global_port_id, const bool& is_reset) { VTR_ASSERT(valid_global_port_id(global_port_id)); global_port_is_reset_[global_port_id] = is_reset; } -void TileAnnotation::set_global_port_default_value(const TileGlobalPortId& global_port_id, - const size_t& default_value) { +void TileAnnotation::set_global_port_default_value( + const TileGlobalPortId& global_port_id, const size_t& default_value) { VTR_ASSERT(valid_global_port_id(global_port_id)); global_port_default_values_[global_port_id] = default_value; } /************************************************************************ - * Internal invalidators/validators + * Internal invalidators/validators ***********************************************************************/ /* Validators */ -bool TileAnnotation::valid_global_port_id(const TileGlobalPortId& global_port_id) const { - return ( size_t(global_port_id) < global_port_ids_.size() ) && ( global_port_id == global_port_ids_[global_port_id] ); +bool TileAnnotation::valid_global_port_id( + const TileGlobalPortId& global_port_id) const { + return (size_t(global_port_id) < global_port_ids_.size()) && + (global_port_id == global_port_ids_[global_port_id]); } -bool TileAnnotation::valid_global_port_attributes(const TileGlobalPortId& global_port_id) const { +bool TileAnnotation::valid_global_port_attributes( + const TileGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); int attribute_counter = 0; @@ -155,4 +165,4 @@ bool TileAnnotation::valid_global_port_attributes(const TileGlobalPortId& global return ((0 == attribute_counter) || (1 == attribute_counter)); } -} /* namespace openfpga ends */ +} // namespace openfpga diff --git a/libs/libarchopenfpga/src/tile_annotation.h b/libs/libarchopenfpga/src/tile_annotation.h index 1f863d1ac..bf699be53 100644 --- a/libs/libarchopenfpga/src/tile_annotation.h +++ b/libs/libarchopenfpga/src/tile_annotation.h @@ -4,16 +4,14 @@ /******************************************************************** * Include header files required by the data structure definition *******************************************************************/ -#include -#include #include - -#include "vtr_vector.h" -#include "vtr_geometry.h" +#include +#include #include "openfpga_port.h" - #include "tile_annotation_fwd.h" +#include "vtr_geometry.h" +#include "vtr_vector.h" /* namespace openfpga begins */ namespace openfpga { @@ -21,7 +19,7 @@ namespace openfpga { /******************************************************************** * This file include the declaration of data structures * to store physical tile annotation, including - * 1. global port definition where a tile port can be treated as a + * 1. global port definition where a tile port can be treated as a * global port of the FPGA fabric * * Note: @@ -30,63 +28,77 @@ namespace openfpga { * to other data structures, please create another one in other header files *******************************************************************/ class TileAnnotation { - public: /* Types */ - typedef vtr::vector::const_iterator global_port_iterator; - /* Create range */ - typedef vtr::Range global_port_range; - public: /* Constructor */ - TileAnnotation(); - public: /* Public accessors: aggregators */ - global_port_range global_ports() const; - public: /* Public accessors */ - std::string global_port_name(const TileGlobalPortId& global_port_id) const; - std::vector global_port_tile_names(const TileGlobalPortId& global_port_id) const; - std::vector global_port_tile_ports(const TileGlobalPortId& global_port_id) const; - std::vector> global_port_tile_coordinates(const TileGlobalPortId& global_port_id) const; - 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; - size_t global_port_default_value(const TileGlobalPortId& global_port_id) const; - public: /* Public mutators */ - /* By default, we do not set it as a clock. - * Users should set it through the set_global_port_is_clock() function - */ - TileGlobalPortId create_global_port(const std::string& port_name); - /* Add tile port information */ - void add_global_port_tile_information(const TileGlobalPortId& global_port_id, - const std::string& tile_name, - const BasicPort& tile_port, - const vtr::Point& tile_coord); - void set_global_port_is_clock(const TileGlobalPortId& global_port_id, - const bool& is_clock); - 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, - const bool& is_reset); - void set_global_port_default_value(const TileGlobalPortId& global_port_id, - const size_t& default_value); - public: /* Public validator */ - bool valid_global_port_id(const TileGlobalPortId& global_port_id) const; - /* Validate attributes of a given global port - * - A port can only be defined as clock or set or reset - */ - bool valid_global_port_attributes(const TileGlobalPortId& global_port_id) const; - private: /* Internal data */ - /* Global port information for tiles */ - vtr::vector global_port_ids_; - vtr::vector global_port_names_; - vtr::vector> global_port_tile_names_; - vtr::vector>> global_port_tile_coordinates_; - vtr::vector> global_port_tile_ports_; - vtr::vector global_port_is_clock_; - vtr::vector global_port_is_reset_; - vtr::vector global_port_is_set_; - vtr::vector global_port_default_values_; + public: /* Types */ + typedef vtr::vector::const_iterator + global_port_iterator; + /* Create range */ + typedef vtr::Range global_port_range; - /* A fast lookup for port names */ - std::map global_port_name2ids_; + public: /* Constructor */ + TileAnnotation(); + + public: /* Public accessors: aggregators */ + global_port_range global_ports() const; + + public: /* Public accessors */ + std::string global_port_name(const TileGlobalPortId& global_port_id) const; + std::vector global_port_tile_names( + const TileGlobalPortId& global_port_id) const; + std::vector global_port_tile_ports( + const TileGlobalPortId& global_port_id) const; + std::vector> global_port_tile_coordinates( + const TileGlobalPortId& global_port_id) const; + 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; + size_t global_port_default_value( + const TileGlobalPortId& global_port_id) const; + + public: /* Public mutators */ + /* By default, we do not set it as a clock. + * Users should set it through the set_global_port_is_clock() function + */ + TileGlobalPortId create_global_port(const std::string& port_name); + /* Add tile port information */ + void add_global_port_tile_information(const TileGlobalPortId& global_port_id, + const std::string& tile_name, + const BasicPort& tile_port, + const vtr::Point& tile_coord); + void set_global_port_is_clock(const TileGlobalPortId& global_port_id, + const bool& is_clock); + 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, + const bool& is_reset); + void set_global_port_default_value(const TileGlobalPortId& global_port_id, + const size_t& default_value); + + public: /* Public validator */ + bool valid_global_port_id(const TileGlobalPortId& global_port_id) const; + /* Validate attributes of a given global port + * - A port can only be defined as clock or set or reset + */ + bool valid_global_port_attributes( + const TileGlobalPortId& global_port_id) const; + + private: /* Internal data */ + /* Global port information for tiles */ + vtr::vector global_port_ids_; + vtr::vector global_port_names_; + vtr::vector> + global_port_tile_names_; + vtr::vector>> + global_port_tile_coordinates_; + vtr::vector> global_port_tile_ports_; + vtr::vector global_port_is_clock_; + vtr::vector global_port_is_reset_; + vtr::vector global_port_is_set_; + vtr::vector global_port_default_values_; + + /* A fast lookup for port names */ + std::map global_port_name2ids_; }; -} /* namespace openfpga ends */ +} // namespace openfpga #endif diff --git a/libs/libarchopenfpga/src/tile_annotation_fwd.h b/libs/libarchopenfpga/src/tile_annotation_fwd.h index 742b0ed52..a76086ba5 100644 --- a/libs/libarchopenfpga/src/tile_annotation_fwd.h +++ b/libs/libarchopenfpga/src/tile_annotation_fwd.h @@ -1,11 +1,11 @@ /************************************************************************ * A header file for TileAnnotation class, including critical data declaration * Please include this file only for using any TileAnnotation data structure - * Refer to tile_annotation.h for more details + * Refer to tile_annotation.h for more details ***********************************************************************/ /************************************************************************ - * Create strong id for tile global ports to avoid illegal type casting + * Create strong id for tile global ports to avoid illegal type casting ***********************************************************************/ #ifndef TILE_ANNOTATION_FWD_H #define TILE_ANNOTATION_FWD_H diff --git a/libs/libarchopenfpga/src/write_xml_bitstream_setting.cpp b/libs/libarchopenfpga/src/write_xml_bitstream_setting.cpp index 1754fbc4b..f9268e653 100644 --- a/libs/libarchopenfpga/src/write_xml_bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/write_xml_bitstream_setting.cpp @@ -2,33 +2,41 @@ * This file includes functions that outputs a bitstream setting to XML format *******************************************************************/ /* Headers from system goes first */ -#include #include +#include /* Headers from vtr util library */ +#include "openfpga_digest.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "openfpga_digest.h" /* Headers from readarchopenfpga library */ -#include "write_xml_utils.h" #include "write_xml_bitstream_setting.h" +#include "write_xml_utils.h" /******************************************************************** * Generate the full hierarchy name for a pb_type in bitstream setting *******************************************************************/ -static -std::string generate_bitstream_setting_pb_type_hierarchy_name(const openfpga::BitstreamSetting& bitstream_setting, - const BitstreamPbTypeSettingId& bitstream_pb_type_setting_id) { +static std::string generate_bitstream_setting_pb_type_hierarchy_name( + const openfpga::BitstreamSetting& bitstream_setting, + const BitstreamPbTypeSettingId& bitstream_pb_type_setting_id) { /* Iterate over the parent_pb_type and modes names, they should well match */ - VTR_ASSERT_SAFE(bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id).size() == bitstream_setting.parent_mode_names(bitstream_pb_type_setting_id).size()); + VTR_ASSERT_SAFE( + bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id) + .size() == + bitstream_setting.parent_mode_names(bitstream_pb_type_setting_id).size()); std::string hie_name; - for (size_t i = 0 ; i < bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id).size(); ++i) { - hie_name += bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id)[i]; + for (size_t i = 0; + i < bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id) + .size(); + ++i) { + hie_name += + bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id)[i]; hie_name += std::string("["); - hie_name += bitstream_setting.parent_mode_names(bitstream_pb_type_setting_id)[i]; + hie_name += + bitstream_setting.parent_mode_names(bitstream_pb_type_setting_id)[i]; hie_name += std::string("]"); hie_name += std::string("."); } @@ -42,18 +50,26 @@ std::string generate_bitstream_setting_pb_type_hierarchy_name(const openfpga::Bi /******************************************************************** * Generate the full hierarchy name for an interconnect in bitstream setting *******************************************************************/ -static -std::string generate_bitstream_setting_interconnect_hierarchy_name(const openfpga::BitstreamSetting& bitstream_setting, - const BitstreamInterconnectSettingId& bitstream_interc_setting_id) { +static std::string generate_bitstream_setting_interconnect_hierarchy_name( + const openfpga::BitstreamSetting& bitstream_setting, + const BitstreamInterconnectSettingId& bitstream_interc_setting_id) { /* Iterate over the parent_pb_type and modes names, they should well match */ - VTR_ASSERT_SAFE(bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id).size() == bitstream_setting.parent_mode_names(bitstream_interc_setting_id).size()); + VTR_ASSERT_SAFE( + bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id) + .size() == + bitstream_setting.parent_mode_names(bitstream_interc_setting_id).size()); std::string hie_name; - for (size_t i = 0 ; i < bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id).size(); ++i) { - hie_name += bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id)[i]; + for (size_t i = 0; + i < bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id) + .size(); + ++i) { + hie_name += + bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id)[i]; hie_name += std::string("["); - hie_name += bitstream_setting.parent_mode_names(bitstream_interc_setting_id)[i]; + hie_name += + bitstream_setting.parent_mode_names(bitstream_interc_setting_id)[i]; hie_name += std::string("]"); hie_name += std::string("."); } @@ -67,71 +83,97 @@ std::string generate_bitstream_setting_interconnect_hierarchy_name(const openfpg /******************************************************************** * A writer to output a bitstream pb_type setting to XML format *******************************************************************/ -static -void write_xml_bitstream_pb_type_setting(std::fstream& fp, - const char* fname, - const openfpga::BitstreamSetting& bitstream_setting, - const BitstreamPbTypeSettingId& bitstream_pb_type_setting_id) { +static void write_xml_bitstream_pb_type_setting( + std::fstream& fp, const char* fname, + const openfpga::BitstreamSetting& bitstream_setting, + const BitstreamPbTypeSettingId& bitstream_pb_type_setting_id) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t" << "" << "\n"; + fp << "/>" + << "\n"; } /******************************************************************** * A writer to output a bitstream interconnect setting to XML format *******************************************************************/ -static -void write_xml_bitstream_interconnect_setting(std::fstream& fp, - const char* fname, - const openfpga::BitstreamSetting& bitstream_setting, - const BitstreamInterconnectSettingId& bitstream_interc_setting_id) { +static void write_xml_bitstream_interconnect_setting( + std::fstream& fp, const char* fname, + const openfpga::BitstreamSetting& bitstream_setting, + const BitstreamInterconnectSettingId& bitstream_interc_setting_id) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t" << "" << "\n"; + fp << "/>" + << "\n"; } /******************************************************************** * A writer to output a bitstream setting to XML format *******************************************************************/ -void write_xml_bitstream_setting(std::fstream& fp, - const char* fname, - const openfpga::BitstreamSetting& bitstream_setting) { +void write_xml_bitstream_setting( + std::fstream& fp, const char* fname, + const openfpga::BitstreamSetting& bitstream_setting) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); /* Write the root node */ - fp << "" << "\n"; + fp << "" + << "\n"; - /* Write pb_type -related settings */ - for (const auto& bitstream_pb_type_setting_id : bitstream_setting.pb_type_settings()) { - write_xml_bitstream_pb_type_setting(fp, fname, bitstream_setting, bitstream_pb_type_setting_id); + /* Write pb_type -related settings */ + for (const auto& bitstream_pb_type_setting_id : + bitstream_setting.pb_type_settings()) { + write_xml_bitstream_pb_type_setting(fp, fname, bitstream_setting, + bitstream_pb_type_setting_id); } - /* Write interconnect -related settings */ - for (const auto& bitstream_interc_setting_id : bitstream_setting.interconnect_settings()) { - write_xml_bitstream_interconnect_setting(fp, fname, bitstream_setting, bitstream_interc_setting_id); + /* Write interconnect -related settings */ + for (const auto& bitstream_interc_setting_id : + bitstream_setting.interconnect_settings()) { + write_xml_bitstream_interconnect_setting(fp, fname, bitstream_setting, + bitstream_interc_setting_id); } /* Write the root node */ - fp << "" << "\n"; + fp << "" + << "\n"; } diff --git a/libs/libarchopenfpga/src/write_xml_bitstream_setting.h b/libs/libarchopenfpga/src/write_xml_bitstream_setting.h index b4eea0d10..1c625ba8c 100644 --- a/libs/libarchopenfpga/src/write_xml_bitstream_setting.h +++ b/libs/libarchopenfpga/src/write_xml_bitstream_setting.h @@ -5,13 +5,14 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "bitstream_setting.h" /******************************************************************** * Function declaration *******************************************************************/ -void write_xml_bitstream_setting(std::fstream& fp, - const char* fname, - const openfpga::BitstreamSetting& bitstream_setting); +void write_xml_bitstream_setting( + std::fstream& fp, const char* fname, + const openfpga::BitstreamSetting& bitstream_setting); #endif diff --git a/libs/libarchopenfpga/src/write_xml_circuit_library.cpp b/libs/libarchopenfpga/src/write_xml_circuit_library.cpp index a9314713d..ac6867cea 100644 --- a/libs/libarchopenfpga/src/write_xml_circuit_library.cpp +++ b/libs/libarchopenfpga/src/write_xml_circuit_library.cpp @@ -2,30 +2,31 @@ * This file includes functions that outputs a circuit library to XML format *******************************************************************/ /* Headers from system goes first */ -#include #include +#include /* Headers from vtr util library */ -#include "vtr_log.h" #include "openfpga_digest.h" +#include "vtr_log.h" /* Headers from readarchopenfpga library */ -#include "write_xml_utils.h" #include "write_xml_circuit_library.h" +#include "write_xml_utils.h" /******************************************************************** * A writer to output the design technology of a circuit model to XML format *******************************************************************/ -static -void write_xml_design_technology(std::fstream& fp, - const char* fname, - const CircuitLibrary& circuit_lib, - const CircuitModelId& model) { +static void write_xml_design_technology(std::fstream& fp, const char* fname, + const CircuitLibrary& circuit_lib, + const CircuitModelId& model) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t\t\t" << "" << "\n"; + fp << "/>" + << "\n"; } /******************************************************************** * A writer to output the device technology of a circuit model to XML format *******************************************************************/ -static -void write_xml_device_technology(std::fstream& fp, - const char* fname, - const CircuitLibrary& circuit_lib, - const CircuitModelId& model) { +static void write_xml_device_technology(std::fstream& fp, const char* fname, + const CircuitLibrary& circuit_lib, + const CircuitModelId& model) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - + if (!circuit_lib.device_model_name(model).empty()) { - fp << "\t\t\t" << "" << "\n"; + fp << "/>" + << "\n"; } } /******************************************************************** * A writer to output a circuit port to XML format *******************************************************************/ -static -void write_xml_circuit_port(std::fstream& fp, - const char* fname, - const CircuitLibrary& circuit_lib, - const CircuitPortId& port) { +static void write_xml_circuit_port(std::fstream& fp, const char* fname, + const CircuitLibrary& circuit_lib, + const CircuitPortId& port) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); @@ -126,54 +160,63 @@ void write_xml_circuit_port(std::fstream& fp, const CircuitModelId& model = circuit_lib.port_parent_model(port); /* Generic information about a port */ - fp << "\t\t\t" << "" << "\n"; + fp << "/>" + << "\n"; } /******************************************************************** * A writer to output wire parasitics of a circuit model to XML format *******************************************************************/ -static -void write_xml_wire_param(std::fstream& fp, - const char* fname, - const CircuitLibrary& circuit_lib, - const CircuitModelId& model) { +static void write_xml_wire_param(std::fstream& fp, const char* fname, + const CircuitLibrary& circuit_lib, + const CircuitModelId& model) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t\t\t" << "" << "\n"; + fp << "/>" + << "\n"; } /******************************************************************** * A writer to output delay matrices of a circuit model to XML format *******************************************************************/ -static -void write_xml_delay_matrix(std::fstream& fp, - const char* fname, - const CircuitLibrary& circuit_lib, - const CircuitModelId& model) { +static void write_xml_delay_matrix(std::fstream& fp, const char* fname, + const CircuitLibrary& circuit_lib, + const CircuitModelId& model) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); @@ -286,17 +333,19 @@ void write_xml_delay_matrix(std::fstream& fp, std::vector out_ports; /* Collect the input ports and output ports */ for (const auto& timing_edge : circuit_lib.timing_edges_by_model(model)) { - /* For each input port of each edge, build a list of unique ports */ - CircuitPortId src_port = circuit_lib.timing_edge_src_port(timing_edge); - if (in_ports.end() == std::find(in_ports.begin(), in_ports.end(), src_port)) { - in_ports.push_back(src_port); - } + /* For each input port of each edge, build a list of unique ports */ + CircuitPortId src_port = circuit_lib.timing_edge_src_port(timing_edge); + if (in_ports.end() == + std::find(in_ports.begin(), in_ports.end(), src_port)) { + in_ports.push_back(src_port); + } - /* For each input port of each edge, build a list of unique ports */ - CircuitPortId sink_port = circuit_lib.timing_edge_sink_port(timing_edge); - if (out_ports.end() == std::find(out_ports.begin(), out_ports.end(), sink_port)) { - out_ports.push_back(sink_port); - } + /* For each input port of each edge, build a list of unique ports */ + CircuitPortId sink_port = circuit_lib.timing_edge_sink_port(timing_edge); + if (out_ports.end() == + std::find(out_ports.begin(), out_ports.end(), sink_port)) { + out_ports.push_back(sink_port); + } } /* Build the string of in_port list */ @@ -306,7 +355,7 @@ void write_xml_delay_matrix(std::fstream& fp, in_port_string += std::string(" "); } in_port_string += circuit_lib.port_prefix(in_port); - } + } /* Build the string of out_port list */ std::string out_port_string; @@ -315,41 +364,45 @@ void write_xml_delay_matrix(std::fstream& fp, out_port_string += std::string(" "); } out_port_string += circuit_lib.port_prefix(out_port); - } + } /* Output rising edges */ fp << "\t\t\t"; fp << "\n"; - + for (const CircuitPortId& out_port : out_ports) { for (const size_t& out_pin : circuit_lib.pins(out_port)) { fp << "\t\t\t\t"; - size_t counter = 0; /* Count the numbers of delays in one line */ + size_t counter = 0; /* Count the numbers of delays in one line */ for (const CircuitPortId& in_port : in_ports) { for (const size_t& in_pin : circuit_lib.pins(in_port)) { - for (const auto& timing_edge : circuit_lib.timing_edges_by_model(model)) { - CircuitPortId src_port = circuit_lib.timing_edge_src_port(timing_edge); + for (const auto& timing_edge : + circuit_lib.timing_edges_by_model(model)) { + CircuitPortId src_port = + circuit_lib.timing_edge_src_port(timing_edge); size_t src_pin = circuit_lib.timing_edge_src_pin(timing_edge); - CircuitPortId sink_port = circuit_lib.timing_edge_sink_port(timing_edge); + CircuitPortId sink_port = + circuit_lib.timing_edge_sink_port(timing_edge); size_t sink_pin = circuit_lib.timing_edge_sink_pin(timing_edge); /* Bypass unwanted edges */ - if ( (src_port != in_port) - || (src_pin != in_pin) - || (sink_port != out_port) - || (sink_pin != out_pin) ) { + if ((src_port != in_port) || (src_pin != in_pin) || + (sink_port != out_port) || (sink_pin != out_pin)) { continue; } /* This is the edge we want, output the rise delay */ if (0 < counter) { fp << std::string(" "); } - fp << std::scientific << circuit_lib.timing_edge_delay(timing_edge, CIRCUIT_MODEL_DELAY_RISE); + fp << std::scientific + << circuit_lib.timing_edge_delay(timing_edge, + CIRCUIT_MODEL_DELAY_RISE); counter++; } } @@ -360,41 +413,46 @@ void write_xml_delay_matrix(std::fstream& fp, } fp << "\t\t\t"; - fp << "" << "\n"; + fp << "" + << "\n"; /* Output falling edges */ fp << "\t\t\t"; fp << "\n"; - + for (const CircuitPortId& out_port : out_ports) { for (const size_t& out_pin : circuit_lib.pins(out_port)) { fp << "\t\t\t\t"; - size_t counter = 0; /* Count the numbers of delays in one line */ + size_t counter = 0; /* Count the numbers of delays in one line */ for (const CircuitPortId& in_port : in_ports) { for (const size_t& in_pin : circuit_lib.pins(in_port)) { - for (const auto& timing_edge : circuit_lib.timing_edges_by_model(model)) { - CircuitPortId src_port = circuit_lib.timing_edge_src_port(timing_edge); + for (const auto& timing_edge : + circuit_lib.timing_edges_by_model(model)) { + CircuitPortId src_port = + circuit_lib.timing_edge_src_port(timing_edge); size_t src_pin = circuit_lib.timing_edge_src_pin(timing_edge); - CircuitPortId sink_port = circuit_lib.timing_edge_sink_port(timing_edge); + CircuitPortId sink_port = + circuit_lib.timing_edge_sink_port(timing_edge); size_t sink_pin = circuit_lib.timing_edge_sink_pin(timing_edge); /* Bypass unwanted edges */ - if ( (src_port != in_port) - || (src_pin != in_pin) - || (sink_port != out_port) - || (sink_pin != out_pin) ) { + if ((src_port != in_port) || (src_pin != in_pin) || + (sink_port != out_port) || (sink_pin != out_pin)) { continue; } /* This is the edge we want, output the rise delay */ if (0 < counter) { fp << std::string(" "); } - fp << std::scientific << circuit_lib.timing_edge_delay(timing_edge, CIRCUIT_MODEL_DELAY_FALL); + fp << std::scientific + << circuit_lib.timing_edge_delay(timing_edge, + CIRCUIT_MODEL_DELAY_FALL); counter++; } } @@ -405,38 +463,42 @@ void write_xml_delay_matrix(std::fstream& fp, } fp << "\t\t\t"; - fp << "" << "\n"; + fp << "" + << "\n"; } /******************************************************************** * A writer to output a circuit model to XML format *******************************************************************/ -static -void write_xml_circuit_model(std::fstream& fp, - const char* fname, - const CircuitLibrary& circuit_lib, - const CircuitModelId& model) { +static void write_xml_circuit_model(std::fstream& fp, const char* fname, + const CircuitLibrary& circuit_lib, + const CircuitModelId& model) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); /* Write the definition of circuit model */ - fp << "\t\t" << "" << "\n"; + fp << ">" + << "\n"; /* Write the design technology of circuit model */ write_xml_design_technology(fp, fname, circuit_lib, model); @@ -444,63 +506,93 @@ void write_xml_circuit_model(std::fstream& fp, /* Write the device technology of circuit model */ write_xml_device_technology(fp, fname, circuit_lib, model); - /* Write the input buffer information of circuit model, + /* Write the input buffer information of circuit model, * only applicable when this circuit model is neither inverter nor buffer */ if (CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(model)) { if (true == circuit_lib.is_input_buffered(model)) { - fp << "\t\t\t" << "" << "\n"; + fp << "\t\t\t" + << "" + << "\n"; } } /* Write the output buffer information of circuit model */ if (CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(model)) { if (true == circuit_lib.is_output_buffered(model)) { - fp << "\t\t\t" << "" << "\n"; + fp << "\t\t\t" + << "" + << "\n"; } } if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) { /* Write the lut input buffer information of circuit model - * This is a mandatory attribute for LUT, so it must exist + * This is a mandatory attribute for LUT, so it must exist */ - fp << "\t\t\t" << "" << "\n"; + fp << "\t\t\t" + << "" + << "\n"; /* Write the lut input inverter information of circuit model - * This is a mandatory attribute for LUT, so it must exist + * This is a mandatory attribute for LUT, so it must exist */ - fp << "\t\t\t" << "" << "\n"; + fp << "\t\t\t" + << "" + << "\n"; /* Write the lut intermediate buffer information of circuit model */ if (true == circuit_lib.is_lut_intermediate_buffered(model)) { - fp << "\t\t\t" << "" << "\n"; + fp << "/>" + << "\n"; } } /* Write the pass-gate-logic information of circuit model */ - if ( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) - || (CIRCUIT_MODEL_MUX == circuit_lib.model_type(model)) ) { - fp << "\t\t\t" << "" << "\n"; + if ((CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) || + (CIRCUIT_MODEL_MUX == circuit_lib.model_type(model))) { + fp << "\t\t\t" + << "" + << "\n"; } /* Write the ports of circuit model */ @@ -509,47 +601,51 @@ void write_xml_circuit_model(std::fstream& fp, } /* Write the wire parasticis of circuit model */ - if ( (CIRCUIT_MODEL_WIRE == circuit_lib.model_type(model)) - || (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) ) { + if ((CIRCUIT_MODEL_WIRE == circuit_lib.model_type(model)) || + (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(model))) { write_xml_wire_param(fp, fname, circuit_lib, model); } /* Write the delay matrix of circuit model - * Skip circuit models without delay matrices + * Skip circuit models without delay matrices */ if (0 < circuit_lib.num_delay_info(model)) { write_xml_delay_matrix(fp, fname, circuit_lib, model); } /* Put an end to the XML definition of this circuit model */ - fp << "\t\t" << "\n"; + fp << "\t\t" + << "\n"; } /******************************************************************** * A writer to output a circuit library to XML format - * Note: - * This function should be run after that the following methods of - * CircuitLibrary are executed + * Note: + * This function should be run after that the following methods of + * CircuitLibrary are executed * 1. build_model_links(); * 2. build_timing_graph(); *******************************************************************/ -void write_xml_circuit_library(std::fstream& fp, - const char* fname, +void write_xml_circuit_library(std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - - /* Write the root node for circuit_library, - * we apply a tab becuase circuit library is a subnode + + /* Write the root node for circuit_library, + * we apply a tab becuase circuit library is a subnode * under the root node */ - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; - /* Write circuit model one by one */ + /* Write circuit model one by one */ for (const CircuitModelId& model : circuit_lib.models()) { write_xml_circuit_model(fp, fname, circuit_lib, model); - } + } /* Write the root node for circuit_library */ - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; } diff --git a/libs/libarchopenfpga/src/write_xml_circuit_library.h b/libs/libarchopenfpga/src/write_xml_circuit_library.h index 90cd513c9..d0b2526f6 100644 --- a/libs/libarchopenfpga/src/write_xml_circuit_library.h +++ b/libs/libarchopenfpga/src/write_xml_circuit_library.h @@ -5,13 +5,13 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "circuit_library.h" /******************************************************************** * Function declaration *******************************************************************/ -void write_xml_circuit_library(std::fstream& fp, - const char* fname, +void write_xml_circuit_library(std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib); #endif diff --git a/libs/libarchopenfpga/src/write_xml_config_protocol.cpp b/libs/libarchopenfpga/src/write_xml_config_protocol.cpp index 7801049a3..d215ee8c9 100644 --- a/libs/libarchopenfpga/src/write_xml_config_protocol.cpp +++ b/libs/libarchopenfpga/src/write_xml_config_protocol.cpp @@ -1,49 +1,67 @@ /******************************************************************** - * This file includes functions that outputs a configuration protocol to XML format + * This file includes functions that outputs a configuration protocol to XML + *format *******************************************************************/ /* Headers from system goes first */ -#include #include +#include /* Headers from vtr util library */ +#include "openfpga_digest.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "openfpga_digest.h" /* Headers from readarchopenfpga library */ -#include "write_xml_utils.h" #include "write_xml_config_protocol.h" +#include "write_xml_utils.h" /******************************************************************** * A writer to output a configuration memory organization to XML format *******************************************************************/ -static -void write_xml_config_organization(std::fstream& fp, - const char* fname, - const ConfigProtocol& config_protocol, - const CircuitLibrary& circuit_lib) { +static void write_xml_config_organization(std::fstream& fp, const char* fname, + const ConfigProtocol& config_protocol, + const CircuitLibrary& circuit_lib) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t\t" << "" << "\n"; + fp << "\t\t" + << "" + << "\n"; /* Output BL/WL protocols */ - fp << "\t\t\t" << "" << "\n"; + fp << "/>" + << "\n"; - fp << "\t\t\t" << "" << "\n"; + fp << "/>" + << "\n"; - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; } /******************************************************************** @@ -52,19 +70,22 @@ void write_xml_config_organization(std::fstream& fp, * This function should be run AFTER the function * link_config_protocol_to_circuit_library() *******************************************************************/ -void write_xml_config_protocol(std::fstream& fp, - const char* fname, +void write_xml_config_protocol(std::fstream& fp, const char* fname, const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - - /* Write the root node */ - fp << "\t" << "" << "\n"; - /* Write configuration memory organization */ + /* Write the root node */ + fp << "\t" + << "" + << "\n"; + + /* Write configuration memory organization */ write_xml_config_organization(fp, fname, config_protocol, circuit_lib); /* Finish writing the root node */ - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; } diff --git a/libs/libarchopenfpga/src/write_xml_config_protocol.h b/libs/libarchopenfpga/src/write_xml_config_protocol.h index d95198da3..f8c1d08ca 100644 --- a/libs/libarchopenfpga/src/write_xml_config_protocol.h +++ b/libs/libarchopenfpga/src/write_xml_config_protocol.h @@ -5,14 +5,14 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "config_protocol.h" + #include "circuit_library.h" +#include "config_protocol.h" /******************************************************************** * Function declaration *******************************************************************/ -void write_xml_config_protocol(std::fstream& fp, - const char* fname, +void write_xml_config_protocol(std::fstream& fp, const char* fname, const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib); diff --git a/libs/libarchopenfpga/src/write_xml_openfpga_arch.cpp b/libs/libarchopenfpga/src/write_xml_openfpga_arch.cpp index a97c3f002..e39565de2 100644 --- a/libs/libarchopenfpga/src/write_xml_openfpga_arch.cpp +++ b/libs/libarchopenfpga/src/write_xml_openfpga_arch.cpp @@ -11,20 +11,20 @@ #include "openfpga_digest.h" /* Headers from readarchopenfpga library */ -#include "write_xml_circuit_library.h" -#include "write_xml_technology_library.h" -#include "write_xml_simulation_setting.h" #include "write_xml_bitstream_setting.h" +#include "write_xml_circuit_library.h" #include "write_xml_config_protocol.h" -#include "write_xml_routing_circuit.h" -#include "write_xml_tile_annotation.h" -#include "write_xml_pb_type_annotation.h" #include "write_xml_openfpga_arch.h" +#include "write_xml_pb_type_annotation.h" +#include "write_xml_routing_circuit.h" +#include "write_xml_simulation_setting.h" +#include "write_xml_technology_library.h" +#include "write_xml_tile_annotation.h" /******************************************************************** * A writer to output an OpenFPGA arch database to XML format *******************************************************************/ -void write_xml_openfpga_arch(const char* fname, +void write_xml_openfpga_arch(const char* fname, const openfpga::Arch& openfpga_arch) { vtr::ScopedStartFinishTimer timer("Write OpenFPGA architecture"); @@ -37,7 +37,8 @@ void write_xml_openfpga_arch(const char* fname, openfpga::check_file_stream(fname, fp); /* Write the root node for openfpga_arch */ - fp << "" << "\n"; + fp << "" + << "\n"; /* Write the technology library */ write_xml_technology_library(fp, fname, openfpga_arch.tech_lib); @@ -46,27 +47,35 @@ void write_xml_openfpga_arch(const char* fname, write_xml_circuit_library(fp, fname, openfpga_arch.circuit_lib); /* Write the configuration protocol */ - write_xml_config_protocol(fp, fname, openfpga_arch.config_protocol, openfpga_arch.circuit_lib); + write_xml_config_protocol(fp, fname, openfpga_arch.config_protocol, + openfpga_arch.circuit_lib); /* Write the connection block circuit definition */ - write_xml_cb_switch_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.cb_switch2circuit); + write_xml_cb_switch_circuit(fp, fname, openfpga_arch.circuit_lib, + openfpga_arch.cb_switch2circuit); /* Write the switch block circuit definition */ - write_xml_sb_switch_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.sb_switch2circuit); + write_xml_sb_switch_circuit(fp, fname, openfpga_arch.circuit_lib, + openfpga_arch.sb_switch2circuit); /* Write the routing segment circuit definition */ - write_xml_routing_segment_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.routing_seg2circuit); + write_xml_routing_segment_circuit(fp, fname, openfpga_arch.circuit_lib, + openfpga_arch.routing_seg2circuit); /* Write the direct connection circuit definition */ - write_xml_direct_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.arch_direct); + write_xml_direct_circuit(fp, fname, openfpga_arch.circuit_lib, + openfpga_arch.arch_direct); /* Write the pb_type annotations */ - openfpga::write_xml_tile_annotations(fp, fname, openfpga_arch.tile_annotations); + openfpga::write_xml_tile_annotations(fp, fname, + openfpga_arch.tile_annotations); /* Write the pb_type annotations */ - openfpga::write_xml_pb_type_annotations(fp, fname, openfpga_arch.pb_type_annotations); + openfpga::write_xml_pb_type_annotations(fp, fname, + openfpga_arch.pb_type_annotations); - fp << "" << "\n"; + fp << "" + << "\n"; /* Close the file stream */ fp.close(); @@ -75,8 +84,8 @@ void write_xml_openfpga_arch(const char* fname, /******************************************************************** * A writer to output an OpenFPGA simulation setting database to XML format *******************************************************************/ -void write_xml_openfpga_simulation_settings(const char* fname, - const openfpga::SimulationSetting& openfpga_sim_setting) { +void write_xml_openfpga_simulation_settings( + const char* fname, const openfpga::SimulationSetting& openfpga_sim_setting) { vtr::ScopedStartFinishTimer timer("Write OpenFPGA simulation settings"); /* Create a file handler */ @@ -97,8 +106,9 @@ void write_xml_openfpga_simulation_settings(const char* fname, /******************************************************************** * A writer to output an OpenFPGA bitstream setting database to XML format *******************************************************************/ -void write_xml_openfpga_bitstream_settings(const char* fname, - const openfpga::BitstreamSetting& openfpga_bitstream_setting) { +void write_xml_openfpga_bitstream_settings( + const char* fname, + const openfpga::BitstreamSetting& openfpga_bitstream_setting) { vtr::ScopedStartFinishTimer timer("Write OpenFPGA bitstream settings"); /* Create a file handler */ diff --git a/libs/libarchopenfpga/src/write_xml_openfpga_arch.h b/libs/libarchopenfpga/src/write_xml_openfpga_arch.h index 3ea251b49..e1dba4920 100644 --- a/libs/libarchopenfpga/src/write_xml_openfpga_arch.h +++ b/libs/libarchopenfpga/src/write_xml_openfpga_arch.h @@ -5,19 +5,21 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "openfpga_arch.h" /******************************************************************** * Function declaration *******************************************************************/ -void write_xml_openfpga_arch(const char* xml_fname, +void write_xml_openfpga_arch(const char* xml_fname, const openfpga::Arch& openfpga_arch); -void write_xml_openfpga_simulation_settings(const char* xml_fname, - const openfpga::SimulationSetting& openfpga_sim_setting); - -void write_xml_openfpga_bitstream_settings(const char* fname, - const openfpga::BitstreamSetting& openfpga_bitstream_setting); +void write_xml_openfpga_simulation_settings( + const char* xml_fname, + const openfpga::SimulationSetting& openfpga_sim_setting); +void write_xml_openfpga_bitstream_settings( + const char* fname, + const openfpga::BitstreamSetting& openfpga_bitstream_setting); #endif diff --git a/libs/libarchopenfpga/src/write_xml_pb_type_annotation.cpp b/libs/libarchopenfpga/src/write_xml_pb_type_annotation.cpp index b401f6ca8..25eb846d0 100644 --- a/libs/libarchopenfpga/src/write_xml_pb_type_annotation.cpp +++ b/libs/libarchopenfpga/src/write_xml_pb_type_annotation.cpp @@ -2,17 +2,17 @@ * This file includes functions that outputs pb_type annotations to XML format *******************************************************************/ /* Headers from system goes first */ -#include #include +#include /* Headers from vtr util library */ +#include "openfpga_digest.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "openfpga_digest.h" /* Headers from readarchopenfpga library */ -#include "write_xml_utils.h" #include "write_xml_pb_type_annotation.h" +#include "write_xml_utils.h" /* namespace openfpga begins */ namespace openfpga { @@ -20,14 +20,16 @@ namespace openfpga { /******************************************************************** * Generate the full hierarchy name for a operating pb_type *******************************************************************/ -static -std::string generate_operating_pb_type_hierarchy_name(const PbTypeAnnotation& pb_type_annotation) { +static std::string generate_operating_pb_type_hierarchy_name( + const PbTypeAnnotation& pb_type_annotation) { /* Iterate over the parent_pb_type and modes names, they should well match */ - VTR_ASSERT_SAFE(pb_type_annotation.operating_parent_pb_type_names().size() == pb_type_annotation.operating_parent_mode_names().size()); + VTR_ASSERT_SAFE(pb_type_annotation.operating_parent_pb_type_names().size() == + pb_type_annotation.operating_parent_mode_names().size()); std::string hie_name; - for (size_t i = 0 ; i < pb_type_annotation.operating_parent_pb_type_names().size(); ++i) { + for (size_t i = 0; + i < pb_type_annotation.operating_parent_pb_type_names().size(); ++i) { hie_name += pb_type_annotation.operating_parent_pb_type_names()[i]; hie_name += std::string("["); hie_name += pb_type_annotation.operating_parent_mode_names()[i]; @@ -44,14 +46,16 @@ std::string generate_operating_pb_type_hierarchy_name(const PbTypeAnnotation& pb /******************************************************************** * Generate the full hierarchy name for a operating pb_type *******************************************************************/ -static -std::string generate_physical_pb_type_hierarchy_name(const PbTypeAnnotation& pb_type_annotation) { +static std::string generate_physical_pb_type_hierarchy_name( + const PbTypeAnnotation& pb_type_annotation) { /* Iterate over the parent_pb_type and modes names, they should well match */ - VTR_ASSERT_SAFE(pb_type_annotation.physical_parent_pb_type_names().size() == pb_type_annotation.physical_parent_mode_names().size()); + VTR_ASSERT_SAFE(pb_type_annotation.physical_parent_pb_type_names().size() == + pb_type_annotation.physical_parent_mode_names().size()); std::string hie_name; - for (size_t i = 0 ; i < pb_type_annotation.physical_parent_pb_type_names().size(); ++i) { + for (size_t i = 0; + i < pb_type_annotation.physical_parent_pb_type_names().size(); ++i) { hie_name += pb_type_annotation.physical_parent_pb_type_names()[i]; hie_name += std::string("["); hie_name += pb_type_annotation.physical_parent_mode_names()[i]; @@ -69,8 +73,7 @@ std::string generate_physical_pb_type_hierarchy_name(const PbTypeAnnotation& pb_ * FIXME: Use a common function to output ports * Generate the full hierarchy name for a operating pb_type *******************************************************************/ -static -std::string generate_physical_pb_port_name(const BasicPort& pb_port) { +static std::string generate_physical_pb_port_name(const BasicPort& pb_port) { std::string port_name; /* Output format: [:] */ @@ -87,111 +90,135 @@ std::string generate_physical_pb_port_name(const BasicPort& pb_port) { /******************************************************************** * A writer to output an pb_type interconnection annotation to XML format *******************************************************************/ -static -void write_xml_interconnect_annotation(std::fstream& fp, - const char* fname, - const openfpga::PbTypeAnnotation& pb_type_annotation, - const std::string& interc_name) { +static void write_xml_interconnect_annotation( + std::fstream& fp, const char* fname, + const openfpga::PbTypeAnnotation& pb_type_annotation, + const std::string& interc_name) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t\t\t" << "" << "\n"; + write_xml_attribute(fp, "name", interc_name.c_str()); + write_xml_attribute( + fp, "circuit_model_name", + pb_type_annotation.interconnect_circuit_model_name(interc_name).c_str()); + + fp << "/>" + << "\n"; } /******************************************************************** * A writer to output an pb_type port annotation to XML format *******************************************************************/ -static -void write_xml_pb_port_annotation(std::fstream& fp, - const char* fname, - const openfpga::PbTypeAnnotation& pb_type_annotation, - const std::string& port_name) { +static void write_xml_pb_port_annotation( + std::fstream& fp, const char* fname, + const openfpga::PbTypeAnnotation& pb_type_annotation, + const std::string& port_name) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t\t\t" << "" << "\n"; + write_xml_attribute(fp, "physical_mode_port_rotate_offset", + physical_mode_port_rotate_offset_attr.c_str()); + fp << "/>" + << "\n"; } /******************************************************************** * A writer to output a device variation in a technology library to XML format *******************************************************************/ -static -void write_xml_pb_type_annotation(std::fstream& fp, - const char* fname, - const openfpga::PbTypeAnnotation& pb_type_annotation) { +static void write_xml_pb_type_annotation( + std::fstream& fp, const char* fname, + const openfpga::PbTypeAnnotation& pb_type_annotation) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t\t" << "" << "\n"; + if ((0 == pb_type_annotation.interconnect_names().size()) && + (0 == pb_type_annotation.port_names().size())) { + fp << "/>" + << "\n"; return; } - fp << ">" << "\n"; + fp << ">" + << "\n"; /* Output interconnects if there are any */ - for (const std::string& interc_name : pb_type_annotation.interconnect_names()) { - write_xml_interconnect_annotation(fp, fname, pb_type_annotation, interc_name); + for (const std::string& interc_name : + pb_type_annotation.interconnect_names()) { + write_xml_interconnect_annotation(fp, fname, pb_type_annotation, + interc_name); } /* Output pb_type ports if there are any */ for (const std::string& port_name : pb_type_annotation.port_names()) { write_xml_pb_port_annotation(fp, fname, pb_type_annotation, port_name); } - - fp << "\t\t" << "\n"; + + fp << "\t\t" + << "\n"; } /******************************************************************** * A writer to output a number of pb_type annotations to XML format *******************************************************************/ -void write_xml_pb_type_annotations(std::fstream& fp, - const char* fname, - const std::vector& pb_type_annotations) { +void write_xml_pb_type_annotations( + std::fstream& fp, const char* fname, + const std::vector& pb_type_annotations) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - - /* Write the root node for pb_type annotations, - * we apply a tab becuase pb_type annotations is just a subnode + + /* Write the root node for pb_type annotations, + * we apply a tab becuase pb_type annotations is just a subnode * under the root node */ - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; - /* Write device model one by one */ + /* Write device model one by one */ for (const PbTypeAnnotation& pb_type_annotation : pb_type_annotations) { write_xml_pb_type_annotation(fp, fname, pb_type_annotation); } /* Write the root node for pb_type annotations */ - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; } -} /* namespace openfpga ends */ +} // namespace openfpga diff --git a/libs/libarchopenfpga/src/write_xml_pb_type_annotation.h b/libs/libarchopenfpga/src/write_xml_pb_type_annotation.h index e40b5ad4e..ff4fd4a60 100644 --- a/libs/libarchopenfpga/src/write_xml_pb_type_annotation.h +++ b/libs/libarchopenfpga/src/write_xml_pb_type_annotation.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "pb_type_annotation.h" /******************************************************************** @@ -13,10 +14,10 @@ /* namespace openfpga begins */ namespace openfpga { -void write_xml_pb_type_annotations(std::fstream& fp, - const char* fname, - const std::vector& pb_type_annotations); +void write_xml_pb_type_annotations( + std::fstream& fp, const char* fname, + const std::vector& pb_type_annotations); -} /* namespace openfpga ends */ +} // namespace openfpga #endif diff --git a/libs/libarchopenfpga/src/write_xml_routing_circuit.cpp b/libs/libarchopenfpga/src/write_xml_routing_circuit.cpp index 978d38516..74eb8beac 100644 --- a/libs/libarchopenfpga/src/write_xml_routing_circuit.cpp +++ b/libs/libarchopenfpga/src/write_xml_routing_circuit.cpp @@ -3,129 +3,145 @@ * to XML format *******************************************************************/ /* Headers from system goes first */ -#include #include +#include /* Headers from vtr util library */ +#include "openfpga_digest.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "openfpga_digest.h" /* Headers from readarchopenfpga library */ -#include "write_xml_utils.h" #include "write_xml_routing_circuit.h" +#include "write_xml_utils.h" /******************************************************************** * Write switch circuit model definition in XML format *******************************************************************/ -static -void write_xml_routing_component_circuit(std::fstream& fp, - const char* fname, - const std::string& routing_component_name, - const CircuitLibrary& circuit_lib, - const std::map& switch2circuit) { +static void write_xml_routing_component_circuit( + std::fstream& fp, const char* fname, + const std::string& routing_component_name, const CircuitLibrary& circuit_lib, + const std::map& switch2circuit) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); /* Iterate over the mapping */ - for (std::map::const_iterator it = switch2circuit.begin(); - it != switch2circuit.end(); - ++it) { - fp << "\t\t" << "<" << routing_component_name; - write_xml_attribute(fp, "name", it->first.c_str()); - write_xml_attribute(fp, "circuit_model_name", circuit_lib.model_name(it->second).c_str()); - fp << "/>" << "\n"; + for (std::map::const_iterator it = + switch2circuit.begin(); + it != switch2circuit.end(); ++it) { + fp << "\t\t" + << "<" << routing_component_name; + write_xml_attribute(fp, "name", it->first.c_str()); + write_xml_attribute(fp, "circuit_model_name", + circuit_lib.model_name(it->second).c_str()); + fp << "/>" + << "\n"; } } /******************************************************************** * Write switch circuit model definition in XML format *******************************************************************/ -static -void write_xml_direct_component_circuit(std::fstream& fp, - const char* fname, - const std::string& direct_tag_name, - const CircuitLibrary& circuit_lib, - const ArchDirect& arch_direct, - const ArchDirectId& direct_id) { +static void write_xml_direct_component_circuit( + std::fstream& fp, const char* fname, const std::string& direct_tag_name, + const CircuitLibrary& circuit_lib, const ArchDirect& arch_direct, + const ArchDirectId& direct_id) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); /* Iterate over the mapping */ - fp << "\t\t" << "<" << direct_tag_name; - write_xml_attribute(fp, "name", arch_direct.name(direct_id).c_str()); - write_xml_attribute(fp, "circuit_model_name", circuit_lib.model_name(arch_direct.circuit_model(direct_id)).c_str()); - write_xml_attribute(fp, "type", DIRECT_TYPE_STRING[arch_direct.type(direct_id)]); - write_xml_attribute(fp, "x_dir", DIRECT_DIRECTION_STRING[arch_direct.x_dir(direct_id)]); - write_xml_attribute(fp, "y_dir", DIRECT_DIRECTION_STRING[arch_direct.y_dir(direct_id)]); - fp << "/>" << "\n"; + fp << "\t\t" + << "<" << direct_tag_name; + write_xml_attribute(fp, "name", arch_direct.name(direct_id).c_str()); + write_xml_attribute( + fp, "circuit_model_name", + circuit_lib.model_name(arch_direct.circuit_model(direct_id)).c_str()); + write_xml_attribute(fp, "type", + DIRECT_TYPE_STRING[arch_direct.type(direct_id)]); + write_xml_attribute(fp, "x_dir", + DIRECT_DIRECTION_STRING[arch_direct.x_dir(direct_id)]); + write_xml_attribute(fp, "y_dir", + DIRECT_DIRECTION_STRING[arch_direct.y_dir(direct_id)]); + fp << "/>" + << "\n"; } /******************************************************************** * Write Connection block circuit models in XML format *******************************************************************/ -void write_xml_cb_switch_circuit(std::fstream& fp, - const char* fname, - const CircuitLibrary& circuit_lib, - const std::map& switch2circuit) { +void write_xml_cb_switch_circuit( + std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib, + const std::map& switch2circuit) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - - /* Write the root node */ - fp << "\t" << "" << "\n"; - /* Write each switch circuit definition */ - write_xml_routing_component_circuit(fp, fname, std::string("switch"), circuit_lib, switch2circuit); + /* Write the root node */ + fp << "\t" + << "" + << "\n"; + + /* Write each switch circuit definition */ + write_xml_routing_component_circuit(fp, fname, std::string("switch"), + circuit_lib, switch2circuit); /* Finish writing the root node */ - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; } /******************************************************************** * Write Switch block circuit models in XML format *******************************************************************/ -void write_xml_sb_switch_circuit(std::fstream& fp, - const char* fname, - const CircuitLibrary& circuit_lib, - const std::map& switch2circuit) { +void write_xml_sb_switch_circuit( + std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib, + const std::map& switch2circuit) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - - /* Write the root node */ - fp << "\t" << "" << "\n"; - /* Write each switch circuit definition */ - write_xml_routing_component_circuit(fp, fname, std::string("switch"), circuit_lib, switch2circuit); + /* Write the root node */ + fp << "\t" + << "" + << "\n"; + + /* Write each switch circuit definition */ + write_xml_routing_component_circuit(fp, fname, std::string("switch"), + circuit_lib, switch2circuit); /* Finish writing the root node */ - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; } /******************************************************************** * Write routing segment circuit models in XML format *******************************************************************/ -void write_xml_routing_segment_circuit(std::fstream& fp, - const char* fname, - const CircuitLibrary& circuit_lib, - const std::map& seg2circuit) { +void write_xml_routing_segment_circuit( + std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib, + const std::map& seg2circuit) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - - /* Write the root node */ - fp << "\t" << "" << "\n"; - /* Write each routing segment circuit definition */ - write_xml_routing_component_circuit(fp, fname, std::string("segment"), circuit_lib, seg2circuit); + /* Write the root node */ + fp << "\t" + << "" + << "\n"; + + /* Write each routing segment circuit definition */ + write_xml_routing_component_circuit(fp, fname, std::string("segment"), + circuit_lib, seg2circuit); /* Finish writing the root node */ - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; } /******************************************************************** * Write direction connection circuit models in XML format *******************************************************************/ -void write_xml_direct_circuit(std::fstream& fp, - const char* fname, +void write_xml_direct_circuit(std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib, const ArchDirect& arch_direct) { /* If the direct2circuit is empty, we do not output XML */ @@ -135,15 +151,20 @@ void write_xml_direct_circuit(std::fstream& fp, /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - - /* Write the root node */ - fp << "\t" << "" << "\n"; - /* Write each direct connection circuit definition */ + /* Write the root node */ + fp << "\t" + << "" + << "\n"; + + /* Write each direct connection circuit definition */ for (const ArchDirectId& direct_id : arch_direct.directs()) { - write_xml_direct_component_circuit(fp, fname, std::string("direct"), circuit_lib, arch_direct, direct_id); + write_xml_direct_component_circuit(fp, fname, std::string("direct"), + circuit_lib, arch_direct, direct_id); } /* Finish writing the root node */ - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; } diff --git a/libs/libarchopenfpga/src/write_xml_routing_circuit.h b/libs/libarchopenfpga/src/write_xml_routing_circuit.h index bddb7cc56..9c814641c 100644 --- a/libs/libarchopenfpga/src/write_xml_routing_circuit.h +++ b/libs/libarchopenfpga/src/write_xml_routing_circuit.h @@ -8,29 +8,25 @@ #include #include -#include "circuit_library.h" #include "arch_direct.h" +#include "circuit_library.h" /******************************************************************** * Function declaration *******************************************************************/ -void write_xml_cb_switch_circuit(std::fstream& fp, - const char* fname, - const CircuitLibrary& circuit_lib, - const std::map& switch2circuit); +void write_xml_cb_switch_circuit( + std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib, + const std::map& switch2circuit); -void write_xml_sb_switch_circuit(std::fstream& fp, - const char* fname, - const CircuitLibrary& circuit_lib, - const std::map& switch2circuit); +void write_xml_sb_switch_circuit( + std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib, + const std::map& switch2circuit); -void write_xml_routing_segment_circuit(std::fstream& fp, - const char* fname, - const CircuitLibrary& circuit_lib, - const std::map& seg2circuit); +void write_xml_routing_segment_circuit( + std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib, + const std::map& seg2circuit); -void write_xml_direct_circuit(std::fstream& fp, - const char* fname, +void write_xml_direct_circuit(std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib, const ArchDirect& arch_direct); diff --git a/libs/libarchopenfpga/src/write_xml_simulation_setting.cpp b/libs/libarchopenfpga/src/write_xml_simulation_setting.cpp index 3f8129908..d14b91d7e 100644 --- a/libs/libarchopenfpga/src/write_xml_simulation_setting.cpp +++ b/libs/libarchopenfpga/src/write_xml_simulation_setting.cpp @@ -2,117 +2,159 @@ * This file includes functions that outputs a simulation setting to XML format *******************************************************************/ /* Headers from system goes first */ -#include #include +#include /* Headers from vtr util library */ +#include "openfpga_digest.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "openfpga_digest.h" /* Headers from readarchopenfpga library */ -#include "write_xml_utils.h" #include "write_xml_simulation_setting.h" +#include "write_xml_utils.h" /******************************************************************** * A writer to output a clock setting in a simulation setting to XML format *******************************************************************/ -static -void write_xml_clock_setting(std::fstream& fp, - const char* fname, - const openfpga::SimulationSetting& sim_setting) { +static void write_xml_clock_setting( + std::fstream& fp, const char* fname, + const openfpga::SimulationSetting& sim_setting) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; - fp << "\t\t" << "" + << "\n"; - fp << ">" << "\n"; - /* Output clock information one by one */ for (const SimulationClockId& clock_id : sim_setting.operating_clocks()) { - fp << "\t\t\t" << "" << "\n"; + write_xml_attribute( + fp, "port", + generate_xml_port_name(sim_setting.clock_port(clock_id)).c_str()); + write_xml_attribute( + fp, "frequency", + std::to_string(sim_setting.clock_frequency(clock_id)).c_str()); + fp << ">" + << "\n"; } - - fp << "\t\t" << "" << "\n"; - fp << "\t\t" << "" << "\n"; + fp << "\t\t" + << "" + << "\n"; + + fp << "\t\t" + << "" + << "\n"; /* Output clock information one by one */ for (const SimulationClockId& clock_id : sim_setting.programming_clocks()) { - fp << "\t\t\t" << "" << "\n"; + write_xml_attribute( + fp, "port", + generate_xml_port_name(sim_setting.clock_port(clock_id)).c_str()); + write_xml_attribute( + fp, "frequency", + std::to_string(sim_setting.clock_frequency(clock_id)).c_str()); + write_xml_attribute( + fp, "is_shift_register", + std::to_string(sim_setting.clock_is_shift_register(clock_id)).c_str()); + fp << ">" + << "\n"; } - fp << "\t\t" << "" << "\n"; + fp << "\t\t" + << "" + << "\n"; - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; } /******************************************************************** * A writer to output a simulator option in a simulation setting to XML format *******************************************************************/ -static -void write_xml_simulator_option(std::fstream& fp, - const char* fname, - const openfpga::SimulationSetting& sim_setting) { +static void write_xml_simulator_option( + std::fstream& fp, const char* fname, + const openfpga::SimulationSetting& sim_setting) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; - fp << "\t\t" << "" << "\n"; + fp << "/>" + << "\n"; - fp << "\t\t" << "" << "\n"; + fp << "/>" + << "\n"; - fp << "\t\t" << "" << "\n"; + fp << "/>" + << "\n"; - fp << "\t\t" << "" << "\n"; + fp << "/>" + << "\n"; - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; } /******************************************************************** * A writer to output a monte carlo simulation setting * in a simulation setting to XML format *******************************************************************/ -static -void write_xml_monte_carlo(std::fstream& fp, - const char* fname, - const openfpga::SimulationSetting& sim_setting) { +static void write_xml_monte_carlo( + std::fstream& fp, const char* fname, + const openfpga::SimulationSetting& sim_setting) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); @@ -123,147 +165,207 @@ void write_xml_monte_carlo(std::fstream& fp, return; } - fp << "\t\t" << "" << "\n"; + write_xml_attribute( + fp, "num_simulation_points", + std::to_string(sim_setting.monte_carlo_simulation_points()).c_str()); + + fp << "/>" + << "\n"; } /******************************************************************** - * A writer to output the slew measurement setting in a simulation setting to XML format + * A writer to output the slew measurement setting in a simulation setting to + *XML format *******************************************************************/ -static -void write_xml_slew_measurement(std::fstream& fp, - const char* fname, - const openfpga::SimulationSetting& sim_setting, - const e_sim_signal_type& signal_type) { +static void write_xml_slew_measurement( + std::fstream& fp, const char* fname, + const openfpga::SimulationSetting& sim_setting, + const e_sim_signal_type& signal_type) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t\t\t" << "<" << SIM_SIGNAL_TYPE_STRING[signal_type]; + fp << "\t\t\t" + << "<" << SIM_SIGNAL_TYPE_STRING[signal_type]; - write_xml_attribute(fp, "upper_thres_pct", sim_setting.measure_slew_upper_threshold(signal_type)); - write_xml_attribute(fp, "lower_thres_pct", sim_setting.measure_slew_lower_threshold(signal_type)); - - fp << "/>" << "\n"; + write_xml_attribute(fp, "upper_thres_pct", + sim_setting.measure_slew_upper_threshold(signal_type)); + write_xml_attribute(fp, "lower_thres_pct", + sim_setting.measure_slew_lower_threshold(signal_type)); + + fp << "/>" + << "\n"; } /******************************************************************** - * A writer to output the delay measurement setting in a simulation setting to XML format + * A writer to output the delay measurement setting in a simulation setting to + *XML format *******************************************************************/ -static -void write_xml_delay_measurement(std::fstream& fp, - const char* fname, - const openfpga::SimulationSetting& sim_setting, - const e_sim_signal_type& signal_type) { +static void write_xml_delay_measurement( + std::fstream& fp, const char* fname, + const openfpga::SimulationSetting& sim_setting, + const e_sim_signal_type& signal_type) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t\t\t" << "<" << SIM_SIGNAL_TYPE_STRING[signal_type]; + fp << "\t\t\t" + << "<" << SIM_SIGNAL_TYPE_STRING[signal_type]; - write_xml_attribute(fp, "input_thres_pct", sim_setting.measure_delay_input_threshold(signal_type)); - write_xml_attribute(fp, "output_thres_pct", sim_setting.measure_delay_output_threshold(signal_type)); - - fp << "/>" << "\n"; + write_xml_attribute(fp, "input_thres_pct", + sim_setting.measure_delay_input_threshold(signal_type)); + write_xml_attribute(fp, "output_thres_pct", + sim_setting.measure_delay_output_threshold(signal_type)); + + fp << "/>" + << "\n"; } /******************************************************************** - * A writer to output a measurement setting in a simulation setting to XML format + * A writer to output a measurement setting in a simulation setting to XML + *format *******************************************************************/ -static -void write_xml_measurement(std::fstream& fp, - const char* fname, - const openfpga::SimulationSetting& sim_setting) { +static void write_xml_measurement( + std::fstream& fp, const char* fname, + const openfpga::SimulationSetting& sim_setting) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; - fp << "\t\t" << "" << "\n"; + fp << "\t\t" + << "" + << "\n"; write_xml_slew_measurement(fp, fname, sim_setting, SIM_SIGNAL_RISE); write_xml_slew_measurement(fp, fname, sim_setting, SIM_SIGNAL_FALL); - fp << "\t\t" << "" << "\n"; + fp << "\t\t" + << "" + << "\n"; - fp << "\t\t" << "" << "\n"; + fp << "\t\t" + << "" + << "\n"; write_xml_delay_measurement(fp, fname, sim_setting, SIM_SIGNAL_RISE); write_xml_delay_measurement(fp, fname, sim_setting, SIM_SIGNAL_FALL); - fp << "\t\t" << "" << "\n"; + fp << "\t\t" + << "" + << "\n"; - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; } /******************************************************************** * A writer to output a stimulus setting in a simulation setting to XML format *******************************************************************/ -static -void write_xml_stimulus(std::fstream& fp, - const char* fname, - const openfpga::SimulationSetting& sim_setting) { +static void write_xml_stimulus(std::fstream& fp, const char* fname, + const openfpga::SimulationSetting& sim_setting) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; - fp << "\t\t" << "" << "\n"; + fp << "\t\t" + << "" + << "\n"; - fp << "\t\t\t" << "" << "\n"; + fp << "\t\t\t" + << "" + << "\n"; - fp << "\t\t\t" << "" << "\n"; + fp << "\t\t\t" + << "" + << "\n"; - fp << "\t\t" << "" << "\n"; + fp << "\t\t" + << "" + << "\n"; - fp << "\t\t" << "" << "\n"; + fp << "\t\t" + << "" + << "\n"; - fp << "\t\t\t" << "" << "\n"; + fp << "\t\t\t" + << "" + << "\n"; - fp << "\t\t\t" << "" << "\n"; + fp << "\t\t\t" + << "" + << "\n"; - fp << "\t\t" << "" << "\n"; + fp << "\t\t" + << "" + << "\n"; - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; } /******************************************************************** * A writer to output a simulation setting to XML format *******************************************************************/ -void write_xml_simulation_setting(std::fstream& fp, - const char* fname, - const openfpga::SimulationSetting& sim_setting) { +void write_xml_simulation_setting( + std::fstream& fp, const char* fname, + const openfpga::SimulationSetting& sim_setting) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); /* Write the root node */ - fp << "" << "\n"; + fp << "" + << "\n"; - /* Write clock settings */ + /* Write clock settings */ write_xml_clock_setting(fp, fname, sim_setting); - /* Write simulator option */ + /* Write simulator option */ write_xml_simulator_option(fp, fname, sim_setting); - /* Write monte carlo simulation setting */ + /* Write monte carlo simulation setting */ write_xml_monte_carlo(fp, fname, sim_setting); - /* Write measurement setting */ + /* Write measurement setting */ write_xml_measurement(fp, fname, sim_setting); - /* Write stimuli setting */ + /* Write stimuli setting */ write_xml_stimulus(fp, fname, sim_setting); /* Write the root node */ - fp << "" << "\n"; + fp << "" + << "\n"; } diff --git a/libs/libarchopenfpga/src/write_xml_simulation_setting.h b/libs/libarchopenfpga/src/write_xml_simulation_setting.h index d0581a8c6..166324d1f 100644 --- a/libs/libarchopenfpga/src/write_xml_simulation_setting.h +++ b/libs/libarchopenfpga/src/write_xml_simulation_setting.h @@ -5,13 +5,14 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "simulation_setting.h" /******************************************************************** * Function declaration *******************************************************************/ -void write_xml_simulation_setting(std::fstream& fp, - const char* fname, - const openfpga::SimulationSetting& sim_setting); +void write_xml_simulation_setting( + std::fstream& fp, const char* fname, + const openfpga::SimulationSetting& sim_setting); #endif diff --git a/libs/libarchopenfpga/src/write_xml_technology_library.cpp b/libs/libarchopenfpga/src/write_xml_technology_library.cpp index bf15bbe32..725d29a85 100644 --- a/libs/libarchopenfpga/src/write_xml_technology_library.cpp +++ b/libs/libarchopenfpga/src/write_xml_technology_library.cpp @@ -2,159 +2,224 @@ * This file includes functions that outputs a technology library to XML format *******************************************************************/ /* Headers from system goes first */ -#include #include +#include /* Headers from vtr util library */ -#include "vtr_log.h" #include "openfpga_digest.h" +#include "vtr_log.h" /* Headers from readarchopenfpga library */ -#include "write_xml_utils.h" #include "write_xml_technology_library.h" +#include "write_xml_utils.h" /******************************************************************** * A writer to output a device model in a technology library to XML format *******************************************************************/ -static -void write_xml_device_model(std::fstream& fp, - const char* fname, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& device_model) { +static void write_xml_device_model(std::fstream& fp, const char* fname, + const TechnologyLibrary& tech_lib, + const TechnologyModelId& device_model) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t\t\t" << "" << "\n"; + fp << ">" + << "\n"; /* Write library settings */ - fp << "\t\t\t\t" << "" << "\n"; + fp << ">" + << "\n"; /* Write design parameters. This is ONLY applicable to transistors */ if (TECH_LIB_MODEL_TRANSISTOR == tech_lib.model_type(device_model)) { - fp << "\t\t\t\t" << "" << "\n"; + fp << "\t\t\t\t" + << "" + << "\n"; } /* Write PMOS and NMOS. This is ONLY applicable to transistors */ if (TECH_LIB_MODEL_TRANSISTOR == tech_lib.model_type(device_model)) { - fp << "\t\t\t\t" << "" << "\n"; + fp << "/>" + << "\n"; - fp << "\t\t\t\t" << "" << "\n"; + fp << "/>" + << "\n"; } /* Write RRAM device parameters. This is ONLY applicable to RRAM */ if (TECH_LIB_MODEL_RRAM == tech_lib.model_type(device_model)) { - fp << "\t\t\t\t" << "" << "\n"; + fp << "/>" + << "\n"; } /* Finished XML dumping for this device model */ - fp << "\t\t\t" << "" << "\n"; + fp << "\t\t\t" + << "" + << "\n"; } /******************************************************************** * A writer to output a device variation in a technology library to XML format *******************************************************************/ -static -void write_xml_device_variation(std::fstream& fp, - const char* fname, - const TechnologyLibrary& tech_lib, - const TechnologyVariationId& device_variation) { +static void write_xml_device_variation( + std::fstream& fp, const char* fname, const TechnologyLibrary& tech_lib, + const TechnologyVariationId& device_variation) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t\t\t" << "" << "\n"; + fp << "/>" + << "\n"; } /******************************************************************** * A writer to output a technology library to XML format - * Note: - * This function should be run after that the following methods of - * TechnologyLibrary are executed + * Note: + * This function should be run after that the following methods of + * TechnologyLibrary are executed * 1. link_models_to_variations(); *******************************************************************/ -void write_xml_technology_library(std::fstream& fp, - const char* fname, +void write_xml_technology_library(std::fstream& fp, const char* fname, const TechnologyLibrary& tech_lib) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - - /* Write the root node for technology_library, - * we apply a tab becuase technology library is a subnode + + /* Write the root node for technology_library, + * we apply a tab becuase technology library is a subnode * under the root node */ - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; - /* Write device library node */ - fp << "\t\t" << "" << "\n"; - - /* Write device model one by one */ + /* Write device library node */ + fp << "\t\t" + << "" + << "\n"; + + /* Write device model one by one */ for (const TechnologyModelId& device_model : tech_lib.models()) { write_xml_device_model(fp, fname, tech_lib, device_model); } - /* Finish writing device library node */ - fp << "\t\t" << "" << "\n"; + /* Finish writing device library node */ + fp << "\t\t" + << "" + << "\n"; - /* Write variation library node */ - fp << "\t\t" << "" << "\n"; + /* Write variation library node */ + fp << "\t\t" + << "" + << "\n"; - /* Write variation model one by one */ + /* Write variation model one by one */ for (const TechnologyVariationId& variation : tech_lib.variations()) { write_xml_device_variation(fp, fname, tech_lib, variation); } - /* Finish writing variation library node */ - fp << "\t\t" << "" << "\n"; + /* Finish writing variation library node */ + fp << "\t\t" + << "" + << "\n"; /* Write the root node for circuit_library */ - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; } diff --git a/libs/libarchopenfpga/src/write_xml_technology_library.h b/libs/libarchopenfpga/src/write_xml_technology_library.h index 8edfb2346..60f423ca8 100644 --- a/libs/libarchopenfpga/src/write_xml_technology_library.h +++ b/libs/libarchopenfpga/src/write_xml_technology_library.h @@ -5,13 +5,13 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "technology_library.h" /******************************************************************** * Function declaration *******************************************************************/ -void write_xml_technology_library(std::fstream& fp, - const char* fname, +void write_xml_technology_library(std::fstream& fp, const char* fname, const TechnologyLibrary& tech_lib); #endif diff --git a/libs/libarchopenfpga/src/write_xml_tile_annotation.cpp b/libs/libarchopenfpga/src/write_xml_tile_annotation.cpp index 8e5ef0d5e..f0d42b54d 100644 --- a/libs/libarchopenfpga/src/write_xml_tile_annotation.cpp +++ b/libs/libarchopenfpga/src/write_xml_tile_annotation.cpp @@ -2,17 +2,17 @@ * This file includes functions that outputs tile annotations to XML format *******************************************************************/ /* Headers from system goes first */ -#include #include +#include /* Headers from vtr util library */ +#include "openfpga_digest.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "openfpga_digest.h" /* Headers from readarchopenfpga library */ -#include "write_xml_utils.h" #include "write_xml_tile_annotation.h" +#include "write_xml_utils.h" /* namespace openfpga begins */ namespace openfpga { @@ -20,62 +20,92 @@ namespace openfpga { /******************************************************************** * A writer to output a device variation in a technology library to XML format *******************************************************************/ -static -void write_xml_tile_annotation_global_port(std::fstream& fp, - const char* fname, - const openfpga::TileAnnotation& tile_annotation, - const TileGlobalPortId& global_port_id) { +static void write_xml_tile_annotation_global_port( + std::fstream& fp, const char* fname, + const openfpga::TileAnnotation& tile_annotation, + const TileGlobalPortId& global_port_id) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - fp << "\t\t" << "" << "\n"; + write_xml_attribute( + fp, "default_value", + tile_annotation.global_port_default_value(global_port_id)); - for (size_t tile_info_id = 0; tile_info_id < tile_annotation.global_port_tile_names(global_port_id).size(); ++tile_info_id) { - fp << "\t\t\t" << "" + << "\n"; + + for (size_t tile_info_id = 0; + tile_info_id < + tile_annotation.global_port_tile_names(global_port_id).size(); + ++tile_info_id) { + fp << "\t\t\t" + << ""; } - fp << "\t\t" << ""; + fp << "\t\t" + << ""; } /******************************************************************** * A writer to output tile annotations to XML format *******************************************************************/ -void write_xml_tile_annotations(std::fstream& fp, - const char* fname, +void write_xml_tile_annotations(std::fstream& fp, const char* fname, const TileAnnotation& tile_annotation) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - - /* Write the root node for pb_type annotations, - * we apply a tab becuase pb_type annotations is just a subnode + + /* Write the root node for pb_type annotations, + * we apply a tab becuase pb_type annotations is just a subnode * under the root node */ - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; - /* Write device model one by one */ - for (const TileGlobalPortId& global_port_id : tile_annotation.global_ports()) { - write_xml_tile_annotation_global_port(fp, fname, tile_annotation, global_port_id); + /* Write device model one by one */ + for (const TileGlobalPortId& global_port_id : + tile_annotation.global_ports()) { + write_xml_tile_annotation_global_port(fp, fname, tile_annotation, + global_port_id); } /* Write the root node for pb_type annotations */ - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; } -} /* namespace openfpga ends */ +} // namespace openfpga diff --git a/libs/libarchopenfpga/src/write_xml_tile_annotation.h b/libs/libarchopenfpga/src/write_xml_tile_annotation.h index e50536a42..2727863ab 100644 --- a/libs/libarchopenfpga/src/write_xml_tile_annotation.h +++ b/libs/libarchopenfpga/src/write_xml_tile_annotation.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "tile_annotation.h" /******************************************************************** @@ -13,10 +14,9 @@ /* namespace openfpga begins */ namespace openfpga { -void write_xml_tile_annotations(std::fstream& fp, - const char* fname, +void write_xml_tile_annotations(std::fstream& fp, const char* fname, const TileAnnotation& tile_annotation); -} /* namespace openfpga ends */ +} // namespace openfpga #endif diff --git a/libs/libarchopenfpga/src/write_xml_utils.cpp b/libs/libarchopenfpga/src/write_xml_utils.cpp index 0ed6ad5a8..99b9b2309 100644 --- a/libs/libarchopenfpga/src/write_xml_utils.cpp +++ b/libs/libarchopenfpga/src/write_xml_utils.cpp @@ -2,93 +2,87 @@ * This file includes most utilized function to write an XML file *******************************************************************/ /* Headers from system goes first */ -#include -#include +#include +#include /* Headers from vtrutil library */ -#include "vtr_assert.h" +#include "vtr_assert.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" +#include "openfpga_digest.h" /* Headers from readarchopenfpga library */ -#include "write_xml_utils.h" +#include "write_xml_utils.h" /******************************************************************** * A most utilized function to write an XML attribute to file *******************************************************************/ -void write_xml_attribute(std::fstream& fp, - const char* attr, +void write_xml_attribute(std::fstream& fp, const char* attr, const char* value) { /* Validate the file stream */ openfpga::valid_file_stream(fp); - fp << " " << attr << "=\"" << value << "\""; + fp << " " << attr << "=\"" << value << "\""; } /******************************************************************** * A most utilized function to write an XML attribute to file - * This accepts the value as a boolean + * This accepts the value as a boolean *******************************************************************/ -void write_xml_attribute(std::fstream& fp, - const char* attr, +void write_xml_attribute(std::fstream& fp, const char* attr, const bool& value) { /* Validate the file stream */ openfpga::valid_file_stream(fp); fp << " " << attr << "=\""; if (true == value) { - fp << "true"; + fp << "true"; } else { VTR_ASSERT_SAFE(false == value); - fp << "false"; + fp << "false"; } - fp << "\""; + fp << "\""; } /******************************************************************** * A most utilized function to write an XML attribute to file * This accepts the value as a float *******************************************************************/ -void write_xml_attribute(std::fstream& fp, - const char* attr, - const int& value) { +void write_xml_attribute(std::fstream& fp, const char* attr, const int& value) { /* Validate the file stream */ openfpga::valid_file_stream(fp); fp << " " << attr << "=\""; fp << value; - fp << "\""; + fp << "\""; } /******************************************************************** * A most utilized function to write an XML attribute to file * This accepts the value as a size_t *******************************************************************/ -void write_xml_attribute(std::fstream& fp, - const char* attr, +void write_xml_attribute(std::fstream& fp, const char* attr, const size_t& value) { /* Validate the file stream */ openfpga::valid_file_stream(fp); fp << " " << attr << "=\""; fp << value; - fp << "\""; + fp << "\""; } /******************************************************************** * A most utilized function to write an XML attribute to file * This accepts the value as a float *******************************************************************/ -void write_xml_attribute(std::fstream& fp, - const char* attr, +void write_xml_attribute(std::fstream& fp, const char* attr, const float& value) { /* Validate the file stream */ openfpga::valid_file_stream(fp); fp << " " << attr << "=\""; fp << std::scientific << value; - fp << "\""; + fp << "\""; } /******************************************************************** diff --git a/libs/libarchopenfpga/src/write_xml_utils.h b/libs/libarchopenfpga/src/write_xml_utils.h index e29342a54..a389ac3fd 100644 --- a/libs/libarchopenfpga/src/write_xml_utils.h +++ b/libs/libarchopenfpga/src/write_xml_utils.h @@ -5,30 +5,23 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "circuit_library.h" -#include "openfpga_port.h" +#include "openfpga_port.h" /******************************************************************** * Function declaration *******************************************************************/ -void write_xml_attribute(std::fstream& fp, - const char* attr, - const char* value); +void write_xml_attribute(std::fstream& fp, const char* attr, const char* value); -void write_xml_attribute(std::fstream& fp, - const char* attr, - const bool& value); +void write_xml_attribute(std::fstream& fp, const char* attr, const bool& value); -void write_xml_attribute(std::fstream& fp, - const char* attr, - const int& value); +void write_xml_attribute(std::fstream& fp, const char* attr, const int& value); -void write_xml_attribute(std::fstream& fp, - const char* attr, +void write_xml_attribute(std::fstream& fp, const char* attr, const float& value); -void write_xml_attribute(std::fstream& fp, - const char* attr, +void write_xml_attribute(std::fstream& fp, const char* attr, const size_t& value); std::string generate_xml_port_name(const openfpga::BasicPort& pb_port); diff --git a/libs/libarchopenfpga/test/read_arch_openfpga.cpp b/libs/libarchopenfpga/test/read_arch_openfpga.cpp index 7974cf258..23d40000f 100644 --- a/libs/libarchopenfpga/test/read_arch_openfpga.cpp +++ b/libs/libarchopenfpga/test/read_arch_openfpga.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * Unit test functions to validate the correctness of + * Unit test functions to validate the correctness of * 1. parser of data structures * 2. writer of data structures *******************************************************************/ @@ -17,21 +17,18 @@ int main(int argc, const char** argv) { VTR_ASSERT((2 == argc) || (3 == argc)); /* Parse the circuit library from an XML file */ - const openfpga::Arch& openfpga_arch = read_xml_openfpga_arch(argv[1]); + const openfpga::Arch& openfpga_arch = read_xml_openfpga_arch(argv[1]); VTR_LOG("Parsed %lu circuit models from XML into circuit library.\n", openfpga_arch.circuit_lib.num_models()); /* Check the circuit library */ check_circuit_library(openfpga_arch.circuit_lib); - + /* Output the circuit library to an XML file * This is optional only used when there is a second argument */ - if (3 <= argc) { + if (3 <= argc) { write_xml_openfpga_arch(argv[2], openfpga_arch); - VTR_LOG("Echo the OpenFPGA architecture to an XML file: %s.\n", - argv[2]); + VTR_LOG("Echo the OpenFPGA architecture to an XML file: %s.\n", argv[2]); } } - - diff --git a/libs/libarchopenfpga/test/read_bitstream_setting_openfpga.cpp b/libs/libarchopenfpga/test/read_bitstream_setting_openfpga.cpp index 9447f2f0f..3a9ff1cf3 100644 --- a/libs/libarchopenfpga/test/read_bitstream_setting_openfpga.cpp +++ b/libs/libarchopenfpga/test/read_bitstream_setting_openfpga.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * Unit test functions to validate the correctness of + * Unit test functions to validate the correctness of * 1. parser of data structures * 2. writer of data structures *******************************************************************/ @@ -16,14 +16,14 @@ int main(int argc, const char** argv) { VTR_ASSERT((2 == argc) || (3 == argc)); /* Parse the simulation settings from an XML file */ - const openfpga::BitstreamSetting& openfpga_bitstream_setting = read_xml_openfpga_bitstream_settings(argv[1]); - VTR_LOG("Parsed bitstream settings from XML %s.\n", - argv[1]); + const openfpga::BitstreamSetting& openfpga_bitstream_setting = + read_xml_openfpga_bitstream_settings(argv[1]); + VTR_LOG("Parsed bitstream settings from XML %s.\n", argv[1]); /* Output the simulation settings to an XML file * This is optional only used when there is a second argument */ - if (3 <= argc) { + if (3 <= argc) { write_xml_openfpga_bitstream_settings(argv[2], openfpga_bitstream_setting); VTR_LOG("Echo the OpenFPGA bitstream settings to an XML file: %s.\n", argv[2]); diff --git a/libs/libarchopenfpga/test/read_simulation_setting_openfpga.cpp b/libs/libarchopenfpga/test/read_simulation_setting_openfpga.cpp index b8540240b..54eeeeb5d 100644 --- a/libs/libarchopenfpga/test/read_simulation_setting_openfpga.cpp +++ b/libs/libarchopenfpga/test/read_simulation_setting_openfpga.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * Unit test functions to validate the correctness of + * Unit test functions to validate the correctness of * 1. parser of data structures * 2. writer of data structures *******************************************************************/ @@ -16,14 +16,14 @@ int main(int argc, const char** argv) { VTR_ASSERT((2 == argc) || (3 == argc)); /* Parse the simulation settings from an XML file */ - const openfpga::SimulationSetting& openfpga_sim_setting = read_xml_openfpga_simulation_settings(argv[1]); - VTR_LOG("Parsed simulation settings from XML %s.\n", - argv[1]); + const openfpga::SimulationSetting& openfpga_sim_setting = + read_xml_openfpga_simulation_settings(argv[1]); + VTR_LOG("Parsed simulation settings from XML %s.\n", argv[1]); /* Output the simulation settings to an XML file * This is optional only used when there is a second argument */ - if (3 <= argc) { + if (3 <= argc) { write_xml_openfpga_simulation_settings(argv[2], openfpga_sim_setting); VTR_LOG("Echo the OpenFPGA simulation settings to an XML file: %s.\n", argv[2]); diff --git a/libs/libbusgroup/src/bus_group.cpp b/libs/libbusgroup/src/bus_group.cpp index 8bc5688ed..bf22e17b5 100644 --- a/libs/libbusgroup/src/bus_group.cpp +++ b/libs/libbusgroup/src/bus_group.cpp @@ -1,11 +1,11 @@ +#include "bus_group.h" + #include #include "vtr_assert.h" #include "vtr_log.h" -#include "bus_group.h" - -namespace openfpga { // Begin namespace openfpga +namespace openfpga { // Begin namespace openfpga /************************************************************************ * Member functions for class BusGroup @@ -14,9 +14,7 @@ namespace openfpga { // Begin namespace openfpga /************************************************************************ * Constructors ***********************************************************************/ -BusGroup::BusGroup() { - return; -} +BusGroup::BusGroup() { return; } /************************************************************************ * Public Accessors : aggregates @@ -26,67 +24,68 @@ BusGroup::bus_group_range BusGroup::buses() const { } /************************************************************************ - * Public Accessors : Basic data query + * Public Accessors : Basic data query ***********************************************************************/ openfpga::BasicPort BusGroup::bus_port(const BusGroupId& bus_id) const { VTR_ASSERT(valid_bus_id(bus_id)); - return bus_ports_[bus_id]; + return bus_ports_[bus_id]; } bool BusGroup::is_big_endian(const BusGroupId& bus_id) const { VTR_ASSERT(valid_bus_id(bus_id)); - return bus_big_endians_[bus_id]; + return bus_big_endians_[bus_id]; } std::vector BusGroup::bus_pins(const BusGroupId& bus_id) const { VTR_ASSERT(valid_bus_id(bus_id)); - return bus_pin_ids_[bus_id]; + return bus_pin_ids_[bus_id]; } int BusGroup::pin_index(const BusPinId& pin_id) const { VTR_ASSERT(valid_pin_id(pin_id)); - return pin_indices_[pin_id]; + return pin_indices_[pin_id]; } std::string BusGroup::pin_name(const BusPinId& pin_id) const { VTR_ASSERT(valid_pin_id(pin_id)); - return pin_names_[pin_id]; + return pin_names_[pin_id]; } BusGroupId BusGroup::find_pin_bus(const std::string& pin_name) const { - std::map::const_iterator result = pin_name2id_map_.find(pin_name); + std::map::const_iterator result = + pin_name2id_map_.find(pin_name); if (result == pin_name2id_map_.end()) { /* Not found, return an invalid id */ return BusGroupId::INVALID(); } /* Found, we should get the parent bus */ - BusPinId pin_id = result->second; + BusPinId pin_id = result->second; return pin_parent_bus_ids_[pin_id]; } BusGroupId BusGroup::find_bus(const std::string& bus_name) const { - std::map::const_iterator result = bus_name2id_map_.find(bus_name); + std::map::const_iterator result = + bus_name2id_map_.find(bus_name); if (result == bus_name2id_map_.end()) { /* Not found, return an invalid id */ return BusGroupId::INVALID(); } /* Found, we should get the parent bus */ - return result->second; + return result->second; } BusPinId BusGroup::find_pin(const std::string& pin_name) const { - std::map::const_iterator result = pin_name2id_map_.find(pin_name); + 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; + return result->second; } -bool BusGroup::empty() const { - return 0 == bus_ids_.size(); -} +bool BusGroup::empty() const { return 0 == bus_ids_.size(); } /************************************************************************ * Public Mutators @@ -108,7 +107,7 @@ void BusGroup::reserve_pins(const size_t& num_pins) { BusGroupId BusGroup::create_bus(const openfpga::BasicPort& bus_port) { /* Create a new id */ BusGroupId bus_id = BusGroupId(bus_ids_.size()); - + bus_ids_.push_back(bus_id); bus_ports_.push_back(bus_port); bus_big_endians_.push_back(true); @@ -119,14 +118,16 @@ BusGroupId BusGroup::create_bus(const openfpga::BasicPort& bus_port) { 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()); + VTR_LOG_ERROR("Duplicated bus name '%s' in bus group", + bus_port.get_name().c_str()); exit(1); } - + return bus_id; } -void BusGroup::set_bus_big_endian(const BusGroupId& bus_id, const bool& big_endian) { +void BusGroup::set_bus_big_endian(const BusGroupId& bus_id, + const bool& big_endian) { VTR_ASSERT(valid_bus_id(bus_id)); bus_big_endians_[bus_id] = big_endian; } @@ -134,7 +135,7 @@ void BusGroup::set_bus_big_endian(const BusGroupId& bus_id, const bool& big_endi BusPinId BusGroup::create_pin(const BusGroupId& bus_id, const int& index) { /* Create a new id */ BusPinId pin_id = BusPinId(pin_ids_.size()); - + pin_ids_.push_back(pin_id); pin_indices_.push_back(index); @@ -143,7 +144,7 @@ BusPinId BusGroup::create_pin(const BusGroupId& bus_id, const int& index) { /* Register the pin to the bus */ VTR_ASSERT(valid_bus_id(bus_id)); pin_parent_bus_ids_.push_back(bus_id); - + /* If the pin index is beyond the range of the bus_pin_ids, resize it */ if (size_t(index) >= bus_pin_ids_[bus_id].size()) { bus_pin_ids_[bus_id].resize(index + 1); @@ -153,7 +154,6 @@ BusPinId BusGroup::create_pin(const BusGroupId& bus_id, const int& index) { return pin_id; } - void BusGroup::set_pin_name(const BusPinId& pin_id, const std::string& name) { VTR_ASSERT(valid_pin_id(pin_id)); pin_names_[pin_id] = name; @@ -169,14 +169,14 @@ void BusGroup::set_pin_name(const BusPinId& pin_id, const std::string& name) { } /************************************************************************ - * Internal invalidators/validators + * Internal invalidators/validators ***********************************************************************/ bool BusGroup::valid_bus_id(const BusGroupId& bus_id) const { - return ( size_t(bus_id) < bus_ids_.size() ) && ( bus_id == bus_ids_[bus_id] ); + return (size_t(bus_id) < bus_ids_.size()) && (bus_id == bus_ids_[bus_id]); } bool BusGroup::valid_pin_id(const BusPinId& pin_id) const { - return ( size_t(pin_id) < pin_ids_.size() ) && ( pin_id == pin_ids_[pin_id] ); + return (size_t(pin_id) < pin_ids_.size()) && (pin_id == pin_ids_[pin_id]); } -} // End of namespace openfpga +} // End of namespace openfpga diff --git a/libs/libbusgroup/src/bus_group.h b/libs/libbusgroup/src/bus_group.h index 85d80c579..c460dfd01 100644 --- a/libs/libbusgroup/src/bus_group.h +++ b/libs/libbusgroup/src/bus_group.h @@ -4,19 +4,18 @@ /******************************************************************** * This file include the declaration of pin constraints *******************************************************************/ -#include -#include #include +#include +#include /* Headers from vtrutil library */ #include "vtr_vector.h" /* Headers from openfpgautil library */ +#include "bus_group_fwd.h" #include "openfpga_port.h" -#include "bus_group_fwd.h" - -namespace openfpga { // Begin namespace openfpga +namespace openfpga { // Begin namespace openfpga /******************************************************************** * A data structure to describe the bus-to-pin mapping @@ -36,99 +35,103 @@ namespace openfpga { // Begin namespace openfpga * *******************************************************************/ class BusGroup { - public: /* Types */ - typedef vtr::vector::const_iterator bus_group_iterator; - typedef vtr::vector::const_iterator bus_pin_iterator; - /* Create range */ - typedef vtr::Range bus_group_range; - typedef vtr::Range bus_pin_range; - public: /* Constructors */ - BusGroup(); - public: /* Accessors: aggregates */ - bus_group_range buses() const; - public: /* Public Accessors: Basic data query */ - /** Get port information of a bus with a given id */ - BasicPort bus_port(const BusGroupId& bus_id) const; + public: /* Types */ + typedef vtr::vector::const_iterator + bus_group_iterator; + typedef vtr::vector::const_iterator bus_pin_iterator; + /* Create range */ + typedef vtr::Range bus_group_range; + typedef vtr::Range bus_pin_range; - /* Check if a bus follows big endian */ - bool is_big_endian(const BusGroupId& bus_id) const; + public: /* Constructors */ + BusGroup(); - /* Get the pins under a specific bus */ - std::vector bus_pins(const BusGroupId& bus_id) const; + public: /* Accessors: aggregates */ + bus_group_range buses() const; - /* Get the index of a pin */ - int pin_index(const BusPinId& pin_id) const; + public: /* Public Accessors: Basic data query */ + /** Get port information of a bus with a given id */ + BasicPort bus_port(const BusGroupId& bus_id) const; - /* Get the name of a pin */ - std::string pin_name(const BusPinId& pin_id) const; + /* Check if a bus follows big endian */ + bool is_big_endian(const BusGroupId& bus_id) const; - /* Find the bus that a pin belongs to */ - BusGroupId find_pin_bus(const std::string& pin_name) const; + /* Get the pins under a specific bus */ + std::vector bus_pins(const BusGroupId& bus_id) const; - /* Find the bus id with a given name */ - BusGroupId find_bus(const std::string& bus_name) const; + /* Get the index of a pin */ + int pin_index(const BusPinId& pin_id) const; - /* Find the pin id with a given name */ - BusPinId find_pin(const std::string& pin_name) const; + /* Get the name of a pin */ + std::string pin_name(const BusPinId& pin_id) const; - /* Check if there are any buses */ - bool empty() const; + /* Find the bus that a pin belongs to */ + BusGroupId find_pin_bus(const std::string& pin_name) const; - public: /* Public Mutators */ - /* Reserve a number of buses to be memory efficent */ - void reserve_buses(const size_t& num_buses); + /* Find the bus id with a given name */ + BusGroupId find_bus(const std::string& bus_name) const; - /* Reserve a number of pins to be memory efficent */ - void reserve_pins(const size_t& num_pins); + /* Find the pin id with a given name */ + BusPinId find_pin(const std::string& pin_name) const; - /* Add a bus to storage */ - BusGroupId create_bus(const openfpga::BasicPort& bus_port); + /* Check if there are any buses */ + bool empty() const; - /* Set endianness for a bus; If not set, by default it assumes big-endian */ - void set_bus_big_endian(const BusGroupId& bus_id, const bool& big_endian); + public: /* Public Mutators */ + /* Reserve a number of buses to be memory efficent */ + void reserve_buses(const size_t& num_buses); - /* Add a pin to a bus, with a given index in the bus, e.g., A[1] in A[0:2] */ - BusPinId create_pin(const BusGroupId& bus_id, const int& index); + /* Reserve a number of pins to be memory efficent */ + void reserve_pins(const size_t& num_pins); - /* Set the name for a pin */ - void set_pin_name(const BusPinId& pin_id, const std::string& name); + /* Add a bus to storage */ + BusGroupId create_bus(const openfpga::BasicPort& bus_port); - public: /* Public invalidators/validators */ - /* Show if the bus id is a valid for data queries */ - bool valid_bus_id(const BusGroupId& bus_id) const; + /* Set endianness for a bus; If not set, by default it assumes big-endian */ + void set_bus_big_endian(const BusGroupId& bus_id, const bool& big_endian); - /* Show if the pin id is a valid for data queries */ - bool valid_pin_id(const BusPinId& pin_id) const; + /* Add a pin to a bus, with a given index in the bus, e.g., A[1] in A[0:2] */ + BusPinId create_pin(const BusGroupId& bus_id, const int& index); - private: /* Internal data */ - /* Unique ids for each bus */ - vtr::vector bus_ids_; + /* Set the name for a pin */ + void set_pin_name(const BusPinId& pin_id, const std::string& name); - /* Port information of each bus */ - vtr::vector bus_ports_; + public: /* Public invalidators/validators */ + /* Show if the bus id is a valid for data queries */ + bool valid_bus_id(const BusGroupId& bus_id) const; - /* Endianness of each bus: big endian by default */ - vtr::vector bus_big_endians_; + /* Show if the pin id is a valid for data queries */ + bool valid_pin_id(const BusPinId& pin_id) const; - /* Indices of each pin under each bus */ - vtr::vector> bus_pin_ids_; + private: /* Internal data */ + /* Unique ids for each bus */ + vtr::vector bus_ids_; - /* Unique ids for each pin */ - vtr::vector pin_ids_; + /* Port information of each bus */ + vtr::vector bus_ports_; - /* Index for each pin */ - vtr::vector pin_indices_; + /* Endianness of each bus: big endian by default */ + vtr::vector bus_big_endians_; - /* Name of each pin under each bus */ - vtr::vector pin_names_; + /* Indices of each pin under each bus */ + vtr::vector> bus_pin_ids_; - /* Parent bus of each pin */ - vtr::vector pin_parent_bus_ids_; + /* Unique ids for each pin */ + vtr::vector pin_ids_; - /* Fast look-up */ - std::map bus_name2id_map_; - std::map pin_name2id_map_; + /* Index for each pin */ + vtr::vector pin_indices_; + + /* Name of each pin under each bus */ + vtr::vector pin_names_; + + /* Parent bus of each pin */ + vtr::vector pin_parent_bus_ids_; + + /* Fast look-up */ + std::map bus_name2id_map_; + std::map pin_name2id_map_; }; -} // End of namespace openfpga +} // End of namespace openfpga #endif diff --git a/libs/libbusgroup/src/bus_group_fwd.h b/libs/libbusgroup/src/bus_group_fwd.h index d6cfea772..89f78a5ec 100644 --- a/libs/libbusgroup/src/bus_group_fwd.h +++ b/libs/libbusgroup/src/bus_group_fwd.h @@ -1,18 +1,18 @@ /************************************************************************ * A header file for BusGroup class, including critical data declaration * Please include this file only for using any PinConstraints data structure - * Refer to bus_group.h for more details + * Refer to bus_group.h for more details ***********************************************************************/ /************************************************************************ - * Create strong id for BusGroup to avoid illegal type casting + * Create strong id for BusGroup to avoid illegal type casting ***********************************************************************/ #ifndef BUS_GROUP_FWD_H #define BUS_GROUP_FWD_H #include "vtr_strong_id.h" -namespace openfpga { // Begin namespace openfpga +namespace openfpga { // Begin namespace openfpga struct bus_group_id_tag; struct bus_pin_id_tag; @@ -23,6 +23,6 @@ typedef vtr::StrongId BusPinId; /* Short declaration of class */ class BusGroup; -} // End of namespace openfpga +} // End of namespace openfpga #endif diff --git a/libs/libbusgroup/src/read_xml_bus_group.cpp b/libs/libbusgroup/src/read_xml_bus_group.cpp index 768ff455a..49ccbe89e 100644 --- a/libs/libbusgroup/src/read_xml_bus_group.cpp +++ b/libs/libbusgroup/src/read_xml_bus_group.cpp @@ -18,31 +18,31 @@ /* Headers from libarchfpga */ #include "arch_error.h" -#include "read_xml_util.h" - #include "bus_group_xml_constants.h" #include "read_xml_bus_group.h" +#include "read_xml_util.h" -namespace openfpga { // Begin namespace openfpga +namespace openfpga { // Begin namespace openfpga /******************************************************************** * Parse XML codes of a to an object of BusGroup *******************************************************************/ -static -void read_xml_pin(pugi::xml_node& xml_pin, - const pugiutil::loc_data& loc_data, - BusGroup& bus_group, - const BusGroupId& bus_id) { +static void read_xml_pin(pugi::xml_node& xml_pin, + const pugiutil::loc_data& loc_data, + BusGroup& bus_group, const BusGroupId& bus_id) { if (false == bus_group.valid_bus_id(bus_id)) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin), "Invalid id of a bus group!\n"); } - int pin_index = get_attribute(xml_pin, XML_PIN_INDEX_ATTRIBUTE_NAME, loc_data).as_int(); - std::string pin_name = get_attribute(xml_pin, XML_PIN_NAME_ATTRIBUTE_NAME, loc_data).as_string(); + int pin_index = + get_attribute(xml_pin, XML_PIN_INDEX_ATTRIBUTE_NAME, loc_data).as_int(); + std::string pin_name = + get_attribute(xml_pin, XML_PIN_NAME_ATTRIBUTE_NAME, loc_data).as_string(); /* Before update storage, check if the pin index is in the range */ - BasicPort pin_port(bus_group.bus_port(bus_id).get_name(), pin_index, pin_index); + BasicPort pin_port(bus_group.bus_port(bus_id).get_name(), pin_index, + pin_index); if (!bus_group.bus_port(bus_id).contained(pin_port)) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin), "Pin index is out of range of the bus port width!\n"); @@ -55,12 +55,11 @@ void read_xml_pin(pugi::xml_node& xml_pin, /******************************************************************** * Parse XML codes of a to an object of BusGroup *******************************************************************/ -static -void read_xml_bus(pugi::xml_node& xml_bus, - const pugiutil::loc_data& loc_data, - BusGroup& bus_group) { - - openfpga::PortParser port_parser(get_attribute(xml_bus, XML_BUS_PORT_ATTRIBUTE_NAME, loc_data).as_string()); +static void read_xml_bus(pugi::xml_node& xml_bus, + const pugiutil::loc_data& loc_data, + BusGroup& bus_group) { + openfpga::PortParser port_parser( + get_attribute(xml_bus, XML_BUS_PORT_ATTRIBUTE_NAME, loc_data).as_string()); /* Create a new bus in the storage */ BusGroupId bus_id = bus_group.create_bus(port_parser.port()); @@ -77,7 +76,10 @@ void read_xml_bus(pugi::xml_node& xml_bus, } /* Find big endian */ - bus_group.set_bus_big_endian(bus_id, get_attribute(xml_bus, XML_BUS_BIG_ENDIAN_ATTRIBUTE_NAME, loc_data, pugiutil::OPTIONAL).as_bool(true)); + bus_group.set_bus_big_endian( + bus_id, get_attribute(xml_bus, XML_BUS_BIG_ENDIAN_ATTRIBUTE_NAME, loc_data, + pugiutil::OPTIONAL) + .as_bool(true)); for (pugi::xml_node xml_pin : xml_bus.children()) { /* Error out if the XML child has an invalid name! */ @@ -85,14 +87,13 @@ void read_xml_bus(pugi::xml_node& xml_bus, bad_tag(xml_pin, loc_data, xml_bus, {XML_PIN_NODE_NAME}); } read_xml_pin(xml_pin, loc_data, bus_group, bus_id); - } + } } /******************************************************************** * Parse XML codes about to an object of BusGroup *******************************************************************/ BusGroup read_xml_bus_group(const char* fname) { - vtr::ScopedStartFinishTimer timer("Read Bus Group"); BusGroup bus_group; @@ -104,16 +105,19 @@ BusGroup read_xml_bus_group(const char* fname) { try { loc_data = pugiutil::load_xml(doc, fname); - pugi::xml_node xml_root = get_single_child(doc, XML_BUS_GROUP_NODE_NAME, loc_data); + pugi::xml_node xml_root = + get_single_child(doc, XML_BUS_GROUP_NODE_NAME, loc_data); - size_t num_buses = std::distance(xml_root.children().begin(), xml_root.children().end()); + size_t num_buses = + std::distance(xml_root.children().begin(), xml_root.children().end()); /* Count the total number of pins */ size_t num_pins = 0; for (pugi::xml_node xml_bus : xml_root.children()) { - num_pins += std::distance(xml_bus.children().begin(), xml_bus.children().end()); + num_pins += + std::distance(xml_bus.children().begin(), xml_bus.children().end()); } - + /* Reserve memory space for the buses */ bus_group.reserve_buses(num_buses); /* Reserve memory space for the pins */ @@ -125,13 +129,12 @@ BusGroup read_xml_bus_group(const char* fname) { bad_tag(xml_bus, loc_data, xml_root, {XML_BUS_NODE_NAME}); } read_xml_bus(xml_bus, loc_data, bus_group); - } + } } catch (pugiutil::XmlError& e) { - archfpga_throw(fname, e.line(), - "%s", e.what()); + archfpga_throw(fname, e.line(), "%s", e.what()); } - return bus_group; + return bus_group; } -} // End of namespace openfpga +} // End of namespace openfpga diff --git a/libs/libbusgroup/src/read_xml_bus_group.h b/libs/libbusgroup/src/read_xml_bus_group.h index 7b1c89a06..53949d3fb 100644 --- a/libs/libbusgroup/src/read_xml_bus_group.h +++ b/libs/libbusgroup/src/read_xml_bus_group.h @@ -4,18 +4,18 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "pugixml_util.hpp" -#include "pugixml.hpp" #include "bus_group.h" +#include "pugixml.hpp" +#include "pugixml_util.hpp" /******************************************************************** * Function declaration *******************************************************************/ -namespace openfpga { // Begin namespace openfpga +namespace openfpga { // Begin namespace openfpga BusGroup read_xml_bus_group(const char* fname); -} // End of namespace openfpga +} // End of namespace openfpga #endif diff --git a/libs/libbusgroup/src/write_xml_bus_group.cpp b/libs/libbusgroup/src/write_xml_bus_group.cpp index be26b44f5..6df83d158 100644 --- a/libs/libbusgroup/src/write_xml_bus_group.cpp +++ b/libs/libbusgroup/src/write_xml_bus_group.cpp @@ -2,8 +2,8 @@ * This file includes functions that outputs a bus group object to XML format *******************************************************************/ /* Headers from system goes first */ -#include #include +#include /* Headers from vtr util library */ #include "vtr_assert.h" @@ -14,25 +14,23 @@ #include "openfpga_digest.h" /* Headers from arch openfpga library */ -#include "write_xml_utils.h" +#include "write_xml_utils.h" /* Headers from pin constraint library */ #include "bus_group_xml_constants.h" #include "write_xml_bus_group.h" -namespace openfpga { // Begin namespace openfpga +namespace openfpga { // Begin namespace openfpga /******************************************************************** * A writer to output a bus to XML format * * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture + * Return 1 if there are more serious bugs in the architecture * Return 2 if fail when creating files *******************************************************************/ -static -int write_xml_bus(std::fstream& fp, - const BusGroup& bus_group, - const BusGroupId& bus_id) { +static int write_xml_bus(std::fstream& fp, const BusGroup& bus_group, + const BusGroupId& bus_id) { /* Validate the file stream */ if (false == openfpga::valid_file_stream(fp)) { return 2; @@ -45,24 +43,32 @@ int write_xml_bus(std::fstream& fp, return 1; } - write_xml_attribute(fp, XML_BUS_PORT_ATTRIBUTE_NAME, generate_xml_port_name(bus_group.bus_port(bus_id)).c_str()); - write_xml_attribute(fp, XML_BUS_BIG_ENDIAN_ATTRIBUTE_NAME, bus_group.is_big_endian(bus_id)); - fp << ">" << "\n"; + write_xml_attribute( + fp, XML_BUS_PORT_ATTRIBUTE_NAME, + generate_xml_port_name(bus_group.bus_port(bus_id)).c_str()); + write_xml_attribute(fp, XML_BUS_BIG_ENDIAN_ATTRIBUTE_NAME, + bus_group.is_big_endian(bus_id)); + fp << ">" + << "\n"; /* Output all the pins under this bus */ for (const BusPinId& pin_id : bus_group.bus_pins(bus_id)) { openfpga::write_tab_to_file(fp, 2); fp << "<" << XML_PIN_NODE_NAME << ""; - write_xml_attribute(fp, XML_PIN_INDEX_ATTRIBUTE_NAME, bus_group.pin_index(pin_id)); - write_xml_attribute(fp, XML_PIN_NAME_ATTRIBUTE_NAME, bus_group.pin_name(pin_id).c_str()); + write_xml_attribute(fp, XML_PIN_INDEX_ATTRIBUTE_NAME, + bus_group.pin_index(pin_id)); + write_xml_attribute(fp, XML_PIN_NAME_ATTRIBUTE_NAME, + bus_group.pin_name(pin_id).c_str()); - fp << "/>" << "\n"; + fp << "/>" + << "\n"; } openfpga::write_tab_to_file(fp, 1); fp << "" << "\n"; + fp << ">" + << "\n"; return 0; } @@ -71,12 +77,10 @@ int write_xml_bus(std::fstream& fp, * 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 1 if there are more serious bugs in the architecture * Return 2 if fail when creating files *******************************************************************/ -int write_xml_bus_group(const char* fname, - const BusGroup& bus_group) { - +int write_xml_bus_group(const char* fname, const BusGroup& bus_group) { vtr::ScopedStartFinishTimer timer("Write Bus Group"); /* Create a file handler */ @@ -86,15 +90,16 @@ int write_xml_bus_group(const char* fname, /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - + /* Write the root node */ - fp << "<" << XML_BUS_GROUP_NODE_NAME << ">" << "\n"; + fp << "<" << XML_BUS_GROUP_NODE_NAME << ">" + << "\n"; int err_code = 0; - /* Write each bus */ + /* Write each bus */ for (const BusGroupId& bus : bus_group.buses()) { - /* Write bus */ + /* Write bus */ err_code = write_xml_bus(fp, bus_group, bus); if (0 != err_code) { return err_code; @@ -102,7 +107,8 @@ int write_xml_bus_group(const char* fname, } /* Finish writing the root node */ - fp << "" << "\n"; + fp << "" + << "\n"; /* Close the file stream */ fp.close(); @@ -110,4 +116,4 @@ int write_xml_bus_group(const char* fname, return err_code; } -} // End of namespace openfpga +} // End of namespace openfpga diff --git a/libs/libbusgroup/src/write_xml_bus_group.h b/libs/libbusgroup/src/write_xml_bus_group.h index 09a51673f..fadadc4fc 100644 --- a/libs/libbusgroup/src/write_xml_bus_group.h +++ b/libs/libbusgroup/src/write_xml_bus_group.h @@ -5,16 +5,16 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "bus_group.h" /******************************************************************** * Function declaration *******************************************************************/ -namespace openfpga { // Begin namespace openfpga +namespace openfpga { // Begin namespace openfpga -int write_xml_bus_group(const char* fname, - const BusGroup& bus_group); +int write_xml_bus_group(const char* fname, const BusGroup& bus_group); -} // End of namespace openfpga +} // End of namespace openfpga #endif diff --git a/libs/libbusgroup/test/xml_io_bus_group.cpp b/libs/libbusgroup/test/xml_io_bus_group.cpp index 1f372c311..41bc22a8b 100644 --- a/libs/libbusgroup/test/xml_io_bus_group.cpp +++ b/libs/libbusgroup/test/xml_io_bus_group.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * Unit test functions to validate the correctness of + * Unit test functions to validate the correctness of * 1. parser of data structures * 2. writer of data structures *******************************************************************/ @@ -16,18 +16,15 @@ int main(int argc, const char** argv) { VTR_ASSERT((2 == argc) || (3 == argc)); /* Parse the circuit library from an XML file */ - const openfpga::BusGroup& bus_group = openfpga::read_xml_bus_group(argv[1]); + const openfpga::BusGroup& bus_group = openfpga::read_xml_bus_group(argv[1]); VTR_LOG("Parsed %lu bus(es) from XML into bus group.\n", bus_group.buses().size()); /* Output the bus group to an XML file * This is optional only used when there is a second argument */ - if (3 <= argc) { + if (3 <= argc) { openfpga::write_xml_bus_group(argv[2], bus_group); - VTR_LOG("Write the bus group to an XML file: %s.\n", - argv[2]); + VTR_LOG("Write the bus group to an XML file: %s.\n", argv[2]); } } - - diff --git a/libs/libfabrickey/src/fabric_key.cpp b/libs/libfabrickey/src/fabric_key.cpp index 500dec09a..f9c84103d 100644 --- a/libs/libfabrickey/src/fabric_key.cpp +++ b/libs/libfabrickey/src/fabric_key.cpp @@ -1,10 +1,10 @@ +#include "fabric_key.h" + #include #include "vtr_assert.h" #include "vtr_log.h" -#include "fabric_key.h" - /************************************************************************ * Member functions for class FabricKey ***********************************************************************/ @@ -12,9 +12,7 @@ /************************************************************************ * Constructors ***********************************************************************/ -FabricKey::FabricKey() { - return; -} +FabricKey::FabricKey() { return; } /************************************************************************ * Public Accessors : aggregates @@ -27,59 +25,64 @@ FabricKey::fabric_region_range FabricKey::regions() const { return vtr::make_range(region_ids_.begin(), region_ids_.end()); } -FabricKey::fabric_bit_line_bank_range FabricKey::bl_banks(const FabricRegionId& region_id) const { +FabricKey::fabric_bit_line_bank_range FabricKey::bl_banks( + const FabricRegionId& region_id) const { VTR_ASSERT(valid_region_id(region_id)); - return vtr::make_range(bl_bank_ids_[region_id].begin(), bl_bank_ids_[region_id].end()); + return vtr::make_range(bl_bank_ids_[region_id].begin(), + bl_bank_ids_[region_id].end()); } -FabricKey::fabric_word_line_bank_range FabricKey::wl_banks(const FabricRegionId& region_id) const { +FabricKey::fabric_word_line_bank_range FabricKey::wl_banks( + const FabricRegionId& region_id) const { VTR_ASSERT(valid_region_id(region_id)); - return vtr::make_range(wl_bank_ids_[region_id].begin(), wl_bank_ids_[region_id].end()); + return vtr::make_range(wl_bank_ids_[region_id].begin(), + wl_bank_ids_[region_id].end()); } /************************************************************************ - * Public Accessors : Basic data query + * Public Accessors : Basic data query ***********************************************************************/ -std::vector FabricKey::region_keys(const FabricRegionId& region_id) const { +std::vector FabricKey::region_keys( + const FabricRegionId& region_id) const { /* validate the region_id */ VTR_ASSERT(valid_region_id(region_id)); - return region_key_ids_[region_id]; + return region_key_ids_[region_id]; } std::string FabricKey::key_name(const FabricKeyId& key_id) const { /* validate the key_id */ VTR_ASSERT(valid_key_id(key_id)); - return key_names_[key_id]; + return key_names_[key_id]; } size_t FabricKey::key_value(const FabricKeyId& key_id) const { /* validate the key_id */ VTR_ASSERT(valid_key_id(key_id)); - return key_values_[key_id]; + return key_values_[key_id]; } std::string FabricKey::key_alias(const FabricKeyId& key_id) const { /* validate the key_id */ VTR_ASSERT(valid_key_id(key_id)); - return key_alias_[key_id]; + return key_alias_[key_id]; } vtr::Point FabricKey::key_coordinate(const FabricKeyId& key_id) const { /* validate the key_id */ VTR_ASSERT(valid_key_id(key_id)); - return key_coordinates_[key_id]; + return key_coordinates_[key_id]; } -bool FabricKey::empty() const { - return 0 == key_ids_.size(); -} +bool FabricKey::empty() const { return 0 == key_ids_.size(); } -std::vector FabricKey::bl_bank_data_ports(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const { +std::vector FabricKey::bl_bank_data_ports( + const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); return bl_bank_data_ports_[region_id][bank_id]; } -std::vector FabricKey::wl_bank_data_ports(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const { +std::vector FabricKey::wl_bank_data_ports( + const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); return wl_bank_data_ports_[region_id][bank_id]; } @@ -106,7 +109,7 @@ FabricRegionId FabricKey::create_region() { bl_bank_data_ports_.emplace_back(); wl_bank_ids_.emplace_back(); wl_bank_data_ports_.emplace_back(); - + return region; } @@ -126,12 +129,12 @@ void FabricKey::add_key_to_region(const FabricRegionId& region_id, VTR_ASSERT(valid_region_id(region_id)); /* Check if the key is already in the region */ - if (region_key_ids_[region_id].end() != std::find(region_key_ids_[region_id].begin(), - region_key_ids_[region_id].end(), - key_id)) { - VTR_LOG_WARN("Try to add a key '%s' which is already in the region '%lu'!\n", - key_name(key_id).c_str(), - size_t(region_id)); + if (region_key_ids_[region_id].end() != + std::find(region_key_ids_[region_id].begin(), + region_key_ids_[region_id].end(), key_id)) { + VTR_LOG_WARN( + "Try to add a key '%s' which is already in the region '%lu'!\n", + key_name(key_id).c_str(), size_t(region_id)); VTR_ASSERT(region_id == key_regions_[key_id]); return; /* Nothing to do but leave a warning! */ } @@ -140,12 +143,13 @@ void FabricKey::add_key_to_region(const FabricRegionId& region_id, region_key_ids_[region_id].push_back(key_id); /* If the key is already in another region, we will error out */ - if ( (true == valid_region_id(key_regions_[key_id])) - && (region_id != key_regions_[key_id])) { - VTR_LOG_ERROR("Try to add a key '%s' to region '%lu' but it is already in another region '%lu'!\n", - key_name(key_id).c_str(), - size_t(key_regions_[key_id]), - size_t(region_id)); + if ((true == valid_region_id(key_regions_[key_id])) && + (region_id != key_regions_[key_id])) { + VTR_LOG_ERROR( + "Try to add a key '%s' to region '%lu' but it is already in another " + "region '%lu'!\n", + key_name(key_id).c_str(), size_t(key_regions_[key_id]), + size_t(region_id)); exit(1); } @@ -170,7 +174,7 @@ FabricKeyId FabricKey::create_key() { key_regions_.emplace_back(FabricRegionId::INVALID()); key_alias_.emplace_back(); key_coordinates_.emplace_back(vtr::Point(-1, -1)); - + return key; } @@ -182,8 +186,7 @@ void FabricKey::set_key_name(const FabricKeyId& key_id, key_names_[key_id] = name; } -void FabricKey::set_key_value(const FabricKeyId& key_id, - const size_t& value) { +void FabricKey::set_key_value(const FabricKeyId& key_id, const size_t& value) { /* validate the key_id */ VTR_ASSERT(valid_key_id(key_id)); @@ -206,80 +209,91 @@ void FabricKey::set_key_coordinate(const FabricKeyId& key_id, key_coordinates_[key_id] = coord; } -void FabricKey::reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) { +void FabricKey::reserve_bl_shift_register_banks(const FabricRegionId& region_id, + const size_t& num_banks) { VTR_ASSERT(valid_region_id(region_id)); bl_bank_ids_[region_id].reserve(num_banks); bl_bank_data_ports_[region_id].reserve(num_banks); } -void FabricKey::reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) { +void FabricKey::reserve_wl_shift_register_banks(const FabricRegionId& region_id, + const size_t& num_banks) { VTR_ASSERT(valid_region_id(region_id)); wl_bank_ids_[region_id].reserve(num_banks); wl_bank_data_ports_[region_id].reserve(num_banks); } -FabricBitLineBankId FabricKey::create_bl_shift_register_bank(const FabricRegionId& region_id) { +FabricBitLineBankId FabricKey::create_bl_shift_register_bank( + const FabricRegionId& region_id) { VTR_ASSERT(valid_region_id(region_id)); - + /* Create a new id */ - FabricBitLineBankId bank = FabricBitLineBankId(bl_bank_ids_[region_id].size()); + FabricBitLineBankId bank = + FabricBitLineBankId(bl_bank_ids_[region_id].size()); bl_bank_ids_[region_id].push_back(bank); bl_bank_data_ports_[region_id].emplace_back(); return bank; } -void FabricKey::add_data_port_to_bl_shift_register_bank(const FabricRegionId& region_id, - const FabricBitLineBankId& bank_id, - const openfpga::BasicPort& data_port) { +void FabricKey::add_data_port_to_bl_shift_register_bank( + const FabricRegionId& region_id, const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port) { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); bl_bank_data_ports_[region_id][bank_id].push_back(data_port); } -FabricWordLineBankId FabricKey::create_wl_shift_register_bank(const FabricRegionId& region_id) { +FabricWordLineBankId FabricKey::create_wl_shift_register_bank( + const FabricRegionId& region_id) { VTR_ASSERT(valid_region_id(region_id)); - + /* Create a new id */ - FabricWordLineBankId bank = FabricWordLineBankId(wl_bank_ids_[region_id].size()); + FabricWordLineBankId bank = + FabricWordLineBankId(wl_bank_ids_[region_id].size()); wl_bank_ids_[region_id].push_back(bank); wl_bank_data_ports_[region_id].emplace_back(); return bank; } -void FabricKey::add_data_port_to_wl_shift_register_bank(const FabricRegionId& region_id, - const FabricWordLineBankId& bank_id, - const openfpga::BasicPort& data_port) { +void FabricKey::add_data_port_to_wl_shift_register_bank( + const FabricRegionId& region_id, const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port) { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); wl_bank_data_ports_[region_id][bank_id].push_back(data_port); } /************************************************************************ - * Internal invalidators/validators + * Internal invalidators/validators ***********************************************************************/ /* Validators */ bool FabricKey::valid_region_id(const FabricRegionId& region_id) const { - return ( size_t(region_id) < region_ids_.size() ) && ( region_id == region_ids_[region_id] ); + return (size_t(region_id) < region_ids_.size()) && + (region_id == region_ids_[region_id]); } bool FabricKey::valid_key_id(const FabricKeyId& key_id) const { - return ( size_t(key_id) < key_ids_.size() ) && ( key_id == key_ids_[key_id] ); + return (size_t(key_id) < key_ids_.size()) && (key_id == key_ids_[key_id]); } bool FabricKey::valid_key_coordinate(const vtr::Point& coord) const { return coord.x() > -1 && coord.y() > -1; } -bool FabricKey::valid_bl_bank_id(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const { +bool FabricKey::valid_bl_bank_id(const FabricRegionId& region_id, + const FabricBitLineBankId& bank_id) const { if (!valid_region_id(region_id)) { return false; } - return ( size_t(bank_id) < bl_bank_ids_[region_id].size() ) && ( bank_id == bl_bank_ids_[region_id][bank_id] ); + return (size_t(bank_id) < bl_bank_ids_[region_id].size()) && + (bank_id == bl_bank_ids_[region_id][bank_id]); } -bool FabricKey::valid_wl_bank_id(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const { +bool FabricKey::valid_wl_bank_id(const FabricRegionId& region_id, + const FabricWordLineBankId& bank_id) const { if (!valid_region_id(region_id)) { return false; } - return ( size_t(bank_id) < wl_bank_ids_[region_id].size() ) && ( bank_id == wl_bank_ids_[region_id][bank_id] ); + return (size_t(bank_id) < wl_bank_ids_[region_id].size()) && + (bank_id == wl_bank_ids_[region_id][bank_id]); } diff --git a/libs/libfabrickey/src/fabric_key.h b/libs/libfabrickey/src/fabric_key.h index 45569f269..53c9f89ac 100644 --- a/libs/libfabrickey/src/fabric_key.h +++ b/libs/libfabrickey/src/fabric_key.h @@ -4,26 +4,25 @@ /******************************************************************** * This file include the declaration of fabric key *******************************************************************/ -#include -#include #include +#include +#include /* Headers from vtrutil library */ -#include "vtr_vector.h" #include "vtr_geometry.h" +#include "vtr_vector.h" /* Headers from openfpgautil library */ -#include "openfpga_port.h" - #include "fabric_key_fwd.h" +#include "openfpga_port.h" /******************************************************************** * A data structure to describe a secure key for fabric organization * A fabric may consist of multiple regions * Each region contains a number of keys - * + * * Note that: - * - each key can only be defined in one unique region + * - each key can only be defined in one unique region * * Typical usage: * -------------- @@ -38,144 +37,168 @@ * *******************************************************************/ class FabricKey { - public: /* Types */ - typedef vtr::vector::const_iterator fabric_key_iterator; - typedef vtr::vector::const_iterator fabric_region_iterator; - typedef vtr::vector::const_iterator fabric_bit_line_bank_iterator; - typedef vtr::vector::const_iterator fabric_word_line_bank_iterator; - /* Create range */ - typedef vtr::Range fabric_region_range; - typedef vtr::Range fabric_key_range; - typedef vtr::Range fabric_bit_line_bank_range; - typedef vtr::Range fabric_word_line_bank_range; - public: /* Constructors */ - FabricKey(); - public: /* Accessors: aggregates */ - fabric_key_range keys() const; - fabric_region_range regions() const; - fabric_bit_line_bank_range bl_banks(const FabricRegionId& region_id) const; - fabric_word_line_bank_range wl_banks(const FabricRegionId& region_id) const; - public: /* Public Accessors: Basic data query */ - /* Access all the keys of a region */ - std::vector region_keys(const FabricRegionId& region_id) const; + public: /* Types */ + typedef vtr::vector::const_iterator + fabric_key_iterator; + typedef vtr::vector::const_iterator + fabric_region_iterator; + typedef vtr::vector::const_iterator + fabric_bit_line_bank_iterator; + typedef vtr::vector::const_iterator + fabric_word_line_bank_iterator; + /* Create range */ + typedef vtr::Range fabric_region_range; + typedef vtr::Range fabric_key_range; + typedef vtr::Range fabric_bit_line_bank_range; + typedef vtr::Range + fabric_word_line_bank_range; - /* Access the name of a key */ - std::string key_name(const FabricKeyId& key_id) const; + public: /* Constructors */ + FabricKey(); - /* Access the value of a key */ - size_t key_value(const FabricKeyId& key_id) const; + public: /* Accessors: aggregates */ + fabric_key_range keys() const; + fabric_region_range regions() const; + fabric_bit_line_bank_range bl_banks(const FabricRegionId& region_id) const; + fabric_word_line_bank_range wl_banks(const FabricRegionId& region_id) const; - /* Access the alias of a key */ - std::string key_alias(const FabricKeyId& key_id) const; + public: /* Public Accessors: Basic data query */ + /* Access all the keys of a region */ + std::vector region_keys(const FabricRegionId& region_id) const; - /* Access the coordinate of a key */ - vtr::Point key_coordinate(const FabricKeyId& key_id) const; + /* Access the name of a key */ + std::string key_name(const FabricKeyId& key_id) const; - /* Check if there are any keys */ - bool empty() const; + /* Access the value of a key */ + size_t key_value(const FabricKeyId& key_id) const; - /* Return a list of data ports which will be driven by a BL shift register bank */ - std::vector bl_bank_data_ports(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const; + /* Access the alias of a key */ + std::string key_alias(const FabricKeyId& key_id) const; - /* Return a list of data ports which will be driven by a WL shift register bank */ - std::vector wl_bank_data_ports(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const; + /* Access the coordinate of a key */ + vtr::Point key_coordinate(const FabricKeyId& key_id) const; - public: /* Public Mutators: model-related */ + /* Check if there are any keys */ + bool empty() const; - /* Reserve a number of regions to be memory efficent */ - void reserve_regions(const size_t& num_regions); + /* Return a list of data ports which will be driven by a BL shift register + * bank */ + std::vector bl_bank_data_ports( + const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const; - /* Create a new region and add it to the library, return an id */ - FabricRegionId create_region(); + /* Return a list of data ports which will be driven by a WL shift register + * bank */ + std::vector wl_bank_data_ports( + const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const; - /* Reserve the memory space for keys under a region, to be memory efficient */ - void reserve_region_keys(const FabricRegionId& region_id, - const size_t& num_keys); + public: /* Public Mutators: model-related */ + /* Reserve a number of regions to be memory efficent */ + void reserve_regions(const size_t& num_regions); - /* Add a key to a region */ - void add_key_to_region(const FabricRegionId& region_id, - const FabricKeyId& key_id); + /* Create a new region and add it to the library, return an id */ + FabricRegionId create_region(); - /* Reserve a number of keys to be memory efficent */ - void reserve_keys(const size_t& num_keys); + /* Reserve the memory space for keys under a region, to be memory efficient */ + void reserve_region_keys(const FabricRegionId& region_id, + const size_t& num_keys); - /* Create a new key and add it to the library, return an id */ - FabricKeyId create_key(); + /* Add a key to a region */ + void add_key_to_region(const FabricRegionId& region_id, + const FabricKeyId& key_id); - /* Configure attributes of a key */ - void set_key_name(const FabricKeyId& key_id, - const std::string& name); + /* Reserve a number of keys to be memory efficent */ + void reserve_keys(const size_t& num_keys); - void set_key_value(const FabricKeyId& key_id, - const size_t& value); + /* Create a new key and add it to the library, return an id */ + FabricKeyId create_key(); - void set_key_alias(const FabricKeyId& key_id, - const std::string& alias); + /* Configure attributes of a key */ + void set_key_name(const FabricKeyId& key_id, const std::string& name); - void set_key_coordinate(const FabricKeyId& key_id, - const vtr::Point& coord); + void set_key_value(const FabricKeyId& key_id, const size_t& value); - /* Reserve a number of banks to be memory efficent */ - void reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks); - void reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks); + void set_key_alias(const FabricKeyId& key_id, const std::string& alias); - /* Create a new shift register bank for BLs and return an id */ - FabricBitLineBankId create_bl_shift_register_bank(const FabricRegionId& region_id); + void set_key_coordinate(const FabricKeyId& key_id, + const vtr::Point& coord); - /* Add a data port to a given BL shift register bank */ - void add_data_port_to_bl_shift_register_bank(const FabricRegionId& region_id, - const FabricBitLineBankId& bank_id, - const openfpga::BasicPort& data_port); + /* Reserve a number of banks to be memory efficent */ + void reserve_bl_shift_register_banks(const FabricRegionId& region_id, + const size_t& num_banks); + void reserve_wl_shift_register_banks(const FabricRegionId& region_id, + const size_t& num_banks); - /* Create a new shift register bank for WLs and return an id */ - FabricWordLineBankId create_wl_shift_register_bank(const FabricRegionId& region_id); + /* Create a new shift register bank for BLs and return an id */ + FabricBitLineBankId create_bl_shift_register_bank( + const FabricRegionId& region_id); - /* Add a data port to a given WL shift register bank */ - void add_data_port_to_wl_shift_register_bank(const FabricRegionId& region_id, - const FabricWordLineBankId& bank_id, - const openfpga::BasicPort& data_port); + /* Add a data port to a given BL shift register bank */ + void add_data_port_to_bl_shift_register_bank( + const FabricRegionId& region_id, const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port); - public: /* Public invalidators/validators */ - bool valid_region_id(const FabricRegionId& region_id) const; - bool valid_key_id(const FabricKeyId& key_id) const; - /* Identify if key coordinate is acceptable to fabric key convention */ - bool valid_key_coordinate(const vtr::Point& coord) const; - bool valid_bl_bank_id(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const; - bool valid_wl_bank_id(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const; - private: /* Internal data */ - /* Unique ids for each region */ - vtr::vector region_ids_; + /* Create a new shift register bank for WLs and return an id */ + FabricWordLineBankId create_wl_shift_register_bank( + const FabricRegionId& region_id); - /* Key ids for each region */ - vtr::vector> region_key_ids_; + /* Add a data port to a given WL shift register bank */ + void add_data_port_to_wl_shift_register_bank( + const FabricRegionId& region_id, const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port); - /* Unique ids for each key */ - vtr::vector key_ids_; + public: /* Public invalidators/validators */ + bool valid_region_id(const FabricRegionId& region_id) const; + bool valid_key_id(const FabricKeyId& key_id) const; + /* Identify if key coordinate is acceptable to fabric key convention */ + bool valid_key_coordinate(const vtr::Point& coord) const; + bool valid_bl_bank_id(const FabricRegionId& region_id, + const FabricBitLineBankId& bank_id) const; + bool valid_wl_bank_id(const FabricRegionId& region_id, + const FabricWordLineBankId& bank_id) const; - /* Names for each key */ - vtr::vector key_names_; + private: /* Internal data */ + /* Unique ids for each region */ + vtr::vector region_ids_; - /* Values for each key */ - vtr::vector key_values_; + /* Key ids for each region */ + vtr::vector> region_key_ids_; - /* Values for each key */ - vtr::vector> key_coordinates_; + /* Unique ids for each key */ + vtr::vector key_ids_; - /* Region for each key */ - vtr::vector key_regions_; + /* Names for each key */ + vtr::vector key_names_; - /* Optional alias for each key, with which a key can also be represented */ - vtr::vector key_alias_; + /* Values for each key */ + vtr::vector key_values_; - /* Unique ids for each BL shift register bank */ - vtr::vector> bl_bank_ids_; - /* Data ports to be connected to each BL shift register bank */ - vtr::vector>> bl_bank_data_ports_; + /* Values for each key */ + vtr::vector> key_coordinates_; - /* Unique ids for each WL shift register bank */ - vtr::vector> wl_bank_ids_; - /* Data ports to be connected to each WL shift register bank */ - vtr::vector>> wl_bank_data_ports_; + /* Region for each key */ + vtr::vector key_regions_; + + /* Optional alias for each key, with which a key can also be represented */ + vtr::vector key_alias_; + + /* Unique ids for each BL shift register bank */ + vtr::vector> + bl_bank_ids_; + /* Data ports to be connected to each BL shift register bank */ + vtr::vector>> + bl_bank_data_ports_; + + /* Unique ids for each WL shift register bank */ + vtr::vector> + wl_bank_ids_; + /* Data ports to be connected to each WL shift register bank */ + vtr::vector>> + wl_bank_data_ports_; }; #endif diff --git a/libs/libfabrickey/src/fabric_key_fwd.h b/libs/libfabrickey/src/fabric_key_fwd.h index 7309daa23..0c282092f 100644 --- a/libs/libfabrickey/src/fabric_key_fwd.h +++ b/libs/libfabrickey/src/fabric_key_fwd.h @@ -1,11 +1,11 @@ /************************************************************************ * A header file for FabricKey class, including critical data declaration * Please include this file only for using any TechnologyLibrary data structure - * Refer to fabric_key.h for more details + * Refer to fabric_key.h for more details ***********************************************************************/ /************************************************************************ - * Create strong id for FabricKey to avoid illegal type casting + * Create strong id for FabricKey to avoid illegal type casting ***********************************************************************/ #ifndef FABRIC_KEY_FWD_H #define FABRIC_KEY_FWD_H diff --git a/libs/libfabrickey/src/read_xml_fabric_key.cpp b/libs/libfabrickey/src/read_xml_fabric_key.cpp index 15fc61fe1..3ae4d792f 100644 --- a/libs/libfabrickey/src/read_xml_fabric_key.cpp +++ b/libs/libfabrickey/src/read_xml_fabric_key.cpp @@ -14,105 +14,111 @@ #include "vtr_time.h" /* Headers from openfpga util library */ -#include "openfpga_tokenizer.h" #include "openfpga_port_parser.h" +#include "openfpga_tokenizer.h" /* Headers from libarchfpga */ #include "arch_error.h" -#include "read_xml_util.h" - #include "read_xml_fabric_key.h" +#include "read_xml_util.h" /******************************************************************** * Parse XML codes of a to an object of FabricKey *******************************************************************/ -static -void read_xml_region_key(pugi::xml_node& xml_component_key, - const pugiutil::loc_data& loc_data, - FabricKey& fabric_key, - const FabricRegionId& fabric_region) { - +static void read_xml_region_key(pugi::xml_node& xml_component_key, + const pugiutil::loc_data& loc_data, + FabricKey& fabric_key, + const FabricRegionId& fabric_region) { /* Find the id of component key */ const size_t& id = get_attribute(xml_component_key, "id", loc_data).as_int(); if (false == fabric_key.valid_key_id(FabricKeyId(id))) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_component_key), - "Invalid 'id' attribute '%d' (in total %lu keys)!\n", - id, + "Invalid 'id' attribute '%d' (in total %lu keys)!\n", id, fabric_key.keys().size()); } VTR_ASSERT_SAFE(true == fabric_key.valid_key_id(FabricKeyId(id))); /* If we have an alias, set the value as well */ - const std::string& alias = get_attribute(xml_component_key, "alias", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(); + const std::string& alias = get_attribute(xml_component_key, "alias", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string(); if (!alias.empty()) { fabric_key.set_key_alias(FabricKeyId(id), alias); } - /* If we have the alias set, name and valus are optional then - * Otherwise, they are mandatory attributes + /* If we have the alias set, name and valus are optional then + * Otherwise, they are mandatory attributes */ - pugiutil::ReqOpt required_name_value = pugiutil::ReqOpt::OPTIONAL; + pugiutil::ReqOpt required_name_value = pugiutil::ReqOpt::OPTIONAL; if (true == alias.empty()) { required_name_value = pugiutil::ReqOpt::REQUIRED; } - const std::string& name = get_attribute(xml_component_key, "name", loc_data, required_name_value).as_string(); - const size_t& value = get_attribute(xml_component_key, "value", loc_data, required_name_value).as_int(); - + const std::string& name = + get_attribute(xml_component_key, "name", loc_data, required_name_value) + .as_string(); + const size_t& value = + get_attribute(xml_component_key, "value", loc_data, required_name_value) + .as_int(); + fabric_key.set_key_name(FabricKeyId(id), name); fabric_key.set_key_value(FabricKeyId(id), value); fabric_key.add_key_to_region(fabric_region, FabricKeyId(id)); /* Parse coordinates */ vtr::Point coord; - coord.set_x(get_attribute(xml_component_key, "column", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-1)); - coord.set_y(get_attribute(xml_component_key, "row", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-1)); + coord.set_x(get_attribute(xml_component_key, "column", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_int(-1)); + coord.set_y(get_attribute(xml_component_key, "row", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_int(-1)); if (fabric_key.valid_key_coordinate(coord)) { fabric_key.set_key_coordinate(FabricKeyId(id), coord); } } /******************************************************************** - * Parse XML codes of a under to an object of FabricKey + * Parse XML codes of a under to an object of + *FabricKey *******************************************************************/ -static -void read_xml_region_bl_shift_register_bank(pugi::xml_node& xml_bank, - const pugiutil::loc_data& loc_data, - FabricKey& fabric_key, - const FabricRegionId& fabric_region) { +static void read_xml_region_bl_shift_register_bank( + pugi::xml_node& xml_bank, const pugiutil::loc_data& loc_data, + FabricKey& fabric_key, const FabricRegionId& fabric_region) { /* Find the id of the bank */ - FabricBitLineBankId bank_id = FabricBitLineBankId(get_attribute(xml_bank, "id", loc_data).as_int()); + FabricBitLineBankId bank_id = + FabricBitLineBankId(get_attribute(xml_bank, "id", loc_data).as_int()); if (!fabric_key.valid_bl_bank_id(fabric_region, bank_id)) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bank), "Invalid 'id' attribute '%lu' (in total %lu BL banks)!\n", - size_t(bank_id), - fabric_key.bl_banks(fabric_region).size()); + size_t(bank_id), fabric_key.bl_banks(fabric_region).size()); } VTR_ASSERT_SAFE(true == fabric_key.valid_bl_bank_id(fabric_region, bank_id)); /* Parse the ports */ - std::string data_ports = get_attribute(xml_bank, "range", loc_data).as_string(); + std::string data_ports = + get_attribute(xml_bank, "range", loc_data).as_string(); /* Split with ',' if we have multiple ports */ openfpga::StringToken tokenizer(data_ports); for (const std::string& data_port : tokenizer.split(',')) { openfpga::PortParser data_port_parser(data_port); - fabric_key.add_data_port_to_bl_shift_register_bank(fabric_region, bank_id, data_port_parser.port()); + fabric_key.add_data_port_to_bl_shift_register_bank(fabric_region, bank_id, + data_port_parser.port()); } } /******************************************************************** * Parse XML codes of a to an object of FabricKey *******************************************************************/ -static -void read_xml_region_bl_shift_register_banks(pugi::xml_node& xml_bl_bank, - const pugiutil::loc_data& loc_data, - FabricKey& fabric_key, - const FabricRegionId& fabric_region) { - size_t num_banks = count_children(xml_bl_bank, "bank", loc_data, pugiutil::ReqOpt::OPTIONAL); +static void read_xml_region_bl_shift_register_banks( + pugi::xml_node& xml_bl_bank, const pugiutil::loc_data& loc_data, + FabricKey& fabric_key, const FabricRegionId& fabric_region) { + size_t num_banks = + count_children(xml_bl_bank, "bank", loc_data, pugiutil::ReqOpt::OPTIONAL); fabric_key.reserve_bl_shift_register_banks(fabric_region, num_banks); for (size_t ibank = 0; ibank < num_banks; ++ibank) { @@ -124,49 +130,50 @@ void read_xml_region_bl_shift_register_banks(pugi::xml_node& xml_bl_bank, if (xml_bank.name() != std::string("bank")) { bad_tag(xml_bank, loc_data, xml_bl_bank, {"bank"}); } - read_xml_region_bl_shift_register_bank(xml_bank, loc_data, fabric_key, fabric_region); + read_xml_region_bl_shift_register_bank(xml_bank, loc_data, fabric_key, + fabric_region); } } /******************************************************************** - * Parse XML codes of a under to an object of FabricKey + * Parse XML codes of a under to an object of + *FabricKey *******************************************************************/ -static -void read_xml_region_wl_shift_register_bank(pugi::xml_node& xml_bank, - const pugiutil::loc_data& loc_data, - FabricKey& fabric_key, - const FabricRegionId& fabric_region) { +static void read_xml_region_wl_shift_register_bank( + pugi::xml_node& xml_bank, const pugiutil::loc_data& loc_data, + FabricKey& fabric_key, const FabricRegionId& fabric_region) { /* Find the id of the bank */ - FabricWordLineBankId bank_id = FabricWordLineBankId(get_attribute(xml_bank, "id", loc_data).as_int()); + FabricWordLineBankId bank_id = + FabricWordLineBankId(get_attribute(xml_bank, "id", loc_data).as_int()); if (!fabric_key.valid_wl_bank_id(fabric_region, bank_id)) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bank), "Invalid 'id' attribute '%lu' (in total %lu WL banks)!\n", - size_t(bank_id), - fabric_key.wl_banks(fabric_region).size()); + size_t(bank_id), fabric_key.wl_banks(fabric_region).size()); } VTR_ASSERT_SAFE(true == fabric_key.valid_wl_bank_id(fabric_region, bank_id)); /* Parse the ports */ - std::string data_ports = get_attribute(xml_bank, "range", loc_data).as_string(); + std::string data_ports = + get_attribute(xml_bank, "range", loc_data).as_string(); /* Split with ',' if we have multiple ports */ openfpga::StringToken tokenizer(data_ports); for (const std::string& data_port : tokenizer.split(',')) { openfpga::PortParser data_port_parser(data_port); - fabric_key.add_data_port_to_wl_shift_register_bank(fabric_region, bank_id, data_port_parser.port()); + fabric_key.add_data_port_to_wl_shift_register_bank(fabric_region, bank_id, + data_port_parser.port()); } } /******************************************************************** * Parse XML codes of a to an object of FabricKey *******************************************************************/ -static -void read_xml_region_wl_shift_register_banks(pugi::xml_node& xml_wl_bank, - const pugiutil::loc_data& loc_data, - FabricKey& fabric_key, - const FabricRegionId& fabric_region) { - size_t num_banks = count_children(xml_wl_bank, "bank", loc_data, pugiutil::ReqOpt::OPTIONAL); +static void read_xml_region_wl_shift_register_banks( + pugi::xml_node& xml_wl_bank, const pugiutil::loc_data& loc_data, + FabricKey& fabric_key, const FabricRegionId& fabric_region) { + size_t num_banks = + count_children(xml_wl_bank, "bank", loc_data, pugiutil::ReqOpt::OPTIONAL); fabric_key.reserve_wl_shift_register_banks(fabric_region, num_banks); for (size_t ibank = 0; ibank < num_banks; ++ibank) { @@ -178,29 +185,30 @@ void read_xml_region_wl_shift_register_banks(pugi::xml_node& xml_wl_bank, if (xml_bank.name() != std::string("bank")) { bad_tag(xml_bank, loc_data, xml_wl_bank, {"bank"}); } - read_xml_region_wl_shift_register_bank(xml_bank, loc_data, fabric_key, fabric_region); + read_xml_region_wl_shift_register_bank(xml_bank, loc_data, fabric_key, + fabric_region); } } /******************************************************************** * Parse XML codes of a to an object of FabricKey *******************************************************************/ -static -void read_xml_fabric_region(pugi::xml_node& xml_region, - const pugiutil::loc_data& loc_data, - FabricKey& fabric_key) { +static void read_xml_fabric_region(pugi::xml_node& xml_region, + const pugiutil::loc_data& loc_data, + FabricKey& fabric_key) { /* Find the unique id for the region */ - const FabricRegionId& region_id = FabricRegionId(get_attribute(xml_region, "id", loc_data).as_int()); + const FabricRegionId& region_id = + FabricRegionId(get_attribute(xml_region, "id", loc_data).as_int()); if (false == fabric_key.valid_region_id(region_id)) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_region), "Invalid region id '%lu' (in total %lu regions)!\n", - size_t(region_id), - fabric_key.regions().size()); + size_t(region_id), fabric_key.regions().size()); } VTR_ASSERT_SAFE(true == fabric_key.valid_region_id(region_id)); /* Reserve memory space for the keys in the region */ - size_t num_keys = count_children(xml_region, "key", loc_data, pugiutil::ReqOpt::OPTIONAL); + size_t num_keys = + count_children(xml_region, "key", loc_data, pugiutil::ReqOpt::OPTIONAL); fabric_key.reserve_region_keys(region_id, num_keys); /* Parse the key for this region */ @@ -209,23 +217,28 @@ void read_xml_fabric_region(pugi::xml_node& xml_region, while (xml_key) { read_xml_region_key(xml_key, loc_data, fabric_key, region_id); xml_key = xml_key.next_sibling(xml_key.name()); - } + } } /* Parse the BL shift register bank for this region */ - pugi::xml_node xml_bl_bank = get_single_child(xml_region, "bl_shift_register_banks", loc_data, pugiutil::ReqOpt::OPTIONAL); - read_xml_region_bl_shift_register_banks(xml_bl_bank, loc_data, fabric_key, region_id); + pugi::xml_node xml_bl_bank = + get_single_child(xml_region, "bl_shift_register_banks", loc_data, + pugiutil::ReqOpt::OPTIONAL); + read_xml_region_bl_shift_register_banks(xml_bl_bank, loc_data, fabric_key, + region_id); /* Parse the WL shift register bank for this region */ - pugi::xml_node xml_wl_bank = get_single_child(xml_region, "wl_shift_register_banks", loc_data, pugiutil::ReqOpt::OPTIONAL); - read_xml_region_wl_shift_register_banks(xml_wl_bank, loc_data, fabric_key, region_id); + pugi::xml_node xml_wl_bank = + get_single_child(xml_region, "wl_shift_register_banks", loc_data, + pugiutil::ReqOpt::OPTIONAL); + read_xml_region_wl_shift_register_banks(xml_wl_bank, loc_data, fabric_key, + region_id); } /******************************************************************** * Parse XML codes about to an object of FabricKey *******************************************************************/ FabricKey read_xml_fabric_key(const char* key_fname) { - vtr::ScopedStartFinishTimer timer("Read Fabric Key"); FabricKey fabric_key; @@ -239,7 +252,8 @@ FabricKey read_xml_fabric_key(const char* key_fname) { pugi::xml_node xml_root = get_single_child(doc, "fabric_key", loc_data); - size_t num_regions = std::distance(xml_root.children().begin(), xml_root.children().end()); + size_t num_regions = + std::distance(xml_root.children().begin(), xml_root.children().end()); /* Reserve memory space for the region */ fabric_key.reserve_regions(num_regions); for (size_t iregion = 0; iregion < num_regions; ++iregion) { @@ -254,7 +268,8 @@ FabricKey read_xml_fabric_key(const char* key_fname) { if (xml_region.name() != std::string("region")) { bad_tag(xml_region, loc_data, xml_root, {"region"}); } - num_keys += std::distance(xml_region.children().begin(), xml_region.children().end()); + num_keys += std::distance(xml_region.children().begin(), + xml_region.children().end()); } fabric_key.reserve_keys(num_keys); @@ -271,12 +286,10 @@ FabricKey read_xml_fabric_key(const char* key_fname) { bad_tag(xml_region, loc_data, xml_root, {"region"}); } read_xml_fabric_region(xml_region, loc_data, fabric_key); - } + } } catch (pugiutil::XmlError& e) { - archfpga_throw(key_fname, e.line(), - "%s", e.what()); + archfpga_throw(key_fname, e.line(), "%s", e.what()); } - return fabric_key; + return fabric_key; } - diff --git a/libs/libfabrickey/src/write_xml_fabric_key.cpp b/libs/libfabrickey/src/write_xml_fabric_key.cpp index ffd64ea54..133c05ddd 100644 --- a/libs/libfabrickey/src/write_xml_fabric_key.cpp +++ b/libs/libfabrickey/src/write_xml_fabric_key.cpp @@ -1,9 +1,10 @@ /******************************************************************** - * This file includes functions that outputs a configuration protocol to XML format + * This file includes functions that outputs a configuration protocol to XML + *format *******************************************************************/ /* Headers from system goes first */ -#include #include +#include /* Headers from vtr util library */ #include "vtr_assert.h" @@ -14,7 +15,7 @@ #include "openfpga_digest.h" /* Headers from arch openfpga library */ -#include "write_xml_utils.h" +#include "write_xml_utils.h" /* Headers from fabrickey library */ #include "write_xml_fabric_key.h" @@ -23,13 +24,12 @@ * A writer to output a component key to XML format * * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture + * Return 1 if there are more serious bugs in the architecture * Return 2 if fail when creating files *******************************************************************/ -static -int write_xml_fabric_component_key(std::fstream& fp, - const FabricKey& fabric_key, - const FabricKeyId& component_key) { +static int write_xml_fabric_component_key(std::fstream& fp, + const FabricKey& fabric_key, + const FabricKeyId& component_key) { /* Validate the file stream */ if (false == openfpga::valid_file_stream(fp)) { return 2; @@ -49,7 +49,8 @@ int write_xml_fabric_component_key(std::fstream& fp, write_xml_attribute(fp, "value", fabric_key.key_value(component_key)); if (!fabric_key.key_alias(component_key).empty()) { - write_xml_attribute(fp, "alias", fabric_key.key_alias(component_key).c_str()); + write_xml_attribute(fp, "alias", + fabric_key.key_alias(component_key).c_str()); } vtr::Point coord = fabric_key.key_coordinate(component_key); @@ -58,7 +59,8 @@ int write_xml_fabric_component_key(std::fstream& fp, write_xml_attribute(fp, "row", coord.y()); } - fp << "/>" << "\n"; + fp << "/>" + << "\n"; return 0; } @@ -67,13 +69,11 @@ int write_xml_fabric_component_key(std::fstream& fp, * A writer to output a BL shift register bank description to XML format * * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture + * Return 1 if there are more serious bugs in the architecture * Return 2 if fail when creating files *******************************************************************/ -static -int write_xml_fabric_bl_shift_register_banks(std::fstream& fp, - const FabricKey& fabric_key, - const FabricRegionId& region) { +static int write_xml_fabric_bl_shift_register_banks( + std::fstream& fp, const FabricKey& fabric_key, const FabricRegionId& region) { /* Validate the file stream */ if (false == openfpga::valid_file_stream(fp)) { return 2; @@ -86,14 +86,15 @@ int write_xml_fabric_bl_shift_register_banks(std::fstream& fp, /* Write the root node */ openfpga::write_tab_to_file(fp, 2); - fp << "" << "\n"; + fp << "" + << "\n"; for (const auto& bank : fabric_key.bl_banks(region)) { openfpga::write_tab_to_file(fp, 3); fp << "" << "\n"; + fp << "/>" + << "\n"; } openfpga::write_tab_to_file(fp, 2); - fp << "" << "\n"; + fp << "" + << "\n"; return 0; } @@ -117,13 +120,11 @@ int write_xml_fabric_bl_shift_register_banks(std::fstream& fp, * A writer to output a WL shift register bank description to XML format * * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture + * Return 1 if there are more serious bugs in the architecture * Return 2 if fail when creating files *******************************************************************/ -static -int write_xml_fabric_wl_shift_register_banks(std::fstream& fp, - const FabricKey& fabric_key, - const FabricRegionId& region) { +static int write_xml_fabric_wl_shift_register_banks( + std::fstream& fp, const FabricKey& fabric_key, const FabricRegionId& region) { /* Validate the file stream */ if (false == openfpga::valid_file_stream(fp)) { return 2; @@ -136,14 +137,15 @@ int write_xml_fabric_wl_shift_register_banks(std::fstream& fp, /* Write the root node */ openfpga::write_tab_to_file(fp, 2); - fp << "" << "\n"; + fp << "" + << "\n"; for (const auto& bank : fabric_key.wl_banks(region)) { openfpga::write_tab_to_file(fp, 3); fp << "" << "\n"; + fp << "/>" + << "\n"; } openfpga::write_tab_to_file(fp, 2); - fp << "" << "\n"; + fp << "" + << "\n"; return 0; } @@ -167,12 +171,10 @@ int write_xml_fabric_wl_shift_register_banks(std::fstream& fp, * A writer to output a fabric key to XML format * * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture + * Return 1 if there are more serious bugs in the architecture * Return 2 if fail when creating files *******************************************************************/ -int write_xml_fabric_key(const char* fname, - const FabricKey& fabric_key) { - +int write_xml_fabric_key(const char* fname, const FabricKey& fabric_key) { vtr::ScopedStartFinishTimer timer("Write Fabric Key"); /* Create a file handler */ @@ -182,22 +184,24 @@ int write_xml_fabric_key(const char* fname, /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - + /* Write the root node */ - fp << "" << "\n"; + fp << "" + << "\n"; int err_code = 0; - /* Write region by region */ + /* Write region by region */ for (const FabricRegionId& region : fabric_key.regions()) { openfpga::write_tab_to_file(fp, 1); - fp << "\n"; + fp << "\n"; /* Write shift register banks */ write_xml_fabric_bl_shift_register_banks(fp, fabric_key, region); write_xml_fabric_wl_shift_register_banks(fp, fabric_key, region); - /* Write component by component */ + /* Write component by component */ for (const FabricKeyId& key : fabric_key.region_keys(region)) { err_code = write_xml_fabric_component_key(fp, fabric_key, key); if (0 != err_code) { @@ -206,11 +210,13 @@ int write_xml_fabric_key(const char* fname, } openfpga::write_tab_to_file(fp, 1); - fp << "" << "\n"; + fp << "" + << "\n"; } /* Finish writing the root node */ - fp << "" << "\n"; + fp << "" + << "\n"; /* Close the file stream */ fp.close(); diff --git a/libs/libfabrickey/src/write_xml_fabric_key.h b/libs/libfabrickey/src/write_xml_fabric_key.h index 985662abf..a47c2602e 100644 --- a/libs/libfabrickey/src/write_xml_fabric_key.h +++ b/libs/libfabrickey/src/write_xml_fabric_key.h @@ -5,12 +5,12 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "fabric_key.h" /******************************************************************** * Function declaration *******************************************************************/ -int write_xml_fabric_key(const char* fname, - const FabricKey& fabric_key); +int write_xml_fabric_key(const char* fname, const FabricKey& fabric_key); #endif diff --git a/libs/libfabrickey/test/test_fabric_key.cpp b/libs/libfabrickey/test/test_fabric_key.cpp index 51acfd818..014c53bef 100644 --- a/libs/libfabrickey/test/test_fabric_key.cpp +++ b/libs/libfabrickey/test/test_fabric_key.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * Unit test functions to validate the correctness of + * Unit test functions to validate the correctness of * 1. parser of data structures * 2. writer of data structures *******************************************************************/ @@ -15,20 +15,15 @@ int main(int argc, const char** argv) { /* Ensure we have only one or two argument */ VTR_ASSERT((2 == argc) || (3 == argc)); - /* Parse the fabric key from an XML file */ FabricKey test_key = read_xml_fabric_key(argv[1]); - VTR_LOG("Read the fabric key from an XML file: %s.\n", - argv[1]); + VTR_LOG("Read the fabric key from an XML file: %s.\n", argv[1]); /* Output the circuit library to an XML file * This is optional only used when there is a second argument */ - if (3 <= argc) { + if (3 <= argc) { write_xml_fabric_key(argv[2], test_key); - VTR_LOG("Echo the fabric key to an XML file: %s.\n", - argv[2]); + VTR_LOG("Echo the fabric key to an XML file: %s.\n", argv[2]); } } - - diff --git a/libs/libfpgabitstream/src/bitstream_manager.cpp b/libs/libfpgabitstream/src/bitstream_manager.cpp index 3d5052989..d82c5832f 100644 --- a/libs/libfpgabitstream/src/bitstream_manager.cpp +++ b/libs/libfpgabitstream/src/bitstream_manager.cpp @@ -1,10 +1,11 @@ /****************************************************************************** - * This file includes member functions for data structure BitstreamManager + * This file includes member functions for data structure BitstreamManager ******************************************************************************/ +#include "bitstream_manager.h" + #include #include "vtr_assert.h" -#include "bitstream_manager.h" /* begin namespace openfpga */ namespace openfpga { @@ -23,23 +24,21 @@ BitstreamManager::BitstreamManager() { * Public Accessors : Aggregates *************************************************/ /* Find all the configuration bits */ -size_t BitstreamManager::num_bits() const { - return num_bits_; -} +size_t BitstreamManager::num_bits() const { return num_bits_; } BitstreamManager::config_bit_range BitstreamManager::bits() const { - return vtr::make_range(config_bit_iterator(ConfigBitId(0), invalid_bit_ids_), - config_bit_iterator(ConfigBitId(num_bits_), invalid_bit_ids_)); + return vtr::make_range( + config_bit_iterator(ConfigBitId(0), invalid_bit_ids_), + config_bit_iterator(ConfigBitId(num_bits_), invalid_bit_ids_)); } -size_t BitstreamManager::num_blocks() const { - return num_blocks_; -} +size_t BitstreamManager::num_blocks() const { return num_blocks_; } /* Find all the configuration blocks */ BitstreamManager::config_block_range BitstreamManager::blocks() const { - return vtr::make_range(config_block_iterator(ConfigBlockId(0), invalid_block_ids_), - config_block_iterator(ConfigBlockId(num_blocks_), invalid_block_ids_)); + return vtr::make_range( + config_block_iterator(ConfigBlockId(0), invalid_block_ids_), + config_block_iterator(ConfigBlockId(num_blocks_), invalid_block_ids_)); } /****************************************************************************** @@ -52,7 +51,8 @@ bool BitstreamManager::bit_value(const ConfigBitId& bit_id) const { return '1' == bit_values_[bit_id]; } -ConfigBlockId BitstreamManager::bit_parent_block(const ConfigBitId& bit_id) const { +ConfigBlockId BitstreamManager::bit_parent_block( + const ConfigBitId& bit_id) const { /* Ensure a valid id */ VTR_ASSERT(true == valid_bit_id(bit_id)); @@ -66,26 +66,29 @@ std::string BitstreamManager::block_name(const ConfigBlockId& block_id) const { return block_names_[block_id]; } -ConfigBlockId BitstreamManager::block_parent(const ConfigBlockId& block_id) const { +ConfigBlockId BitstreamManager::block_parent( + const ConfigBlockId& block_id) const { /* Ensure the input ids are valid */ VTR_ASSERT(true == valid_block_id(block_id)); return parent_block_ids_[block_id]; } -std::vector BitstreamManager::block_children(const ConfigBlockId& block_id) const { +std::vector BitstreamManager::block_children( + const ConfigBlockId& block_id) const { /* Ensure the input ids are valid */ VTR_ASSERT(true == valid_block_id(block_id)); return child_block_ids_[block_id]; } -std::vector BitstreamManager::block_bits(const ConfigBlockId& block_id) const { +std::vector BitstreamManager::block_bits( + const ConfigBlockId& block_id) const { /* Ensure the input ids are valid */ VTR_ASSERT(true == valid_block_id(block_id)); - size_t lsb = block_bit_id_lsbs_[block_id]; - size_t length = block_bit_lengths_[block_id]; + size_t lsb = block_bit_id_lsbs_[block_id]; + size_t length = block_bit_lengths_[block_id]; std::vector bits(length, ConfigBitId::INVALID()); @@ -101,8 +104,8 @@ std::vector BitstreamManager::block_bits(const ConfigBlockId& block } /* Find the child block in a bitstream manager with a given name */ -ConfigBlockId BitstreamManager::find_child_block(const ConfigBlockId& block_id, - const std::string& child_block_name) const { +ConfigBlockId BitstreamManager::find_child_block( + const ConfigBlockId& block_id, const std::string& child_block_name) const { /* Ensure the input ids are valid */ VTR_ASSERT(true == valid_block_id(block_id)); @@ -130,14 +133,16 @@ int BitstreamManager::block_path_id(const ConfigBlockId& block_id) const { return block_path_ids_[block_id]; } -std::string BitstreamManager::block_input_net_ids(const ConfigBlockId& block_id) const { +std::string BitstreamManager::block_input_net_ids( + const ConfigBlockId& block_id) const { /* Ensure the input ids are valid */ VTR_ASSERT(true == valid_block_id(block_id)); return block_input_net_ids_[block_id]; } -std::string BitstreamManager::block_output_net_ids(const ConfigBlockId& block_id) const { +std::string BitstreamManager::block_output_net_ids( + const ConfigBlockId& block_id) const { /* Ensure the input ids are valid */ VTR_ASSERT(true == valid_block_id(block_id)); @@ -147,7 +152,8 @@ std::string BitstreamManager::block_output_net_ids(const ConfigBlockId& block_id /****************************************************************************** * Public Mutators ******************************************************************************/ -ConfigBitId BitstreamManager::add_bit(const ConfigBlockId& parent_block, const bool& bit_value) { +ConfigBitId BitstreamManager::add_bit(const ConfigBlockId& parent_block, + const bool& bit_value) { ConfigBitId bit = ConfigBitId(num_bits_); /* Add a new bit, and allocate associated data structures */ num_bits_++; @@ -159,7 +165,7 @@ ConfigBitId BitstreamManager::add_bit(const ConfigBlockId& parent_block, const b bit_parent_blocks_.push_back(parent_block); - return bit; + return bit; } void BitstreamManager::reserve_blocks(const size_t& num_blocks) { @@ -190,13 +196,13 @@ ConfigBlockId BitstreamManager::create_block() { parent_block_ids_.push_back(ConfigBlockId::INVALID()); child_block_ids_.emplace_back(); - return block; + return block; } ConfigBlockId BitstreamManager::add_block(const std::string& block_name) { ConfigBlockId block = create_block(); set_block_name(block, block_name); - + return block; } @@ -216,7 +222,8 @@ void BitstreamManager::reserve_child_blocks(const ConfigBlockId& parent_block, child_block_ids_[parent_block].reserve(num_children); } -void BitstreamManager::add_child_block(const ConfigBlockId& parent_block, const ConfigBlockId& child_block) { +void BitstreamManager::add_child_block(const ConfigBlockId& parent_block, + const ConfigBlockId& child_block) { /* Ensure the input ids are valid */ VTR_ASSERT(true == valid_block_id(parent_block)); VTR_ASSERT(true == valid_block_id(child_block)); @@ -224,8 +231,11 @@ void BitstreamManager::add_child_block(const ConfigBlockId& parent_block, const /* We should have only a parent block for each block! */ VTR_ASSERT(ConfigBlockId::INVALID() == parent_block_ids_[child_block]); - /* Ensure the child block is not in the list of children of the parent block */ - std::vector::iterator it = std::find(child_block_ids_[parent_block].begin(), child_block_ids_[parent_block].end(), child_block); + /* Ensure the child block is not in the list of children of the parent block + */ + std::vector::iterator it = + std::find(child_block_ids_[parent_block].begin(), + child_block_ids_[parent_block].end(), child_block); VTR_ASSERT(it == child_block_ids_[parent_block].end()); /* Add the child_block to the parent_block */ @@ -234,12 +244,13 @@ void BitstreamManager::add_child_block(const ConfigBlockId& parent_block, const parent_block_ids_[child_block] = parent_block; } -void BitstreamManager::add_block_bits(const ConfigBlockId& block, - const std::vector& block_bitstream) { +void BitstreamManager::add_block_bits( + const ConfigBlockId& block, const std::vector& block_bitstream) { /* Ensure the input ids are valid */ VTR_ASSERT(true == valid_block_id(block)); - /* Add the bit to the block, record anchors in bit indexing for block-level searching */ + /* Add the bit to the block, record anchors in bit indexing for block-level + * searching */ block_bit_id_lsbs_[block] = num_bits_; block_bit_lengths_[block] = block_bitstream.size(); for (const bool& bit : block_bitstream) { @@ -247,7 +258,8 @@ void BitstreamManager::add_block_bits(const ConfigBlockId& block, } } -void BitstreamManager::add_path_id_to_block(const ConfigBlockId& block, const int& path_id) { +void BitstreamManager::add_path_id_to_block(const ConfigBlockId& block, + const int& path_id) { /* Ensure the input ids are valid */ VTR_ASSERT(true == valid_block_id(block)); @@ -255,8 +267,8 @@ void BitstreamManager::add_path_id_to_block(const ConfigBlockId& block, const in block_path_ids_[block] = path_id; } -void BitstreamManager::add_input_net_id_to_block(const ConfigBlockId& block, - const std::string& input_net_id) { +void BitstreamManager::add_input_net_id_to_block( + const ConfigBlockId& block, const std::string& input_net_id) { /* Ensure the input ids are valid */ VTR_ASSERT(true == valid_block_id(block)); @@ -264,8 +276,8 @@ void BitstreamManager::add_input_net_id_to_block(const ConfigBlockId& block, block_input_net_ids_[block] = input_net_id; } -void BitstreamManager::add_output_net_id_to_block(const ConfigBlockId& block, - const std::string& output_net_id) { +void BitstreamManager::add_output_net_id_to_block( + const ConfigBlockId& block, const std::string& output_net_id) { /* Ensure the input ids are valid */ VTR_ASSERT(true == valid_block_id(block)); @@ -284,7 +296,8 @@ bool BitstreamManager::valid_block_id(const ConfigBlockId& block_id) const { return (size_t(block_id) < num_blocks_); } -bool BitstreamManager::valid_block_path_id(const ConfigBlockId& block_id) const { +bool BitstreamManager::valid_block_path_id( + const ConfigBlockId& block_id) const { return (true == valid_block_id(block_id)) && (-2 != block_path_id(block_id)); } diff --git a/libs/libfpgabitstream/src/bitstream_manager.h b/libs/libfpgabitstream/src/bitstream_manager.h index 32575c5db..aaf25b14c 100644 --- a/libs/libfpgabitstream/src/bitstream_manager.h +++ b/libs/libfpgabitstream/src/bitstream_manager.h @@ -1,244 +1,266 @@ /****************************************************************************** - * This file introduces a data structure to store bitstream-related information + * This file introduces a data structure to store bitstream-related information * * General concept * --------------- - * The idea is to create a unified data structure that stores all the configuration bits - * with proper annotation to which modules in FPGA fabric it belongs to. - * 1. It can be easily organized in fabric-dependent representation - * (generate a sequence of bitstream which exactly fit the configuration protocol of FPGA fabric) - * 2. Or it can be easily organized in fabric-independent representation (think about XML file) + * The idea is to create a unified data structure that stores all the + *configuration bits with proper annotation to which modules in FPGA fabric it + *belongs to. + * 1. It can be easily organized in fabric-dependent representation + * (generate a sequence of bitstream which exactly fit the configuration + *protocol of FPGA fabric) + * 2. Or it can be easily organized in fabric-independent representation + *(think about XML file) * - * Cross-reference + * Cross-reference * --------------- - * May be used only when you want to bind the bitstream to a specific FPGA fabric! - * If you do so, please make sure the block name is exactly same as the instance name - * of a child module in ModuleManager!!! - * The configurable modules/instances in module manager are arranged - * in the sequence to fit different configuration protocol. - * By using the link between ModuleManager and BitstreamManager, - * we can build a sequence of configuration bits to fit different configuration protocols. + * May be used only when you want to bind the bitstream to a specific FPGA + *fabric! If you do so, please make sure the block name is exactly same as the + *instance name of a child module in ModuleManager!!! The configurable + *modules/instances in module manager are arranged in the sequence to fit + *different configuration protocol. By using the link between ModuleManager and + *BitstreamManager, we can build a sequence of configuration bits to fit + *different configuration protocols. * * +------------------+ +-----------------+ * | | block_name == instance_name | | * | BitstreamManager |-------------------------------->| ModuleManager | * | | | | - * +------------------+ +-----------------+ + * +------------------+ +-----------------+ * * Restrictions: - * 1. Each block inside BitstreamManager should have only 1 parent block + * 1. Each block inside BitstreamManager should have only 1 parent block * and multiple child block - * 2. Each bit inside BitstreamManager should have only 1 parent block - * + * 2. Each bit inside BitstreamManager should have only 1 parent block + * ******************************************************************************/ #ifndef BITSTREAM_MANAGER_H #define BITSTREAM_MANAGER_H -#include #include -#include #include -#include "vtr_vector.h" +#include +#include #include "bitstream_manager_fwd.h" +#include "vtr_vector.h" /* begin namespace openfpga */ namespace openfpga { class BitstreamManager { - public: /* Type implementations */ - /* - * This class (forward delcared above) is a template used to represent a lazily calculated - * iterator of the specified ID type. The key assumption made is that the ID space is - * contiguous and can be walked by incrementing the underlying ID value. To account for - * invalid IDs, it keeps a reference to the invalid ID set and returns ID::INVALID() for - * ID values in the set. - * - * It is used to lazily create an iteration range (e.g. as returned by RRGraph::edges() RRGraph::nodes()) - * just based on the count of allocated elements (i.e. RRGraph::num_nodes_ or RRGraph::num_edges_), - * and the set of any invalid IDs (i.e. RRGraph::invalid_node_ids_, RRGraph::invalid_edge_ids_). - */ - template - class lazy_id_iterator : public std::iterator { - public: - //Since we pass ID as a template to std::iterator we need to use an explicit 'typename' - //to bring the value_type and iterator names into scope - typedef typename std::iterator::value_type value_type; - typedef typename std::iterator::iterator iterator; + public: /* Type implementations */ + /* + * This class (forward delcared above) is a template used to represent a + * lazily calculated iterator of the specified ID type. The key assumption + * made is that the ID space is contiguous and can be walked by incrementing + * the underlying ID value. To account for invalid IDs, it keeps a reference + * to the invalid ID set and returns ID::INVALID() for ID values in the set. + * + * It is used to lazily create an iteration range (e.g. as returned by + * RRGraph::edges() RRGraph::nodes()) just based on the count of allocated + * elements (i.e. RRGraph::num_nodes_ or RRGraph::num_edges_), and the set of + * any invalid IDs (i.e. RRGraph::invalid_node_ids_, + * RRGraph::invalid_edge_ids_). + */ + template + class lazy_id_iterator + : public std::iterator { + public: + // Since we pass ID as a template to std::iterator we need to use an + // explicit 'typename' to bring the value_type and iterator names into scope + typedef + typename std::iterator::value_type + value_type; + typedef + typename std::iterator::iterator + iterator; - lazy_id_iterator(value_type init, const std::unordered_set& invalid_ids) - : value_(init) - , invalid_ids_(invalid_ids) {} + lazy_id_iterator(value_type init, const std::unordered_set& invalid_ids) + : value_(init), invalid_ids_(invalid_ids) {} - //Advance to the next ID value - iterator operator++() { - value_ = ID(size_t(value_) + 1); - return *this; - } + // Advance to the next ID value + iterator operator++() { + value_ = ID(size_t(value_) + 1); + return *this; + } - //Advance to the previous ID value - iterator operator--() { - value_ = ID(size_t(value_) - 1); - return *this; - } + // Advance to the previous ID value + iterator operator--() { + value_ = ID(size_t(value_) - 1); + return *this; + } - //Dereference the iterator - value_type operator*() const { return (invalid_ids_.count(value_)) ? ID::INVALID() : value_; } + // Dereference the iterator + value_type operator*() const { + return (invalid_ids_.count(value_)) ? ID::INVALID() : value_; + } - friend bool operator==(const lazy_id_iterator lhs, const lazy_id_iterator rhs) { return lhs.value_ == rhs.value_; } - friend bool operator!=(const lazy_id_iterator lhs, const lazy_id_iterator rhs) { return !(lhs == rhs); } + friend bool operator==(const lazy_id_iterator lhs, + const lazy_id_iterator rhs) { + return lhs.value_ == rhs.value_; + } + friend bool operator!=(const lazy_id_iterator lhs, + const lazy_id_iterator rhs) { + return !(lhs == rhs); + } - private: - value_type value_; - const std::unordered_set& invalid_ids_; - }; + private: + value_type value_; + const std::unordered_set& invalid_ids_; + }; - public: /* Public constructor */ - BitstreamManager(); + public: /* Public constructor */ + BitstreamManager(); - public: /* Types and ranges */ - //Lazy iterator utility forward declaration - template - class lazy_id_iterator; + public: /* Types and ranges */ + // Lazy iterator utility forward declaration + template + class lazy_id_iterator; - typedef lazy_id_iterator config_bit_iterator; - typedef lazy_id_iterator config_block_iterator; + typedef lazy_id_iterator config_bit_iterator; + typedef lazy_id_iterator config_block_iterator; - typedef vtr::Range config_bit_range; - typedef vtr::Range config_block_range; + typedef vtr::Range config_bit_range; + typedef vtr::Range config_block_range; - public: /* Public aggregators */ - /* Find all the configuration bits */ - size_t num_bits() const; - config_bit_range bits() const; + public: /* Public aggregators */ + /* Find all the configuration bits */ + size_t num_bits() const; + config_bit_range bits() const; - size_t num_blocks() const; - config_block_range blocks() const; + size_t num_blocks() const; + config_block_range blocks() const; - public: /* Public Accessors */ - /* Find the value of bitstream */ - bool bit_value(const ConfigBitId& bit_id) const; + public: /* Public Accessors */ + /* Find the value of bitstream */ + bool bit_value(const ConfigBitId& bit_id) const; - /* Find the parent block of a configuration bit */ - ConfigBlockId bit_parent_block(const ConfigBitId& bit_id) const; + /* Find the parent block of a configuration bit */ + ConfigBlockId bit_parent_block(const ConfigBitId& bit_id) const; - /* Find a name of a block */ - std::string block_name(const ConfigBlockId& block_id) const; + /* Find a name of a block */ + std::string block_name(const ConfigBlockId& block_id) const; - /* Find the parent of a block */ - ConfigBlockId block_parent(const ConfigBlockId& block_id) const; + /* Find the parent of a block */ + ConfigBlockId block_parent(const ConfigBlockId& block_id) const; - /* Find the children of a block */ - std::vector block_children(const ConfigBlockId& block_id) const; + /* Find the children of a block */ + std::vector block_children( + const ConfigBlockId& block_id) const; - /* Find all the bits that belong to a block */ - std::vector block_bits(const ConfigBlockId& block_id) const; + /* Find all the bits that belong to a block */ + std::vector block_bits(const ConfigBlockId& block_id) const; - /* Find the child block in a bitstream manager with a given name */ - ConfigBlockId find_child_block(const ConfigBlockId& block_id, const std::string& child_block_name) const; + /* Find the child block in a bitstream manager with a given name */ + ConfigBlockId find_child_block(const ConfigBlockId& block_id, + const std::string& child_block_name) const; - /* Find path id of a block */ - int block_path_id(const ConfigBlockId& block_id) const; + /* Find path id of a block */ + int block_path_id(const ConfigBlockId& block_id) const; - /* Find input net ids of a block */ - std::string block_input_net_ids(const ConfigBlockId& block_id) const; + /* Find input net ids of a block */ + std::string block_input_net_ids(const ConfigBlockId& block_id) const; - /* Find input net ids of a block */ - std::string block_output_net_ids(const ConfigBlockId& block_id) const; + /* Find input net ids of a block */ + std::string block_output_net_ids(const ConfigBlockId& block_id) const; - public: /* Public Mutators */ - /* Add a new configuration bit to the bitstream manager */ - ConfigBitId add_bit(const ConfigBlockId& parent_block, const bool& bit_value); + public: /* Public Mutators */ + /* Add a new configuration bit to the bitstream manager */ + ConfigBitId add_bit(const ConfigBlockId& parent_block, const bool& bit_value); - /* Reserve memory for a number of clocks */ - void reserve_blocks(const size_t& num_blocks); + /* Reserve memory for a number of clocks */ + void reserve_blocks(const size_t& num_blocks); - /* Reserve memory for a number of bits */ - void reserve_bits(const size_t& num_bits); + /* Reserve memory for a number of bits */ + void reserve_bits(const size_t& num_bits); - /* Create a new block of configuration bits */ - ConfigBlockId create_block(); + /* Create a new block of configuration bits */ + ConfigBlockId create_block(); - /* Add a new block of configuration bits to the bitstream manager */ - ConfigBlockId add_block(const std::string& block_name); + /* Add a new block of configuration bits to the bitstream manager */ + ConfigBlockId add_block(const std::string& block_name); - /* Set a name for a block */ - void set_block_name(const ConfigBlockId& block_id, - const std::string& block_name); + /* Set a name for a block */ + void set_block_name(const ConfigBlockId& block_id, + const std::string& block_name); - /* Reserve child blocks for a block to be memory efficient */ - void reserve_child_blocks(const ConfigBlockId& parent_block, - const size_t& num_children); + /* Reserve child blocks for a block to be memory efficient */ + void reserve_child_blocks(const ConfigBlockId& parent_block, + const size_t& num_children); - /* Set a block as a child block of another */ - void add_child_block(const ConfigBlockId& parent_block, const ConfigBlockId& child_block); + /* Set a block as a child block of another */ + void add_child_block(const ConfigBlockId& parent_block, + const ConfigBlockId& child_block); - /* Add a bitstream to a block */ - void add_block_bits(const ConfigBlockId& block, - const std::vector& block_bitstream); + /* Add a bitstream to a block */ + void add_block_bits(const ConfigBlockId& block, + const std::vector& block_bitstream); - /* Add a path id to a block */ - void add_path_id_to_block(const ConfigBlockId& block, const int& path_id); - - /* Add an input net id to a block */ - void add_input_net_id_to_block(const ConfigBlockId& block, const std::string& input_net_id); + /* Add a path id to a block */ + void add_path_id_to_block(const ConfigBlockId& block, const int& path_id); - /* Add an output net id to a block */ - void add_output_net_id_to_block(const ConfigBlockId& block, const std::string& output_net_id); + /* Add an input net id to a block */ + void add_input_net_id_to_block(const ConfigBlockId& block, + const std::string& input_net_id); - public: /* Public Validators */ - bool valid_bit_id(const ConfigBitId& bit_id) const; + /* Add an output net id to a block */ + void add_output_net_id_to_block(const ConfigBlockId& block, + const std::string& output_net_id); - bool valid_block_id(const ConfigBlockId& block_id) const; + public: /* Public Validators */ + bool valid_bit_id(const ConfigBitId& bit_id) const; - bool valid_block_path_id(const ConfigBlockId& block_id) const; + bool valid_block_id(const ConfigBlockId& block_id) const; - private: /* Internal data */ - /* Unique id of a block of bits in the Bitstream */ - size_t num_blocks_; - std::unordered_set invalid_block_ids_; - vtr::vector block_bit_id_lsbs_; - vtr::vector block_bit_lengths_; + bool valid_block_path_id(const ConfigBlockId& block_id) const; - /* Back-annotation for the bits */ - /* Parent block of a bit in the Bitstream - * For each bit, the block name can be designed to be same as the instance name in a module - * to reflect its position in the module tree (ModuleManager) - * Note that the blocks here all unique, unlike ModuleManager where modules can be instanciated - * Therefore, this block graph can be considered as a flattened graph of ModuleGraph - */ - vtr::vector block_names_; - vtr::vector parent_block_ids_; - vtr::vector> child_block_ids_; + private: /* Internal data */ + /* Unique id of a block of bits in the Bitstream */ + size_t num_blocks_; + std::unordered_set invalid_block_ids_; + vtr::vector block_bit_id_lsbs_; + vtr::vector block_bit_lengths_; - /* The ids of the inputs of routing multiplexer blocks which is propagated to outputs - * By default, it will be -2 (which is invalid) - * A valid id starts from -1 - * -1 indicates an unused routing multiplexer. - * It will be converted to a valid id by bitstream builders) - * For used routing multiplexers, the path id will be >= 0 - * - * Note: - * -Bitstream manager will NOT check if the id is good for bitstream builders - * It just store the results - */ - vtr::vector block_path_ids_; + /* Back-annotation for the bits */ + /* Parent block of a bit in the Bitstream + * For each bit, the block name can be designed to be same as the instance + * name in a module to reflect its position in the module tree (ModuleManager) + * Note that the blocks here all unique, unlike ModuleManager where modules + * can be instanciated Therefore, this block graph can be considered as a + * flattened graph of ModuleGraph + */ + vtr::vector block_names_; + vtr::vector parent_block_ids_; + vtr::vector> child_block_ids_; - /* Net ids that are mapped to inputs and outputs of this block - * - * Note: - * -Bitstream manager will NOT check if the id is good for bitstream builders - * It just store the results - */ - vtr::vector block_input_net_ids_; - vtr::vector block_output_net_ids_; + /* The ids of the inputs of routing multiplexer blocks which is propagated to + * outputs By default, it will be -2 (which is invalid) A valid id starts from + * -1 -1 indicates an unused routing multiplexer. It will be converted to a + * valid id by bitstream builders) For used routing multiplexers, the path id + * will be >= 0 + * + * Note: + * -Bitstream manager will NOT check if the id is good for bitstream + * builders It just store the results + */ + vtr::vector block_path_ids_; - /* Unique id of a bit in the Bitstream */ - size_t num_bits_; - std::unordered_set invalid_bit_ids_; - /* value of a bit in the Bitstream */ - vtr::vector bit_values_; - vtr::vector bit_parent_blocks_; + /* Net ids that are mapped to inputs and outputs of this block + * + * Note: + * -Bitstream manager will NOT check if the id is good for bitstream + * builders It just store the results + */ + vtr::vector block_input_net_ids_; + vtr::vector block_output_net_ids_; + + /* Unique id of a bit in the Bitstream */ + size_t num_bits_; + std::unordered_set invalid_bit_ids_; + /* value of a bit in the Bitstream */ + vtr::vector bit_values_; + vtr::vector bit_parent_blocks_; }; } /* end namespace openfpga */ diff --git a/libs/libfpgabitstream/src/bitstream_manager_fwd.h b/libs/libfpgabitstream/src/bitstream_manager_fwd.h index 55a596633..43c1aa160 100644 --- a/libs/libfpgabitstream/src/bitstream_manager_fwd.h +++ b/libs/libfpgabitstream/src/bitstream_manager_fwd.h @@ -1,5 +1,5 @@ /************************************************** - * This file includes only declarations for + * This file includes only declarations for * the data structures for bitstream database * Please refer to bitstream_manager.h for more details *************************************************/ @@ -22,4 +22,4 @@ class BitstreamManager; } /* end namespace openfpga */ -#endif +#endif diff --git a/libs/libfpgabitstream/src/bitstream_manager_utils.cpp b/libs/libfpgabitstream/src/bitstream_manager_utils.cpp index 721c147d4..c80431793 100644 --- a/libs/libfpgabitstream/src/bitstream_manager_utils.cpp +++ b/libs/libfpgabitstream/src/bitstream_manager_utils.cpp @@ -3,33 +3,32 @@ * BitstreamManager * * Note: These functions are not generic enough so that they - * should NOT be a member function! + * should NOT be a member function! *******************************************************************/ #include /* Headers from vtrutil library */ -#include "vtr_assert.h" - #include "bitstream_manager_utils.h" +#include "vtr_assert.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * Recursively find the hierarchy of a block of bitstream manager - * Return a vector of the block ids, where the top-level block - * locates in the head, while the leaf block locates in the tail + * Recursively find the hierarchy of a block of bitstream manager + * Return a vector of the block ids, where the top-level block + * locates in the head, while the leaf block locates in the tail * top, next, ... , block *******************************************************************/ -std::vector find_bitstream_manager_block_hierarchy(const BitstreamManager& bitstream_manager, - const ConfigBlockId& block) { +std::vector find_bitstream_manager_block_hierarchy( + const BitstreamManager& bitstream_manager, const ConfigBlockId& block) { std::vector block_hierarchy; ConfigBlockId temp_block = block; /* Generate a tree of parent block */ while (true == bitstream_manager.valid_block_id(temp_block)) { block_hierarchy.push_back(temp_block); - /* Go to upper level */ + /* Go to upper level */ temp_block = bitstream_manager.block_parent(temp_block); } @@ -40,10 +39,11 @@ std::vector find_bitstream_manager_block_hierarchy(const Bitstrea } /******************************************************************** - * Find all the top-level blocks in a bitstream manager, + * Find all the top-level blocks in a bitstream manager, * which have no parents *******************************************************************/ -std::vector find_bitstream_manager_top_blocks(const BitstreamManager& bitstream_manager) { +std::vector find_bitstream_manager_top_blocks( + const BitstreamManager& bitstream_manager) { std::vector top_blocks; for (const ConfigBlockId& blk : bitstream_manager.blocks()) { if (ConfigBlockId::INVALID() != bitstream_manager.block_parent(blk)) { @@ -56,12 +56,14 @@ std::vector find_bitstream_manager_top_blocks(const BitstreamMana } /******************************************************************** - * Find the index of a configuration bit in the children bits of its parent block + * Find the index of a configuration bit in the children bits of its parent + *block *******************************************************************/ -size_t find_bitstream_manager_config_bit_index_in_parent_block(const BitstreamManager& bitstream_manager, - const ConfigBitId& bit_id) { +size_t find_bitstream_manager_config_bit_index_in_parent_block( + const BitstreamManager& bitstream_manager, const ConfigBitId& bit_id) { size_t curr_index = 0; - for (const ConfigBitId& cand_bit : bitstream_manager.block_bits(bitstream_manager.bit_parent_block(bit_id))) { + for (const ConfigBitId& cand_bit : bitstream_manager.block_bits( + bitstream_manager.bit_parent_block(bit_id))) { if (cand_bit == bit_id) { break; } @@ -77,9 +79,10 @@ size_t find_bitstream_manager_config_bit_index_in_parent_block(const BitstreamMa * this function will recursively visit all the child blocks * until reaching a leaf block, where we collect the number of bits *******************************************************************/ -size_t rec_find_bitstream_manager_block_sum_of_bits(const BitstreamManager& bitstream_manager, - const ConfigBlockId& block) { - /* For leaf block, return directly with the number of bits, because it has not child block */ +size_t rec_find_bitstream_manager_block_sum_of_bits( + const BitstreamManager& bitstream_manager, const ConfigBlockId& block) { + /* For leaf block, return directly with the number of bits, because it has not + * child block */ if (0 < bitstream_manager.block_bits(block).size()) { VTR_ASSERT_SAFE(bitstream_manager.block_children(block).empty()); return bitstream_manager.block_bits(block).size(); @@ -87,8 +90,10 @@ size_t rec_find_bitstream_manager_block_sum_of_bits(const BitstreamManager& bits size_t sum_of_bits = 0; /* Dive to child blocks if this block has any */ - for (const ConfigBlockId& child_block : bitstream_manager.block_children(block)) { - sum_of_bits += rec_find_bitstream_manager_block_sum_of_bits(bitstream_manager, child_block); + for (const ConfigBlockId& child_block : + bitstream_manager.block_children(block)) { + sum_of_bits += rec_find_bitstream_manager_block_sum_of_bits( + bitstream_manager, child_block); } return sum_of_bits; diff --git a/libs/libfpgabitstream/src/bitstream_manager_utils.h b/libs/libfpgabitstream/src/bitstream_manager_utils.h index e1e8b8567..f30793eb7 100644 --- a/libs/libfpgabitstream/src/bitstream_manager_utils.h +++ b/libs/libfpgabitstream/src/bitstream_manager_utils.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "bitstream_manager.h" /******************************************************************** @@ -14,16 +15,17 @@ /* begin namespace openfpga */ namespace openfpga { -std::vector find_bitstream_manager_block_hierarchy(const BitstreamManager& bitstream_manager, - const ConfigBlockId& block); +std::vector find_bitstream_manager_block_hierarchy( + const BitstreamManager& bitstream_manager, const ConfigBlockId& block); -std::vector find_bitstream_manager_top_blocks(const BitstreamManager& bitstream_manager); +std::vector find_bitstream_manager_top_blocks( + const BitstreamManager& bitstream_manager); -size_t find_bitstream_manager_config_bit_index_in_parent_block(const BitstreamManager& bitstream_manager, - const ConfigBitId& bit_id); +size_t find_bitstream_manager_config_bit_index_in_parent_block( + const BitstreamManager& bitstream_manager, const ConfigBitId& bit_id); -size_t rec_find_bitstream_manager_block_sum_of_bits(const BitstreamManager& bitstream_manager, - const ConfigBlockId& block); +size_t rec_find_bitstream_manager_block_sum_of_bits( + const BitstreamManager& bitstream_manager, const ConfigBlockId& block); } /* end namespace openfpga */ diff --git a/libs/libfpgabitstream/src/read_xml_arch_bitstream.cpp b/libs/libfpgabitstream/src/read_xml_arch_bitstream.cpp index be39c4e64..edb352fce 100644 --- a/libs/libfpgabitstream/src/read_xml_arch_bitstream.cpp +++ b/libs/libfpgabitstream/src/read_xml_arch_bitstream.cpp @@ -15,11 +15,9 @@ /* Headers from libarchfpga */ #include "arch_error.h" -#include "read_xml_util.h" - #include "openfpga_reserved_words.h" - #include "read_xml_arch_bitstream.h" +#include "read_xml_util.h" /* begin namespace openfpga */ namespace openfpga { @@ -28,14 +26,13 @@ namespace openfpga { * Parse XML codes of a to an object of BitstreamManager * This function goes recursively until we reach the leaf node *******************************************************************/ -static -void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block, - const pugiutil::loc_data& loc_data, - BitstreamManager& bitstream_manager, - const ConfigBlockId& parent_block) { - +static void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block, + const pugiutil::loc_data& loc_data, + BitstreamManager& bitstream_manager, + const ConfigBlockId& parent_block) { /* Find the name of this bitstream block */ - const std::string& block_name = get_attribute(xml_bitstream_block, "name", loc_data).as_string(); + const std::string& block_name = + get_attribute(xml_bitstream_block, "name", loc_data).as_string(); /* Create the bitstream block */ ConfigBlockId curr_block = bitstream_manager.add_block(block_name); @@ -44,10 +41,12 @@ void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block, bitstream_manager.add_child_block(parent_block, curr_block); /* Parse input nets if defined */ - pugi::xml_node xml_input_nets = get_single_child(xml_bitstream_block, "input_nets", loc_data, pugiutil::ReqOpt::OPTIONAL); + pugi::xml_node xml_input_nets = get_single_child( + xml_bitstream_block, "input_nets", loc_data, pugiutil::ReqOpt::OPTIONAL); if (xml_input_nets) { std::vector input_nets; - size_t num_input_nets = count_children(xml_input_nets, "path", loc_data, pugiutil::ReqOpt::OPTIONAL); + size_t num_input_nets = count_children(xml_input_nets, "path", loc_data, + pugiutil::ReqOpt::OPTIONAL); input_nets.resize(num_input_nets); /* Find the child paths/nets */ @@ -57,10 +56,11 @@ void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block, bad_tag(xml_input_net, loc_data, xml_input_nets, {"path"}); } const int& id = get_attribute(xml_input_net, "id", loc_data).as_int(); - const std::string& net_name = get_attribute(xml_input_net, "net_name", loc_data).as_string(); + const std::string& net_name = + get_attribute(xml_input_net, "net_name", loc_data).as_string(); VTR_ASSERT((size_t)id < input_nets.size()); - input_nets[id] = net_name; - } + input_nets[id] = net_name; + } std::string input_nets_str; bool need_splitter = false; @@ -71,14 +71,16 @@ void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block, input_nets_str += input_net; need_splitter = true; } - bitstream_manager.add_input_net_id_to_block(curr_block, input_nets_str); + bitstream_manager.add_input_net_id_to_block(curr_block, input_nets_str); } /* Parse output nets if defined */ - pugi::xml_node xml_output_nets = get_single_child(xml_bitstream_block, "output_nets", loc_data, pugiutil::ReqOpt::OPTIONAL); + pugi::xml_node xml_output_nets = get_single_child( + xml_bitstream_block, "output_nets", loc_data, pugiutil::ReqOpt::OPTIONAL); if (xml_output_nets) { std::vector output_nets; - size_t num_output_nets = count_children(xml_output_nets, "path", loc_data, pugiutil::ReqOpt::OPTIONAL); + size_t num_output_nets = count_children(xml_output_nets, "path", loc_data, + pugiutil::ReqOpt::OPTIONAL); output_nets.resize(num_output_nets); /* Find the child paths/nets */ @@ -88,10 +90,11 @@ void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block, bad_tag(xml_output_net, loc_data, xml_output_nets, {"path"}); } const int& id = get_attribute(xml_output_net, "id", loc_data).as_int(); - const std::string& net_name = get_attribute(xml_output_net, "net_name", loc_data).as_string(); + const std::string& net_name = + get_attribute(xml_output_net, "net_name", loc_data).as_string(); VTR_ASSERT((size_t)id < output_nets.size()); - output_nets[id] = net_name; - } + output_nets[id] = net_name; + } std::string output_nets_str; bool need_splitter = false; @@ -102,16 +105,20 @@ void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block, output_nets_str += output_net; need_splitter = true; } - bitstream_manager.add_output_net_id_to_block(curr_block, output_nets_str); + bitstream_manager.add_output_net_id_to_block(curr_block, output_nets_str); } /* Parse configuration bits */ - pugi::xml_node xml_bitstream = get_single_child(xml_bitstream_block, "bitstream", loc_data, pugiutil::ReqOpt::OPTIONAL); + pugi::xml_node xml_bitstream = get_single_child( + xml_bitstream_block, "bitstream", loc_data, pugiutil::ReqOpt::OPTIONAL); if (xml_bitstream) { - /* Parse path_id: -2 is an invalid value defined in the bitstream manager internally */ - const int& path_id = get_attribute(xml_bitstream, "path_id", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-2); + /* Parse path_id: -2 is an invalid value defined in the bitstream manager + * internally */ + const int& path_id = get_attribute(xml_bitstream, "path_id", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_int(-2); if (-2 < path_id) { - bitstream_manager.add_path_id_to_block(curr_block, path_id); + bitstream_manager.add_path_id_to_block(curr_block, path_id); } /* Find the child paths/nets */ @@ -127,21 +134,21 @@ void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block, /* Link the bit to parent block */ bitstream_manager.add_block_bits(curr_block, block_bits); } - + /* Go recursively: find all the child blocks and parse */ for (pugi::xml_node xml_child : xml_bitstream_block.children()) { /* We only care child bitstream blocks here */ if (xml_child.name() == std::string("bitstream_block")) { - rec_read_xml_bitstream_block(xml_child, loc_data, bitstream_manager, curr_block); + rec_read_xml_bitstream_block(xml_child, loc_data, bitstream_manager, + curr_block); } - } + } } /******************************************************************** * Parse XML codes about to an object of Bitstream *******************************************************************/ BitstreamManager read_xml_architecture_bitstream(const char* fname) { - vtr::ScopedStartFinishTimer timer("Read Architecture Bitstream file"); BitstreamManager bitstream_manager; @@ -155,11 +162,13 @@ BitstreamManager read_xml_architecture_bitstream(const char* fname) { /* Count the child */ - pugi::xml_node xml_root = get_single_child(doc, "bitstream_block", loc_data); + pugi::xml_node xml_root = + get_single_child(doc, "bitstream_block", loc_data); /* Find the name of the top block*/ - const std::string& top_block_name = get_attribute(xml_root, "name", loc_data).as_string(); - + const std::string& top_block_name = + get_attribute(xml_root, "name", loc_data).as_string(); + if (top_block_name != std::string(FPGA_TOP_MODULE_NAME)) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_root), "Top-level block must be named as '%s'!\n", @@ -169,7 +178,8 @@ BitstreamManager read_xml_architecture_bitstream(const char* fname) { /* Create the top-level block */ ConfigBlockId top_block = bitstream_manager.add_block(top_block_name); - size_t num_blks = count_children(xml_root, "bitstream_block", loc_data, pugiutil::ReqOpt::OPTIONAL); + size_t num_blks = count_children(xml_root, "bitstream_block", loc_data, + pugiutil::ReqOpt::OPTIONAL); /* Reserve bitstream blocks in the data base */ bitstream_manager.reserve_blocks(num_blks); @@ -182,15 +192,14 @@ BitstreamManager read_xml_architecture_bitstream(const char* fname) { if (xml_blk.name() != std::string("bitstream_block")) { bad_tag(xml_blk, loc_data, xml_root, {"bitstream_block"}); } - rec_read_xml_bitstream_block(xml_blk, loc_data, bitstream_manager, top_block); - } + rec_read_xml_bitstream_block(xml_blk, loc_data, bitstream_manager, + top_block); + } } catch (pugiutil::XmlError& e) { - archfpga_throw(fname, e.line(), - "%s", e.what()); + archfpga_throw(fname, e.line(), "%s", e.what()); } - return bitstream_manager; + return bitstream_manager; } } /* end namespace openfpga */ - diff --git a/libs/libfpgabitstream/src/read_xml_arch_bitstream.h b/libs/libfpgabitstream/src/read_xml_arch_bitstream.h index 0f24c802b..3e7aea42a 100644 --- a/libs/libfpgabitstream/src/read_xml_arch_bitstream.h +++ b/libs/libfpgabitstream/src/read_xml_arch_bitstream.h @@ -4,9 +4,9 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "pugixml_util.hpp" -#include "pugixml.hpp" #include "bitstream_manager.h" +#include "pugixml.hpp" +#include "pugixml_util.hpp" /******************************************************************** * Function declaration diff --git a/libs/libfpgabitstream/src/report_arch_bitstream_distribution.cpp b/libs/libfpgabitstream/src/report_arch_bitstream_distribution.cpp index 55e344e3f..51a002528 100644 --- a/libs/libfpgabitstream/src/report_arch_bitstream_distribution.cpp +++ b/libs/libfpgabitstream/src/report_arch_bitstream_distribution.cpp @@ -11,13 +11,11 @@ #include "vtr_time.h" /* Headers from openfpgautil library */ +#include "bitstream_manager_utils.h" #include "openfpga_digest.h" +#include "openfpga_reserved_words.h" #include "openfpga_tokenizer.h" #include "openfpga_version.h" - -#include "openfpga_reserved_words.h" - -#include "bitstream_manager_utils.h" #include "report_arch_bitstream_distribution.h" /* begin namespace openfpga */ @@ -26,17 +24,15 @@ namespace openfpga { /******************************************************************** * Recursively report the bitstream distribution of a block to a file * This function will use a Depth-First Search in outputting bitstream - * for each block + * for each block * For block with child blocks, we visit each child recursively - * The reporting can be stopped at a given maximum hierarchy level + * The reporting can be stopped at a given maximum hierarchy level * which is used to limit the length of the report *******************************************************************/ -static -void rec_report_block_bitstream_distribution_to_xml_file(std::fstream& fp, - const BitstreamManager& bitstream_manager, - const ConfigBlockId& block, - const size_t& max_hierarchy_level, - const size_t& hierarchy_level) { +static void rec_report_block_bitstream_distribution_to_xml_file( + std::fstream& fp, const BitstreamManager& bitstream_manager, + const ConfigBlockId& block, const size_t& max_hierarchy_level, + const size_t& hierarchy_level) { valid_file_stream(fp); if (hierarchy_level > max_hierarchy_level) { @@ -46,33 +42,37 @@ void rec_report_block_bitstream_distribution_to_xml_file(std::fstream& fp, /* Write the bitstream distribution of this block */ write_tab_to_file(fp, hierarchy_level); fp << "" << std::endl; /* Dive to child blocks if this block has any */ - for (const ConfigBlockId& child_block : bitstream_manager.block_children(block)) { - rec_report_block_bitstream_distribution_to_xml_file(fp, bitstream_manager, child_block, - max_hierarchy_level, hierarchy_level + 1); + for (const ConfigBlockId& child_block : + bitstream_manager.block_children(block)) { + rec_report_block_bitstream_distribution_to_xml_file( + fp, bitstream_manager, child_block, max_hierarchy_level, + hierarchy_level + 1); } write_tab_to_file(fp, hierarchy_level); - fp << "" <" << std::endl; } /******************************************************************** * Report the distribution of bitstream by blocks, e.g., the number of * configuration bits per SB/CB/CLB - * This function can generate a report to a file + * This function can generate a report to a file * - * Notes: + * Notes: * - The output format is a table whose format is compatible with RST files *******************************************************************/ -int report_architecture_bitstream_distribution(std::fstream& fp, - const BitstreamManager& bitstream_manager, - const size_t& max_hierarchy_level, - const size_t& hierarchy_level) { - std::string timer_message = std::string("Report architecture bitstream distribution"); +int report_architecture_bitstream_distribution( + std::fstream& fp, const BitstreamManager& bitstream_manager, + const size_t& max_hierarchy_level, const size_t& hierarchy_level) { + std::string timer_message = + std::string("Report architecture bitstream distribution"); vtr::ScopedStartFinishTimer timer(timer_message); /* Check the file stream */ @@ -80,18 +80,21 @@ int report_architecture_bitstream_distribution(std::fstream& fp, int curr_level = hierarchy_level; write_tab_to_file(fp, curr_level); - fp << "" <" << std::endl; /* Find the top block, which has not parents */ - std::vector top_block = find_bitstream_manager_top_blocks(bitstream_manager); + std::vector top_block = + find_bitstream_manager_top_blocks(bitstream_manager); /* Make sure we have only 1 top block */ VTR_ASSERT(1 == top_block.size()); /* Write bitstream, block by block, in a recursive way */ - rec_report_block_bitstream_distribution_to_xml_file(fp, bitstream_manager, top_block[0], max_hierarchy_level + 2, curr_level + 1); + rec_report_block_bitstream_distribution_to_xml_file( + fp, bitstream_manager, top_block[0], max_hierarchy_level + 2, + curr_level + 1); write_tab_to_file(fp, curr_level); - fp << "" <" << std::endl; return 0; } diff --git a/libs/libfpgabitstream/src/report_arch_bitstream_distribution.h b/libs/libfpgabitstream/src/report_arch_bitstream_distribution.h index 975e44a18..7cd8a689e 100644 --- a/libs/libfpgabitstream/src/report_arch_bitstream_distribution.h +++ b/libs/libfpgabitstream/src/report_arch_bitstream_distribution.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "bitstream_manager.h" /******************************************************************** @@ -14,10 +15,9 @@ /* begin namespace openfpga */ namespace openfpga { -int report_architecture_bitstream_distribution(std::fstream& fp, - const BitstreamManager& bitstream_manager, - const size_t& max_hierarchy_level, - const size_t& hierarchy_level); +int report_architecture_bitstream_distribution( + std::fstream& fp, const BitstreamManager& bitstream_manager, + const size_t& max_hierarchy_level, const size_t& hierarchy_level); } /* end namespace openfpga */ diff --git a/libs/libfpgabitstream/src/write_xml_arch_bitstream.cpp b/libs/libfpgabitstream/src/write_xml_arch_bitstream.cpp index 0c6c5fe49..6314afe62 100644 --- a/libs/libfpgabitstream/src/write_xml_arch_bitstream.cpp +++ b/libs/libfpgabitstream/src/write_xml_arch_bitstream.cpp @@ -12,12 +12,10 @@ #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" -#include "openfpga_tokenizer.h" - -#include "openfpga_reserved_words.h" - #include "bitstream_manager_utils.h" +#include "openfpga_digest.h" +#include "openfpga_reserved_words.h" +#include "openfpga_tokenizer.h" #include "write_xml_arch_bitstream.h" /* begin namespace openfpga */ @@ -26,20 +24,19 @@ namespace openfpga { /******************************************************************** * This function write header information to a bitstream file *******************************************************************/ -static -void write_bitstream_xml_file_head(std::fstream& fp, - const bool& include_time_stamp) { +static void write_bitstream_xml_file_head(std::fstream& fp, + const bool& include_time_stamp) { valid_file_stream(fp); - + fp << "" << std::endl; @@ -49,38 +46,39 @@ void write_bitstream_xml_file_head(std::fstream& fp, /******************************************************************** * Recursively write the bitstream of a block to a xml file * This function will use a Depth-First Search in outputting bitstream - * for each block + * for each block * 1. For block with bits as children, we will output the XML lines - * 2. For block without bits/child blocks, we can return + * 2. For block without bits/child blocks, we can return * 3. For block with child blocks, we visit each child recursively *******************************************************************/ -static -void rec_write_block_bitstream_to_xml_file(std::fstream& fp, - const BitstreamManager& bitstream_manager, - const ConfigBlockId& block, - const size_t& hierarchy_level) { +static void rec_write_block_bitstream_to_xml_file( + std::fstream& fp, const BitstreamManager& bitstream_manager, + const ConfigBlockId& block, const size_t& hierarchy_level) { valid_file_stream(fp); /* Write the bits of this block */ write_tab_to_file(fp, hierarchy_level); fp << "" << std::endl; /* Dive to child blocks if this block has any */ - for (const ConfigBlockId& child_block : bitstream_manager.block_children(block)) { - rec_write_block_bitstream_to_xml_file(fp, bitstream_manager, child_block, hierarchy_level + 1); + for (const ConfigBlockId& child_block : + bitstream_manager.block_children(block)) { + rec_write_block_bitstream_to_xml_file(fp, bitstream_manager, child_block, + hierarchy_level + 1); } - + if (0 == bitstream_manager.block_bits(block).size()) { write_tab_to_file(fp, hierarchy_level); - fp << "" <" << std::endl; return; } - std::vector block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, block); - + std::vector block_hierarchy = + find_bitstream_manager_block_hierarchy(bitstream_manager, block); + /* Output hierarchy of this parent*/ write_tab_to_file(fp, hierarchy_level + 1); fp << "" << std::endl; @@ -101,7 +99,8 @@ void rec_write_block_bitstream_to_xml_file(std::fstream& fp, fp << "\n"; size_t path_counter = 0; /* Split with space */ - StringToken input_net_tokenizer(bitstream_manager.block_input_net_ids(block)); + StringToken input_net_tokenizer( + bitstream_manager.block_input_net_ids(block)); for (const std::string& net : input_net_tokenizer.split(std::string(" "))) { write_tab_to_file(fp, hierarchy_level + 2); fp << "\n"; size_t path_counter = 0; /* Split with space */ - StringToken output_net_tokenizer(bitstream_manager.block_output_net_ids(block)); - for (const std::string& net : output_net_tokenizer.split(std::string(" "))) { + StringToken output_net_tokenizer( + bitstream_manager.block_output_net_ids(block)); + for (const std::string& net : + output_net_tokenizer.split(std::string(" "))) { write_tab_to_file(fp, hierarchy_level + 2); fp << "" << std::endl; bit_counter++; @@ -158,32 +161,37 @@ void rec_write_block_bitstream_to_xml_file(std::fstream& fp, fp << "" << std::endl; write_tab_to_file(fp, hierarchy_level); - fp << "" <" << std::endl; } /******************************************************************** - * Write the bitstream to a file without binding to the configuration + * Write the bitstream to a file without binding to the configuration * procotols of a given FPGA fabric in XML format * - * Notes: + * Notes: * This is a very generic representation for bitstream that are implemented - * by VPR engine. It shows the bitstream for each blocks in the FPGA + * by VPR engine. It shows the bitstream for each blocks in the FPGA * architecture that users are modeling. - * This function can be used to: + * This function can be used to: * 1. Debug the bitstream decoding to see if there is any bug - * 2. Create an intermediate file to reorganize a bitstream for + * 2. Create an intermediate file to reorganize a bitstream for * specific FPGAs - * 3. TODO: support FASM format + * 3. TODO: support FASM format *******************************************************************/ void write_xml_architecture_bitstream(const BitstreamManager& bitstream_manager, const std::string& fname, const bool& include_time_stamp) { /* Ensure that we have a valid file name */ if (true == fname.empty()) { - VTR_LOG_ERROR("Received empty file name to output bitstream!\n\tPlease specify a valid file name.\n"); + VTR_LOG_ERROR( + "Received empty file name to output bitstream!\n\tPlease specify a valid " + "file name.\n"); } - std::string timer_message = std::string("Write ") + std::to_string(bitstream_manager.bits().size()) + std::string(" architecture independent bitstream into XML file '") + fname + std::string("'"); + std::string timer_message = + std::string("Write ") + std::to_string(bitstream_manager.bits().size()) + + std::string(" architecture independent bitstream into XML file '") + fname + + std::string("'"); vtr::ScopedStartFinishTimer timer(timer_message); /* Create the file stream */ @@ -196,7 +204,8 @@ void write_xml_architecture_bitstream(const BitstreamManager& bitstream_manager, write_bitstream_xml_file_head(fp, include_time_stamp); /* Find the top block, which has not parents */ - std::vector top_block = find_bitstream_manager_top_blocks(bitstream_manager); + std::vector top_block = + find_bitstream_manager_top_blocks(bitstream_manager); /* Make sure we have only 1 top block */ VTR_ASSERT(1 == top_block.size()); diff --git a/libs/libfpgabitstream/src/write_xml_arch_bitstream.h b/libs/libfpgabitstream/src/write_xml_arch_bitstream.h index 9a93280b4..cc6817aa8 100644 --- a/libs/libfpgabitstream/src/write_xml_arch_bitstream.h +++ b/libs/libfpgabitstream/src/write_xml_arch_bitstream.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "bitstream_manager.h" /******************************************************************** diff --git a/libs/libfpgabitstream/test/test_arch_bitstream.cpp b/libs/libfpgabitstream/test/test_arch_bitstream.cpp index 0f94353f3..f46945c02 100644 --- a/libs/libfpgabitstream/test/test_arch_bitstream.cpp +++ b/libs/libfpgabitstream/test/test_arch_bitstream.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * Unit test functions to validate the correctness of + * Unit test functions to validate the correctness of * 1. parser of data structures * 2. writer of data structures *******************************************************************/ @@ -10,22 +10,22 @@ /* Headers from fabric key */ #include "read_xml_arch_bitstream.h" -#include "write_xml_arch_bitstream.h" #include "report_arch_bitstream_distribution.h" +#include "write_xml_arch_bitstream.h" int main(int argc, const char** argv) { /* Ensure we have only one or two or 3 argument */ VTR_ASSERT((2 == argc) || (3 == argc) || (4 == argc) || (5 == argc)); /* Parse the bitstream from an XML file */ - openfpga::BitstreamManager test_bitstream = openfpga::read_xml_architecture_bitstream(argv[1]); - VTR_LOG("Read the bitstream from an XML file: %s.\n", - argv[1]); + openfpga::BitstreamManager test_bitstream = + openfpga::read_xml_architecture_bitstream(argv[1]); + VTR_LOG("Read the bitstream from an XML file: %s.\n", argv[1]); /* Output the bitstream database to an XML file * This is optional only used when there is a second argument */ - if (3 <= argc) { + if (3 <= argc) { openfpga::write_xml_architecture_bitstream(test_bitstream, argv[2], true); VTR_LOG("Echo the bitstream (with time stamp) to an XML file: %s.\n", argv[2]); @@ -36,16 +36,13 @@ int main(int argc, const char** argv) { /* Output the bitstream distribution to an XML file * This is optional only used when there is a third argument */ - if (4 <= argc) { + if (4 <= argc) { /* Create the file stream */ std::fstream fp; fp.open(argv[3], std::fstream::out | std::fstream::trunc); - openfpga::report_architecture_bitstream_distribution(fp, test_bitstream, 1, 0); - VTR_LOG("Echo the bitstream distribution to an XML file: %s.\n", - argv[3]); + openfpga::report_architecture_bitstream_distribution(fp, test_bitstream, 1, + 0); + VTR_LOG("Echo the bitstream distribution to an XML file: %s.\n", argv[3]); } - } - - diff --git a/libs/libini/src/ini.h b/libs/libini/src/ini.h old mode 100755 new mode 100644 index 3a2040ce1..2aec714ba --- a/libs/libini/src/ini.h +++ b/libs/libini/src/ini.h @@ -2,22 +2,23 @@ * The MIT License (MIT) * Copyright (c) 2018 Danijel Durakovic * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is furnished to do - * so, subject to the following conditions: + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. * */ @@ -83,673 +84,544 @@ #ifndef MINI_INI_H_ #define MINI_INI_H_ -#include -#include -#include -#include -#include -#include -#include -#include #include -namespace mINI -{ -namespace INIStringUtil -{ +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mINI { +namespace INIStringUtil { const std::string whitespaceDelimiters = " \t\n\r\f\v"; -inline void trim(std::string &str) -{ - str.erase(str.find_last_not_of(whitespaceDelimiters) + 1); - str.erase(0, str.find_first_not_of(whitespaceDelimiters)); +inline void trim(std::string &str) { + str.erase(str.find_last_not_of(whitespaceDelimiters) + 1); + str.erase(0, str.find_first_not_of(whitespaceDelimiters)); } #ifndef MINI_CASE_SENSITIVE -inline void toLower(std::string &str) -{ - std::transform(str.begin(), str.end(), str.begin(), ::tolower); +inline void toLower(std::string &str) { + std::transform(str.begin(), str.end(), str.begin(), ::tolower); } #endif -inline void replace(std::string &str, std::string const &a, std::string const &b) -{ - if (!a.empty()) - { - std::size_t pos = 0; - while ((pos = str.find(a, pos)) != std::string::npos) - { - str.replace(pos, a.size(), b); - pos += b.size(); - } - } +inline void replace(std::string &str, std::string const &a, + std::string const &b) { + if (!a.empty()) { + std::size_t pos = 0; + while ((pos = str.find(a, pos)) != std::string::npos) { + str.replace(pos, a.size(), b); + pos += b.size(); + } + } } #ifdef _WIN32 const std::string endl = "\r\n"; #else const std::string endl = "\n"; #endif -} // namespace INIStringUtil +} // namespace INIStringUtil template -class INIMap -{ -private: - using T_DataIndexMap = std::unordered_map; - using T_DataItem = std::pair; - using T_DataContainer = std::vector; - using T_MultiArgs = typename std::vector>; +class INIMap { + private: + using T_DataIndexMap = std::unordered_map; + using T_DataItem = std::pair; + using T_DataContainer = std::vector; + using T_MultiArgs = typename std::vector>; - T_DataIndexMap dataIndexMap; - T_DataContainer data; + T_DataIndexMap dataIndexMap; + T_DataContainer data; - inline std::size_t setEmpty(std::string &key) - { - std::size_t index = data.size(); - dataIndexMap[key] = index; - data.emplace_back(key, T()); - return index; - } + inline std::size_t setEmpty(std::string &key) { + std::size_t index = data.size(); + dataIndexMap[key] = index; + data.emplace_back(key, T()); + return index; + } -public: - using const_iterator = typename T_DataContainer::const_iterator; + public: + using const_iterator = typename T_DataContainer::const_iterator; - INIMap() {} + INIMap() {} - INIMap(INIMap const &other) - { - std::size_t data_size = other.data.size(); - for (std::size_t i = 0; i < data_size; ++i) - { - auto const &key = other.data[i].first; - auto const &obj = other.data[i].second; - data.emplace_back(key, obj); - } - dataIndexMap = T_DataIndexMap(other.dataIndexMap); - } + INIMap(INIMap const &other) { + std::size_t data_size = other.data.size(); + for (std::size_t i = 0; i < data_size; ++i) { + auto const &key = other.data[i].first; + auto const &obj = other.data[i].second; + data.emplace_back(key, obj); + } + dataIndexMap = T_DataIndexMap(other.dataIndexMap); + } - T &operator[](std::string key) - { - INIStringUtil::trim(key); + T &operator[](std::string key) { + INIStringUtil::trim(key); #ifndef MINI_CASE_SENSITIVE - INIStringUtil::toLower(key); + INIStringUtil::toLower(key); #endif - auto it = dataIndexMap.find(key); - bool hasIt = (it != dataIndexMap.end()); - std::size_t index = (hasIt) ? it->second : setEmpty(key); - return data[index].second; - } - T get(std::string key) const - { - INIStringUtil::trim(key); + auto it = dataIndexMap.find(key); + bool hasIt = (it != dataIndexMap.end()); + std::size_t index = (hasIt) ? it->second : setEmpty(key); + return data[index].second; + } + T get(std::string key) const { + INIStringUtil::trim(key); #ifndef MINI_CASE_SENSITIVE - INIStringUtil::toLower(key); + INIStringUtil::toLower(key); #endif - auto it = dataIndexMap.find(key); - if (it == dataIndexMap.end()) - { - return T(); - } - return T(data[it->second].second); - } - bool has(std::string key) const - { - INIStringUtil::trim(key); + auto it = dataIndexMap.find(key); + if (it == dataIndexMap.end()) { + return T(); + } + return T(data[it->second].second); + } + bool has(std::string key) const { + INIStringUtil::trim(key); #ifndef MINI_CASE_SENSITIVE - INIStringUtil::toLower(key); + INIStringUtil::toLower(key); #endif - return (dataIndexMap.count(key) == 1); - } - void set(std::string key, T obj) - { - INIStringUtil::trim(key); + return (dataIndexMap.count(key) == 1); + } + void set(std::string key, T obj) { + INIStringUtil::trim(key); #ifndef MINI_CASE_SENSITIVE - INIStringUtil::toLower(key); + INIStringUtil::toLower(key); #endif - auto it = dataIndexMap.find(key); - if (it != dataIndexMap.end()) - { - data[it->second].second = obj; - } - else - { - dataIndexMap[key] = data.size(); - data.emplace_back(key, obj); - } - } - void set(T_MultiArgs const &multiArgs) - { - for (auto const &it : multiArgs) - { - auto const &key = it.first; - auto const &obj = it.second; - set(key, obj); - } - } - bool remove(std::string key) - { - INIStringUtil::trim(key); + auto it = dataIndexMap.find(key); + if (it != dataIndexMap.end()) { + data[it->second].second = obj; + } else { + dataIndexMap[key] = data.size(); + data.emplace_back(key, obj); + } + } + void set(T_MultiArgs const &multiArgs) { + for (auto const &it : multiArgs) { + auto const &key = it.first; + auto const &obj = it.second; + set(key, obj); + } + } + bool remove(std::string key) { + INIStringUtil::trim(key); #ifndef MINI_CASE_SENSITIVE - INIStringUtil::toLower(key); + INIStringUtil::toLower(key); #endif - auto it = dataIndexMap.find(key); - if (it != dataIndexMap.end()) - { - std::size_t index = it->second; - data.erase(data.begin() + index); - dataIndexMap.erase(it); - for (auto &it2 : dataIndexMap) - { - auto &vi = it2.second; - if (vi > index) - { - vi--; - } - } - return true; - } - return false; - } - void clear() - { - data.clear(); - dataIndexMap.clear(); - } - std::size_t size() const - { - return data.size(); - } - const_iterator begin() const { return data.begin(); } - const_iterator end() const { return data.end(); } + auto it = dataIndexMap.find(key); + if (it != dataIndexMap.end()) { + std::size_t index = it->second; + data.erase(data.begin() + index); + dataIndexMap.erase(it); + for (auto &it2 : dataIndexMap) { + auto &vi = it2.second; + if (vi > index) { + vi--; + } + } + return true; + } + return false; + } + void clear() { + data.clear(); + dataIndexMap.clear(); + } + std::size_t size() const { return data.size(); } + const_iterator begin() const { return data.begin(); } + const_iterator end() const { return data.end(); } }; using INIStructure = INIMap>; -namespace INIParser -{ +namespace INIParser { using T_ParseValues = std::pair; -enum class PDataType : char -{ - PDATA_NONE, - PDATA_COMMENT, - PDATA_SECTION, - PDATA_KEYVALUE, - PDATA_UNKNOWN +enum class PDataType : char { + PDATA_NONE, + PDATA_COMMENT, + PDATA_SECTION, + PDATA_KEYVALUE, + PDATA_UNKNOWN }; -inline PDataType parseLine(std::string line, T_ParseValues &parseData) -{ - parseData.first.clear(); - parseData.second.clear(); - INIStringUtil::trim(line); - if (line.empty()) - { - return PDataType::PDATA_NONE; - } - char firstCharacter = line[0]; - if (firstCharacter == ';') - { - return PDataType::PDATA_COMMENT; - } - if (firstCharacter == '[') - { - auto commentAt = line.find_first_of(';'); - if (commentAt != std::string::npos) - { - line = line.substr(0, commentAt); - } - auto closingBracketAt = line.find_last_of(']'); - if (closingBracketAt != std::string::npos) - { - auto section = line.substr(1, closingBracketAt - 1); - INIStringUtil::trim(section); - parseData.first = section; - return PDataType::PDATA_SECTION; - } - } - auto lineNorm = line; - INIStringUtil::replace(lineNorm, "\\=", " "); - auto equalsAt = lineNorm.find_first_of('='); - if (equalsAt != std::string::npos) - { - auto key = line.substr(0, equalsAt); - INIStringUtil::trim(key); - INIStringUtil::replace(key, "\\=", "="); - auto value = line.substr(equalsAt + 1); - INIStringUtil::trim(value); - parseData.first = key; - parseData.second = value; - return PDataType::PDATA_KEYVALUE; - } - return PDataType::PDATA_UNKNOWN; +inline PDataType parseLine(std::string line, T_ParseValues &parseData) { + parseData.first.clear(); + parseData.second.clear(); + INIStringUtil::trim(line); + if (line.empty()) { + return PDataType::PDATA_NONE; + } + char firstCharacter = line[0]; + if (firstCharacter == ';') { + return PDataType::PDATA_COMMENT; + } + if (firstCharacter == '[') { + auto commentAt = line.find_first_of(';'); + if (commentAt != std::string::npos) { + line = line.substr(0, commentAt); + } + auto closingBracketAt = line.find_last_of(']'); + if (closingBracketAt != std::string::npos) { + auto section = line.substr(1, closingBracketAt - 1); + INIStringUtil::trim(section); + parseData.first = section; + return PDataType::PDATA_SECTION; + } + } + auto lineNorm = line; + INIStringUtil::replace(lineNorm, "\\=", " "); + auto equalsAt = lineNorm.find_first_of('='); + if (equalsAt != std::string::npos) { + auto key = line.substr(0, equalsAt); + INIStringUtil::trim(key); + INIStringUtil::replace(key, "\\=", "="); + auto value = line.substr(equalsAt + 1); + INIStringUtil::trim(value); + parseData.first = key; + parseData.second = value; + return PDataType::PDATA_KEYVALUE; + } + return PDataType::PDATA_UNKNOWN; } -} // namespace INIParser +} // namespace INIParser -class INIReader -{ -public: - using T_LineData = std::vector; - using T_LineDataPtr = std::shared_ptr; +class INIReader { + public: + using T_LineData = std::vector; + using T_LineDataPtr = std::shared_ptr; -private: - std::ifstream fileReadStream; - T_LineDataPtr lineData; + private: + std::ifstream fileReadStream; + T_LineDataPtr lineData; - T_LineData readFile() - { - std::string fileContents; - fileReadStream.seekg(0, std::ios::end); - fileContents.resize(fileReadStream.tellg()); - fileReadStream.seekg(0, std::ios::beg); - std::size_t fileSize = fileContents.size(); - fileReadStream.read(&fileContents[0], fileSize); - fileReadStream.close(); - T_LineData output; - if (fileSize == 0) - { - return output; - } - std::string buffer; - buffer.reserve(50); - for (std::size_t i = 0; i < fileSize; ++i) - { - char &c = fileContents[i]; - if (c == '\n') - { - output.emplace_back(buffer); - buffer.clear(); - continue; - } - if (c != '\0' && c != '\r') - { - buffer += c; - } - } - output.emplace_back(buffer); - return output; - } + T_LineData readFile() { + std::string fileContents; + fileReadStream.seekg(0, std::ios::end); + fileContents.resize(fileReadStream.tellg()); + fileReadStream.seekg(0, std::ios::beg); + std::size_t fileSize = fileContents.size(); + fileReadStream.read(&fileContents[0], fileSize); + fileReadStream.close(); + T_LineData output; + if (fileSize == 0) { + return output; + } + std::string buffer; + buffer.reserve(50); + for (std::size_t i = 0; i < fileSize; ++i) { + char &c = fileContents[i]; + if (c == '\n') { + output.emplace_back(buffer); + buffer.clear(); + continue; + } + if (c != '\0' && c != '\r') { + buffer += c; + } + } + output.emplace_back(buffer); + return output; + } -public: - INIReader(std::string const &filename, bool keepLineData = false) - { - fileReadStream.open(filename, std::ios::in | std::ios::binary); - if (keepLineData) - { - lineData = std::make_shared(); - } - } - ~INIReader() {} + public: + INIReader(std::string const &filename, bool keepLineData = false) { + fileReadStream.open(filename, std::ios::in | std::ios::binary); + if (keepLineData) { + lineData = std::make_shared(); + } + } + ~INIReader() {} - bool operator>>(INIStructure &data) - { - if (!fileReadStream.is_open()) - { - return false; - } - T_LineData fileLines = readFile(); - std::string section; - bool inSection = false; - INIParser::T_ParseValues parseData; - for (auto const &line : fileLines) - { - auto parseResult = INIParser::parseLine(line, parseData); - if (parseResult == INIParser::PDataType::PDATA_SECTION) - { - inSection = true; - data[section = parseData.first]; - } - else if (inSection && parseResult == INIParser::PDataType::PDATA_KEYVALUE) - { - auto const &key = parseData.first; - auto const &value = parseData.second; - data[section][key] = value; - } - if (lineData && parseResult != INIParser::PDataType::PDATA_UNKNOWN) - { - if (parseResult == INIParser::PDataType::PDATA_KEYVALUE && !inSection) - { - continue; - } - lineData->emplace_back(line); - } - } - return true; - } - T_LineDataPtr getLines() - { - return lineData; - } + bool operator>>(INIStructure &data) { + if (!fileReadStream.is_open()) { + return false; + } + T_LineData fileLines = readFile(); + std::string section; + bool inSection = false; + INIParser::T_ParseValues parseData; + for (auto const &line : fileLines) { + auto parseResult = INIParser::parseLine(line, parseData); + if (parseResult == INIParser::PDataType::PDATA_SECTION) { + inSection = true; + data[section = parseData.first]; + } else if (inSection && + parseResult == INIParser::PDataType::PDATA_KEYVALUE) { + auto const &key = parseData.first; + auto const &value = parseData.second; + data[section][key] = value; + } + if (lineData && parseResult != INIParser::PDataType::PDATA_UNKNOWN) { + if (parseResult == INIParser::PDataType::PDATA_KEYVALUE && !inSection) { + continue; + } + lineData->emplace_back(line); + } + } + return true; + } + T_LineDataPtr getLines() { return lineData; } }; -class INIGenerator -{ -private: - std::ofstream fileWriteStream; +class INIGenerator { + private: + std::ofstream fileWriteStream; -public: - bool prettyPrint = false; + public: + bool prettyPrint = false; - INIGenerator(std::string const &filename) - { - fileWriteStream.open(filename, std::ios::out | std::ios::binary); - } - ~INIGenerator() {} + INIGenerator(std::string const &filename) { + fileWriteStream.open(filename, std::ios::out | std::ios::binary); + } + ~INIGenerator() {} - bool operator<<(INIStructure const &data) - { - if (!fileWriteStream.is_open()) - { - return false; - } - if (!data.size()) - { - return true; - } - auto it = data.begin(); - for (;;) - { - auto const §ion = it->first; - auto const &collection = it->second; - fileWriteStream - << "[" - << section - << "]"; - if (collection.size()) - { - fileWriteStream << INIStringUtil::endl; - auto it2 = collection.begin(); - for (;;) - { - auto key = it2->first; - INIStringUtil::replace(key, "=", "\\="); - auto value = it2->second; - INIStringUtil::trim(value); - fileWriteStream - << key - << ((prettyPrint) ? " = " : "=") - << value; - if (++it2 == collection.end()) - { - break; - } - fileWriteStream << INIStringUtil::endl; - } - } - if (++it == data.end()) - { - break; - } - fileWriteStream << INIStringUtil::endl; - if (prettyPrint) - { - fileWriteStream << INIStringUtil::endl; - } - } - return true; - } + bool operator<<(INIStructure const &data) { + if (!fileWriteStream.is_open()) { + return false; + } + if (!data.size()) { + return true; + } + auto it = data.begin(); + for (;;) { + auto const §ion = it->first; + auto const &collection = it->second; + fileWriteStream << "[" << section << "]"; + if (collection.size()) { + fileWriteStream << INIStringUtil::endl; + auto it2 = collection.begin(); + for (;;) { + auto key = it2->first; + INIStringUtil::replace(key, "=", "\\="); + auto value = it2->second; + INIStringUtil::trim(value); + fileWriteStream << key << ((prettyPrint) ? " = " : "=") << value; + if (++it2 == collection.end()) { + break; + } + fileWriteStream << INIStringUtil::endl; + } + } + if (++it == data.end()) { + break; + } + fileWriteStream << INIStringUtil::endl; + if (prettyPrint) { + fileWriteStream << INIStringUtil::endl; + } + } + return true; + } }; -class INIWriter -{ -private: - using T_LineData = std::vector; - using T_LineDataPtr = std::shared_ptr; +class INIWriter { + private: + using T_LineData = std::vector; + using T_LineDataPtr = std::shared_ptr; - std::string filename; + std::string filename; - T_LineData getLazyOutput(T_LineDataPtr const &lineData, INIStructure &data, INIStructure &original) - { - T_LineData output; - INIParser::T_ParseValues parseData; - std::string sectionCurrent; - bool parsingSection = false; - bool continueToNextSection = false; - bool discardNextEmpty = false; - bool writeNewKeys = false; - std::size_t lastKeyLine = 0; - for (auto line = lineData->begin(); line != lineData->end(); ++line) - { - if (!writeNewKeys) - { - auto parseResult = INIParser::parseLine(*line, parseData); - if (parseResult == INIParser::PDataType::PDATA_SECTION) - { - if (parsingSection) - { - writeNewKeys = true; - parsingSection = false; - --line; - continue; - } - sectionCurrent = parseData.first; - if (data.has(sectionCurrent)) - { - parsingSection = true; - continueToNextSection = false; - discardNextEmpty = false; - output.emplace_back(*line); - lastKeyLine = output.size(); - } - else - { - continueToNextSection = true; - discardNextEmpty = true; - continue; - } - } - else if (parseResult == INIParser::PDataType::PDATA_KEYVALUE) - { - if (continueToNextSection) - { - continue; - } - if (data.has(sectionCurrent)) - { - auto &collection = data[sectionCurrent]; - auto const &key = parseData.first; - auto const &value = parseData.second; - if (collection.has(key)) - { - auto outputValue = collection[key]; - if (value == outputValue) - { - output.emplace_back(*line); - } - else - { - INIStringUtil::trim(outputValue); - auto lineNorm = *line; - INIStringUtil::replace(lineNorm, "\\=", " "); - auto equalsAt = lineNorm.find_first_of('='); - auto valueAt = lineNorm.find_first_not_of( - INIStringUtil::whitespaceDelimiters, - equalsAt + 1); - std::string outputLine = line->substr(0, valueAt); - if (prettyPrint && equalsAt + 1 == valueAt) - { - outputLine += " "; - } - outputLine += outputValue; - output.emplace_back(outputLine); - } - lastKeyLine = output.size(); - } - } - } - else - { - if (discardNextEmpty && line->empty()) - { - discardNextEmpty = false; - } - else if (parseResult != INIParser::PDataType::PDATA_UNKNOWN) - { - output.emplace_back(*line); - } - } - } - if (writeNewKeys || std::next(line) == lineData->end()) - { - T_LineData linesToAdd; - if (data.has(sectionCurrent) && original.has(sectionCurrent)) - { - auto const &collection = data[sectionCurrent]; - auto const &collectionOriginal = original[sectionCurrent]; - for (auto const &it : collection) - { - auto key = it.first; - if (collectionOriginal.has(key)) - { - continue; - } - auto value = it.second; - INIStringUtil::replace(key, "=", "\\="); - INIStringUtil::trim(value); - linesToAdd.emplace_back( - key + ((prettyPrint) ? " = " : "=") + value); - } - } - if (!linesToAdd.empty()) - { - output.insert( - output.begin() + lastKeyLine, - linesToAdd.begin(), - linesToAdd.end()); - } - if (writeNewKeys) - { - writeNewKeys = false; - --line; - } - } - } - for (auto const &it : data) - { - auto const §ion = it.first; - if (original.has(section)) - { - continue; - } - if (prettyPrint && output.size() > 0 && !output.back().empty()) - { - output.emplace_back(); - } - output.emplace_back("[" + section + "]"); - auto const &collection = it.second; - for (auto const &it2 : collection) - { - auto key = it2.first; - auto value = it2.second; - INIStringUtil::replace(key, "=", "\\="); - INIStringUtil::trim(value); - output.emplace_back( - key + ((prettyPrint) ? " = " : "=") + value); - } - } - return output; - } + T_LineData getLazyOutput(T_LineDataPtr const &lineData, INIStructure &data, + INIStructure &original) { + T_LineData output; + INIParser::T_ParseValues parseData; + std::string sectionCurrent; + bool parsingSection = false; + bool continueToNextSection = false; + bool discardNextEmpty = false; + bool writeNewKeys = false; + std::size_t lastKeyLine = 0; + for (auto line = lineData->begin(); line != lineData->end(); ++line) { + if (!writeNewKeys) { + auto parseResult = INIParser::parseLine(*line, parseData); + if (parseResult == INIParser::PDataType::PDATA_SECTION) { + if (parsingSection) { + writeNewKeys = true; + parsingSection = false; + --line; + continue; + } + sectionCurrent = parseData.first; + if (data.has(sectionCurrent)) { + parsingSection = true; + continueToNextSection = false; + discardNextEmpty = false; + output.emplace_back(*line); + lastKeyLine = output.size(); + } else { + continueToNextSection = true; + discardNextEmpty = true; + continue; + } + } else if (parseResult == INIParser::PDataType::PDATA_KEYVALUE) { + if (continueToNextSection) { + continue; + } + if (data.has(sectionCurrent)) { + auto &collection = data[sectionCurrent]; + auto const &key = parseData.first; + auto const &value = parseData.second; + if (collection.has(key)) { + auto outputValue = collection[key]; + if (value == outputValue) { + output.emplace_back(*line); + } else { + INIStringUtil::trim(outputValue); + auto lineNorm = *line; + INIStringUtil::replace(lineNorm, "\\=", " "); + auto equalsAt = lineNorm.find_first_of('='); + auto valueAt = lineNorm.find_first_not_of( + INIStringUtil::whitespaceDelimiters, equalsAt + 1); + std::string outputLine = line->substr(0, valueAt); + if (prettyPrint && equalsAt + 1 == valueAt) { + outputLine += " "; + } + outputLine += outputValue; + output.emplace_back(outputLine); + } + lastKeyLine = output.size(); + } + } + } else { + if (discardNextEmpty && line->empty()) { + discardNextEmpty = false; + } else if (parseResult != INIParser::PDataType::PDATA_UNKNOWN) { + output.emplace_back(*line); + } + } + } + if (writeNewKeys || std::next(line) == lineData->end()) { + T_LineData linesToAdd; + if (data.has(sectionCurrent) && original.has(sectionCurrent)) { + auto const &collection = data[sectionCurrent]; + auto const &collectionOriginal = original[sectionCurrent]; + for (auto const &it : collection) { + auto key = it.first; + if (collectionOriginal.has(key)) { + continue; + } + auto value = it.second; + INIStringUtil::replace(key, "=", "\\="); + INIStringUtil::trim(value); + linesToAdd.emplace_back(key + ((prettyPrint) ? " = " : "=") + + value); + } + } + if (!linesToAdd.empty()) { + output.insert(output.begin() + lastKeyLine, linesToAdd.begin(), + linesToAdd.end()); + } + if (writeNewKeys) { + writeNewKeys = false; + --line; + } + } + } + for (auto const &it : data) { + auto const §ion = it.first; + if (original.has(section)) { + continue; + } + if (prettyPrint && output.size() > 0 && !output.back().empty()) { + output.emplace_back(); + } + output.emplace_back("[" + section + "]"); + auto const &collection = it.second; + for (auto const &it2 : collection) { + auto key = it2.first; + auto value = it2.second; + INIStringUtil::replace(key, "=", "\\="); + INIStringUtil::trim(value); + output.emplace_back(key + ((prettyPrint) ? " = " : "=") + value); + } + } + return output; + } -public: - bool prettyPrint = false; + public: + bool prettyPrint = false; - INIWriter(std::string const &file_name) - : filename(file_name) - { - } - ~INIWriter() {} + INIWriter(std::string const &file_name) : filename(file_name) {} + ~INIWriter() {} - bool operator<<(INIStructure &data) - { - struct stat buf; - bool fileExists = (stat(filename.c_str(), &buf) == 0); - if (!fileExists) - { - INIGenerator generator(filename); - generator.prettyPrint = prettyPrint; - return generator << data; - } - INIStructure originalData; - T_LineDataPtr lineData; - bool readSuccess = false; - { - INIReader reader(filename, true); - if ((readSuccess = reader >> originalData)) - { - lineData = reader.getLines(); - } - } - if (!readSuccess) - { - return false; - } - T_LineData output = getLazyOutput(lineData, data, originalData); - std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary); - if (fileWriteStream.is_open()) - { - if (output.size()) - { - auto line = output.begin(); - for (;;) - { - fileWriteStream << *line; - if (++line == output.end()) - { - break; - } - fileWriteStream << INIStringUtil::endl; - } - } - return true; - } - return false; - } + bool operator<<(INIStructure &data) { + struct stat buf; + bool fileExists = (stat(filename.c_str(), &buf) == 0); + if (!fileExists) { + INIGenerator generator(filename); + generator.prettyPrint = prettyPrint; + return generator << data; + } + INIStructure originalData; + T_LineDataPtr lineData; + bool readSuccess = false; + { + INIReader reader(filename, true); + if ((readSuccess = reader >> originalData)) { + lineData = reader.getLines(); + } + } + if (!readSuccess) { + return false; + } + T_LineData output = getLazyOutput(lineData, data, originalData); + std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary); + if (fileWriteStream.is_open()) { + if (output.size()) { + auto line = output.begin(); + for (;;) { + fileWriteStream << *line; + if (++line == output.end()) { + break; + } + fileWriteStream << INIStringUtil::endl; + } + } + return true; + } + return false; + } }; -class INIFile -{ -private: - std::string filename; +class INIFile { + private: + std::string filename; -public: - INIFile(std::string const &file_name) - : filename(file_name) - { - } + public: + INIFile(std::string const &file_name) : filename(file_name) {} - ~INIFile() {} + ~INIFile() {} - bool read(INIStructure &data) const - { - if (data.size()) - { - data.clear(); - } - if (filename.empty()) - { - return false; - } - INIReader reader(filename); - return reader >> data; - } - bool generate(INIStructure const &data, bool pretty = false) const - { - if (filename.empty()) - { - return false; - } - INIGenerator generator(filename); - generator.prettyPrint = pretty; - return generator << data; - } - bool write(INIStructure &data, bool pretty = false) const - { - if (filename.empty()) - { - return false; - } - INIWriter writer(filename); - writer.prettyPrint = pretty; - return writer << data; - } + bool read(INIStructure &data) const { + if (data.size()) { + data.clear(); + } + if (filename.empty()) { + return false; + } + INIReader reader(filename); + return reader >> data; + } + bool generate(INIStructure const &data, bool pretty = false) const { + if (filename.empty()) { + return false; + } + INIGenerator generator(filename); + generator.prettyPrint = pretty; + return generator << data; + } + bool write(INIStructure &data, bool pretty = false) const { + if (filename.empty()) { + return false; + } + INIWriter writer(filename); + writer.prettyPrint = pretty; + return writer << data; + } }; -} // namespace mINI +} // namespace mINI -#endif // MINI_INI_H_ +#endif // MINI_INI_H_ diff --git a/libs/libopenfpgashell/src/command.cpp b/libs/libopenfpgashell/src/command.cpp index 8c20ffe5a..ae6e86839 100644 --- a/libs/libopenfpgashell/src/command.cpp +++ b/libs/libopenfpgashell/src/command.cpp @@ -1,25 +1,22 @@ /********************************************************************* * Member functions for class Command ********************************************************************/ -#include "vtr_assert.h" #include "command.h" +#include "vtr_assert.h" + /* Begin namespace openfpga */ namespace openfpga { /********************************************************************* * Public constructors ********************************************************************/ -Command::Command(const char* name) { - name_ = std::string(name); -} +Command::Command(const char* name) { name_ = std::string(name); } /************************************************************************ * Public Accessors : aggregates ***********************************************************************/ -std::string Command::name() const { - return name_; -} +std::string Command::name() const { return name_; } Command::command_option_range Command::options() const { return vtr::make_range(option_ids_.begin(), option_ids_.end()); @@ -47,7 +44,8 @@ std::vector Command::require_value_options() const { CommandOptionId Command::option(const std::string& name) const { /* Ensure that the name is unique in the option list */ - std::map::const_iterator name_it = option_name2ids_.find(name); + std::map::const_iterator name_it = + option_name2ids_.find(name); if (name_it == option_name2ids_.end()) { return CommandOptionId::INVALID(); } @@ -56,7 +54,8 @@ CommandOptionId Command::option(const std::string& name) const { CommandOptionId Command::short_option(const std::string& name) const { /* Ensure that the name is unique in the option list */ - std::map::const_iterator name_it = option_short_name2ids_.find(name); + std::map::const_iterator name_it = + option_short_name2ids_.find(name); if (name_it == option_short_name2ids_.end()) { return CommandOptionId::INVALID(); } @@ -87,13 +86,15 @@ bool Command::option_require_value(const CommandOptionId& option_id) const { return NUM_OPT_VALUE_TYPES != option_require_value_types_[option_id]; } -e_option_value_type Command::option_require_value_type(const CommandOptionId& option_id) const { +e_option_value_type Command::option_require_value_type( + const CommandOptionId& option_id) const { /* Validate the option id */ VTR_ASSERT(true == valid_option_id(option_id)); return option_require_value_types_[option_id]; } -std::string Command::option_description(const CommandOptionId& option_id) const { +std::string Command::option_description( + const CommandOptionId& option_id) const { /* Validate the option id */ VTR_ASSERT(true == valid_option_id(option_id)); return option_description_[option_id]; @@ -105,10 +106,11 @@ std::string Command::option_description(const CommandOptionId& option_id) const /* Add an option without required values */ CommandOptionId Command::add_option(const char* name, - const bool& option_required, + const bool& option_required, const char* description) { /* Ensure that the name is unique in the option list */ - std::map::const_iterator name_it = option_name2ids_.find(std::string(name)); + std::map::const_iterator name_it = + option_name2ids_.find(std::string(name)); if (name_it != option_name2ids_.end()) { return CommandOptionId::INVALID(); } @@ -126,22 +128,23 @@ CommandOptionId Command::add_option(const char* name, option_name2ids_[std::string(name)] = option; return option; -} +} /* Add a short name to an option */ -bool Command::set_option_short_name(const CommandOptionId& option_id, +bool Command::set_option_short_name(const CommandOptionId& option_id, const char* short_name) { /* Validate the option id */ VTR_ASSERT(true == valid_option_id(option_id)); /* Short name is optional, so do the following only when it is not empty - * Ensure that the short name is unique in the option list + * Ensure that the short name is unique in the option list */ if (true == std::string(short_name).empty()) { return false; } - std::map::const_iterator short_name_it = option_short_name2ids_.find(std::string(short_name)); + std::map::const_iterator short_name_it = + option_short_name2ids_.find(std::string(short_name)); if (short_name_it != option_short_name2ids_.end()) { return false; } @@ -152,10 +155,11 @@ bool Command::set_option_short_name(const CommandOptionId& option_id, option_short_name2ids_[std::string(short_name)] = option_id; return true; -} +} -void Command::set_option_require_value(const CommandOptionId& option_id, - const e_option_value_type& option_require_value_type) { +void Command::set_option_require_value( + const CommandOptionId& option_id, + const e_option_value_type& option_require_value_type) { /* Validate the option id */ VTR_ASSERT(true == valid_option_id(option_id)); @@ -163,10 +167,11 @@ void Command::set_option_require_value(const CommandOptionId& option_id, } /************************************************************************ - * Public invalidators/validators + * Public invalidators/validators ***********************************************************************/ bool Command::valid_option_id(const CommandOptionId& option_id) const { - return ( size_t(option_id) < option_ids_.size() ) && ( option_id == option_ids_[option_id] ); + return (size_t(option_id) < option_ids_.size()) && + (option_id == option_ids_[option_id]); } } /* End namespace openfpga */ diff --git a/libs/libopenfpgashell/src/command.h b/libs/libopenfpgashell/src/command.h index 05bf89fed..63bbd254e 100644 --- a/libs/libopenfpgashell/src/command.h +++ b/libs/libopenfpgashell/src/command.h @@ -6,7 +6,7 @@ * This is a cornerstone data structure of mini shell * which aims to store command-line options for parser * - * This data structue is design to read-in the command line options + * This data structue is design to read-in the command line options * which are organized as follows: * * -- @@ -15,13 +15,13 @@ * This is not only used by each command available in the shell * but also the interface of the shell, such as interactive mode ********************************************************************/ -#include #include +#include #include -#include "vtr_vector.h" -#include "vtr_range.h" #include "command_fwd.h" +#include "vtr_range.h" +#include "vtr_vector.h" /* Begin namespace openfpga */ namespace openfpga { @@ -37,7 +37,7 @@ enum e_option_value_type { }; /********************************************************************* - * Data structure to stores all the information related to a command + * Data structure to stores all the information related to a command * to be defined in the mini shell * This data structure should NOT contain any parsing results! * It should be a read-only once created! @@ -45,7 +45,7 @@ enum e_option_value_type { * An example of how to use * ----------------------- * // Create a new command with a name of 'read_file' - * // This command can be called as + * // This command can be called as * // read_file --file * // read_file -f * // read_file --help @@ -79,64 +79,73 @@ enum e_option_value_type { * When adding an option name, please do NOT add any dash at the beginning!!! ********************************************************************/ class Command { - public: /* Types */ - typedef vtr::vector::const_iterator command_option_iterator; - /* Create range */ - typedef vtr::Range command_option_range; - public: /* Constructor */ - Command(const char* name); - public: /* Public accessors */ - std::string name() const; - command_option_range options() const; - /* Find all the options that are mandatory */ - std::vector required_options() const; - /* Find all the options that require a value */ - std::vector require_value_options() const; - CommandOptionId option(const std::string& name) const; - CommandOptionId short_option(const std::string& name) const; - std::string option_name(const CommandOptionId& option_id) const; - std::string option_short_name(const CommandOptionId& option_id) const; - bool option_required(const CommandOptionId& option_id) const; - bool option_require_value(const CommandOptionId& option_id) const; - e_option_value_type option_require_value_type(const CommandOptionId& option_id) const; - std::string option_description(const CommandOptionId& option_id) const; - public: /* Public mutators */ - CommandOptionId add_option(const char* name, - const bool& option_required, - const char* description); - bool set_option_short_name(const CommandOptionId& option_id, const char* short_name); - void set_option_require_value(const CommandOptionId& option_id, - const e_option_value_type& option_require_value_type); - public: /* Public validators */ - bool valid_option_id(const CommandOptionId& option_id) const; - private: /* Internal data */ - /* The name of the command */ - std::string name_; + public: /* Types */ + typedef vtr::vector::const_iterator + command_option_iterator; + /* Create range */ + typedef vtr::Range command_option_range; - vtr::vector option_ids_; + public: /* Constructor */ + Command(const char* name); - /* Information about the options available in this command */ - /* Name of command line option to appear in the user interface - * Regular names are typically with a prefix of double dash '--' - * Short names are typically with a prefix of single dash '-' - */ - vtr::vector option_names_; - vtr::vector option_short_names_; + public: /* Public accessors */ + std::string name() const; + command_option_range options() const; + /* Find all the options that are mandatory */ + std::vector required_options() const; + /* Find all the options that require a value */ + std::vector require_value_options() const; + CommandOptionId option(const std::string& name) const; + CommandOptionId short_option(const std::string& name) const; + std::string option_name(const CommandOptionId& option_id) const; + std::string option_short_name(const CommandOptionId& option_id) const; + bool option_required(const CommandOptionId& option_id) const; + bool option_require_value(const CommandOptionId& option_id) const; + e_option_value_type option_require_value_type( + const CommandOptionId& option_id) const; + std::string option_description(const CommandOptionId& option_id) const; - /* If the option is manadatory when parsing */ - vtr::vector option_required_; + public: /* Public mutators */ + CommandOptionId add_option(const char* name, const bool& option_required, + const char* description); + bool set_option_short_name(const CommandOptionId& option_id, + const char* short_name); + void set_option_require_value( + const CommandOptionId& option_id, + const e_option_value_type& option_require_value_type); - /* Data type of the option values to be converted - * If the option does NOT require a value, this will be an invalid type - */ - vtr::vector option_require_value_types_; + public: /* Public validators */ + bool valid_option_id(const CommandOptionId& option_id) const; - /* Description of the option, this is going to be printed out in the help desk */ - vtr::vector option_description_; + private: /* Internal data */ + /* The name of the command */ + std::string name_; - /* Fast name look-up */ - std::map option_name2ids_; - std::map option_short_name2ids_; + vtr::vector option_ids_; + + /* Information about the options available in this command */ + /* Name of command line option to appear in the user interface + * Regular names are typically with a prefix of double dash '--' + * Short names are typically with a prefix of single dash '-' + */ + vtr::vector option_names_; + vtr::vector option_short_names_; + + /* If the option is manadatory when parsing */ + vtr::vector option_required_; + + /* Data type of the option values to be converted + * If the option does NOT require a value, this will be an invalid type + */ + vtr::vector option_require_value_types_; + + /* Description of the option, this is going to be printed out in the help desk + */ + vtr::vector option_description_; + + /* Fast name look-up */ + std::map option_name2ids_; + std::map option_short_name2ids_; }; } /* End namespace openfpga */ diff --git a/libs/libopenfpgashell/src/command_context.cpp b/libs/libopenfpgashell/src/command_context.cpp index 24593a77b..c798d9b00 100644 --- a/libs/libopenfpgashell/src/command_context.cpp +++ b/libs/libopenfpgashell/src/command_context.cpp @@ -1,9 +1,10 @@ /********************************************************************* - * Member functions for class CommandContext + * Member functions for class CommandContext ********************************************************************/ -#include "vtr_assert.h" #include "command_context.h" +#include "vtr_assert.h" + /* Begin namespace openfpga */ namespace openfpga { @@ -24,13 +25,14 @@ bool CommandContext::option_enable(const Command& command, return option_enabled_[option_id]; } -std::string CommandContext::option_value(const Command& command, - const CommandOptionId& option_id) const { +std::string CommandContext::option_value( + const Command& command, const CommandOptionId& option_id) const { VTR_ASSERT(true == command.valid_option_id(option_id)); return option_values_[option_id]; } -std::vector CommandContext::check_required_options(const Command& command) const { +std::vector CommandContext::check_required_options( + const Command& command) const { std::vector fail_options; for (const CommandOptionId& option_id : command.required_options()) { if (false == option_enabled_[option_id]) { @@ -40,7 +42,8 @@ std::vector CommandContext::check_required_options(const Comman return fail_options; } -std::vector CommandContext::check_required_option_values(const Command& command) const { +std::vector CommandContext::check_required_option_values( + const Command& command) const { std::vector fail_options; for (const CommandOptionId& option_id : command.require_value_options()) { if (true == option_values_[option_id].empty()) { @@ -50,18 +53,19 @@ std::vector CommandContext::check_required_option_values(const return fail_options; } - /********************************************************************* * Public mutators ********************************************************************/ void CommandContext::set_option(const Command& command, - const CommandOptionId& option_id, const bool& status) { + const CommandOptionId& option_id, + const bool& status) { VTR_ASSERT(true == command.valid_option_id(option_id)); option_enabled_[option_id] = status; } void CommandContext::set_option_value(const Command& command, - const CommandOptionId& option_id, const std::string& value) { + const CommandOptionId& option_id, + const std::string& value) { VTR_ASSERT(true == command.valid_option_id(option_id)); option_values_[option_id] = value; } diff --git a/libs/libopenfpgashell/src/command_context.h b/libs/libopenfpgashell/src/command_context.h index 5f3fb8856..5f87aeaff 100644 --- a/libs/libopenfpgashell/src/command_context.h +++ b/libs/libopenfpgashell/src/command_context.h @@ -2,9 +2,10 @@ #define COMMAND_CONTEXT_H #include -#include "vtr_vector.h" -#include "command_fwd.h" + #include "command.h" +#include "command_fwd.h" +#include "vtr_vector.h" /* Begin namespace openfpga */ namespace openfpga { @@ -13,47 +14,53 @@ namespace openfpga { * Data structure to stores parsing results for a command ********************************************************************/ class CommandContext { - public: /* Public constructor */ - /* Build a context based on the command information - * This will allocate the internal data structure and assign default values + public: /* Public constructor */ + /* Build a context based on the command information + * This will allocate the internal data structure and assign default values + */ + CommandContext(const Command& command); + + public: /* Public accessors */ + bool option_enable(const Command& command, + const CommandOptionId& option_id) const; + std::string option_value(const Command& command, + const CommandOptionId& option_id) const; + /* Check if all the required options have been enabled + * Any thing wrong will be reported in the return vector + * + * Note: + * This function is supposed to be called after parsing is completed */ - CommandContext(const Command& command); - public: /* Public accessors */ - bool option_enable(const Command& command, - const CommandOptionId& option_id) const; - std::string option_value(const Command& command, - const CommandOptionId& option_id) const; - /* Check if all the required options have been enabled - * Any thing wrong will be reported in the return vector - * - * Note: - * This function is supposed to be called after parsing is completed - */ - std::vector check_required_options(const Command& command) const; + std::vector check_required_options( + const Command& command) const; - /* Check all the values that are required by the options - * Any thing wrong will be reported in the return vector - * - * Note: - * This function is supposed to be called after parsing is completed - */ - std::vector check_required_option_values(const Command& command) const; - public: /* Public mutators */ - void set_option(const Command& command, - const CommandOptionId& option_id, const bool& status); - void set_option_value(const Command& command, - const CommandOptionId& option_id, const std::string& value); - /* Reset the command context to initial state */ - void reset(); - private: /* Internal data */ - /* Identify if the option is enabled or not */ - vtr::vector option_enabled_; + /* Check all the values that are required by the options + * Any thing wrong will be reported in the return vector + * + * Note: + * This function is supposed to be called after parsing is completed + */ + std::vector check_required_option_values( + const Command& command) const; - /* All the follow-up value of each option is stored as string, - * It will be converted the data types by outside function - * according to the value types - */ - vtr::vector option_values_; + public: /* Public mutators */ + void set_option(const Command& command, const CommandOptionId& option_id, + const bool& status); + void set_option_value(const Command& command, + const CommandOptionId& option_id, + const std::string& value); + /* Reset the command context to initial state */ + void reset(); + + private: /* Internal data */ + /* Identify if the option is enabled or not */ + vtr::vector option_enabled_; + + /* All the follow-up value of each option is stored as string, + * It will be converted the data types by outside function + * according to the value types + */ + vtr::vector option_values_; }; } /* End namespace openfpga */ diff --git a/libs/libopenfpgashell/src/command_echo.cpp b/libs/libopenfpgashell/src/command_echo.cpp index b7d02420a..0ff52ca26 100644 --- a/libs/libopenfpgashell/src/command_echo.cpp +++ b/libs/libopenfpgashell/src/command_echo.cpp @@ -2,9 +2,10 @@ * This file includes functions that output the content of * object Command and CommandContext ********************************************************************/ +#include "command_echo.h" + #include "vtr_assert.h" #include "vtr_log.h" -#include "command_echo.h" /* Begin namespace openfpga */ namespace openfpga { @@ -14,20 +15,18 @@ namespace openfpga { * This function is mainly used to create help desk for a command ********************************************************************/ void print_command_options(const Command& cmd) { - VTR_LOG("Command '%s' usage:\n%lu options available\n", - cmd.name().c_str(), cmd.options().size()); + VTR_LOG("Command '%s' usage:\n%lu options available\n", cmd.name().c_str(), + cmd.options().size()); for (const CommandOptionId& opt : cmd.options()) { if (true == cmd.option_short_name(opt).empty()) { - VTR_LOG("\t--%s : %s\n", - cmd.option_name(opt).c_str(), + VTR_LOG("\t--%s : %s\n", cmd.option_name(opt).c_str(), cmd.option_description(opt).c_str()); continue; - } - VTR_LOG("\t--%s, -%s : %s\n", - cmd.option_name(opt).c_str(), + } + VTR_LOG("\t--%s, -%s : %s\n", cmd.option_name(opt).c_str(), cmd.option_short_name(opt).c_str(), cmd.option_description(opt).c_str()); - } + } } /********************************************************************* @@ -35,23 +34,20 @@ void print_command_options(const Command& cmd) { * This function is mainly used to validate what options have been enabled * for users' confirmation ********************************************************************/ -void print_command_context(const Command& cmd, +void print_command_context(const Command& cmd, const CommandContext& cmd_context) { VTR_LOG("\nConfirm selected options when call command '%s':\n", cmd.name().c_str()); for (const CommandOptionId& opt : cmd.options()) { - VTR_LOG("--%s", - cmd.option_name(opt).c_str()); + VTR_LOG("--%s", cmd.option_name(opt).c_str()); if (false == cmd.option_short_name(opt).empty()) { - VTR_LOG(", -%s", - cmd.option_short_name(opt).c_str()); + VTR_LOG(", -%s", cmd.option_short_name(opt).c_str()); } - + if (false == cmd.option_require_value(opt)) { - VTR_LOG(": %s\n", - cmd_context.option_enable(cmd, opt) ? "on" : "off"); + VTR_LOG(": %s\n", cmd_context.option_enable(cmd, opt) ? "on" : "off"); } else { - VTR_ASSERT_SAFE (true == cmd.option_require_value(opt)); + VTR_ASSERT_SAFE(true == cmd.option_require_value(opt)); /* If the option is disabled, we output an off */ std::string opt_value; if (false == cmd_context.option_enable(cmd, opt)) { @@ -59,10 +55,9 @@ void print_command_context(const Command& cmd, } else { opt_value = cmd_context.option_value(cmd, opt); } - VTR_LOG(": %s\n", - opt_value.c_str()); + VTR_LOG(": %s\n", opt_value.c_str()); } - } + } } -} /* End namespace minshell */ +} // namespace openfpga diff --git a/libs/libopenfpgashell/src/command_echo.h b/libs/libopenfpgashell/src/command_echo.h index 2d8ce2c66..6eda0a046 100644 --- a/libs/libopenfpgashell/src/command_echo.h +++ b/libs/libopenfpgashell/src/command_echo.h @@ -16,7 +16,7 @@ namespace openfpga { void print_command_options(const Command& cmd); -void print_command_context(const Command& cmd, +void print_command_context(const Command& cmd, const CommandContext& cmd_context); } /* End namespace openfpga */ diff --git a/libs/libopenfpgashell/src/command_exit_codes.h b/libs/libopenfpgashell/src/command_exit_codes.h index f1490e533..6f563de07 100644 --- a/libs/libopenfpgashell/src/command_exit_codes.h +++ b/libs/libopenfpgashell/src/command_exit_codes.h @@ -15,13 +15,14 @@ constexpr int CMD_EXEC_NONE = -1; /* Everything OK */ constexpr int CMD_EXEC_SUCCESS = 0; -/* Fatal error occurred, we have to abort and do not execute the rest of commands */ +/* Fatal error occurred, we have to abort and do not execute the rest of + * commands */ constexpr int CMD_EXEC_FATAL_ERROR = 1; -/* See minor errors but it will not impact the downsteam. We can continue to execute the rest of commands */ +/* See minor errors but it will not impact the downsteam. We can continue to + * execute the rest of commands */ constexpr int CMD_EXEC_MINOR_ERROR = 2; - } /* End namespace openfpga */ #endif diff --git a/libs/libopenfpgashell/src/command_fwd.h b/libs/libopenfpgashell/src/command_fwd.h index 3d59097dc..1467994c3 100644 --- a/libs/libopenfpgashell/src/command_fwd.h +++ b/libs/libopenfpgashell/src/command_fwd.h @@ -7,7 +7,7 @@ namespace openfpga { /********************************************************************* - * A strong id for the options used by a command + * A strong id for the options used by a command ********************************************************************/ struct command_option_id_tag; diff --git a/libs/libopenfpgashell/src/command_parser.cpp b/libs/libopenfpgashell/src/command_parser.cpp index b2daf12f7..62888a11c 100644 --- a/libs/libopenfpgashell/src/command_parser.cpp +++ b/libs/libopenfpgashell/src/command_parser.cpp @@ -1,14 +1,15 @@ /******************************************************************** - * This file includes parser(s) to convert user's input from + * This file includes parser(s) to convert user's input from * shell interface to a data structure CommandContext * * TODO: a strong dependency is that we use VTR logging system *******************************************************************/ +#include "command_parser.h" + #include #include "vtr_assert.h" #include "vtr_log.h" -#include "command_parser.h" /* Begin namespace openfpga */ namespace openfpga { @@ -16,15 +17,12 @@ namespace openfpga { /******************************************************************** * Try to find an option in the command and update the CommandContext if needed *******************************************************************/ -static -CommandOptionId parse_option(const std::string& argv, - const Command& cmd, - CommandContext& cmd_context) { +static CommandOptionId parse_option(const std::string& argv, const Command& cmd, + CommandContext& cmd_context) { CommandOptionId option_id = cmd.option(argv); /* Not found, error out */ if (CommandOptionId::INVALID() == option_id) { - VTR_LOG("Detect unknown option '--%s'!\n", - argv.c_str()); + VTR_LOG("Detect unknown option '--%s'!\n", argv.c_str()); return CommandOptionId::INVALID(); } /* Found, update the CommandContext */ @@ -37,15 +35,13 @@ CommandOptionId parse_option(const std::string& argv, * Try to find a short option in the command * Update the CommandContext if needed *******************************************************************/ -static -CommandOptionId parse_short_option(const std::string& argv, - const Command& cmd, - CommandContext& cmd_context) { +static CommandOptionId parse_short_option(const std::string& argv, + const Command& cmd, + CommandContext& cmd_context) { CommandOptionId option_id = cmd.short_option(argv); /* Not found, error out */ if (CommandOptionId::INVALID() == option_id) { - VTR_LOG("Detect unknown short option '-%s'!\n", - argv.c_str()); + VTR_LOG("Detect unknown short option '-%s'!\n", argv.c_str()); return CommandOptionId::INVALID(); } /* Found, update the CommandContext */ @@ -55,19 +51,17 @@ CommandOptionId parse_short_option(const std::string& argv, } /******************************************************************** - * Main parser to convert user's input from + * Main parser to convert user's input from * shell interface to a data structure CommandContext *******************************************************************/ -bool parse_command(const std::vector& argv, - const Command& cmd, +bool parse_command(const std::vector& argv, const Command& cmd, CommandContext& cmd_context) { /* We at least expect 1 arguement, which is the command name itself */ VTR_ASSERT(1 <= argv.size()); /* Validate that the command name matches argv[0] */ - if (argv[0] != cmd.name()) { - VTR_LOG("Unexpected command name '%s'!\n", - argv[0].c_str()); + if (argv[0] != cmd.name()) { + VTR_LOG("Unexpected command name '%s'!\n", argv[0].c_str()); return false; } @@ -75,18 +69,18 @@ bool parse_command(const std::vector& argv, for (size_t iarg = 1; iarg < argv.size(); ++iarg) { /* Option must start with dash */ if (0 != strncmp("-", argv[iarg].c_str(), 1)) { - VTR_LOG("Invalid option '%s'!\n", - argv[iarg].c_str()); + VTR_LOG("Invalid option '%s'!\n", argv[iarg].c_str()); return false; } - /* First try to process a full option + /* First try to process a full option * which always starts with double dash '--' */ if (0 == strncmp("--", argv[iarg].c_str(), 2)) { /* See if there is a option defined in the command object - * Note that the first two characters are skipped when searching the name + * Note that the first two characters are skipped when searching the name */ - CommandOptionId option_id = parse_option(argv[iarg].substr(2), cmd, cmd_context); + CommandOptionId option_id = + parse_option(argv[iarg].substr(2), cmd, cmd_context); if (CommandOptionId::INVALID() == option_id) { return false; @@ -105,14 +99,15 @@ bool parse_command(const std::vector& argv, continue; } - /* Second try to process a short option + /* Second try to process a short option * which always starts with double dash '-' */ if (0 == strncmp("-", argv[iarg].c_str(), 1)) { /* See if there is a option defined in the command object - * Note that the first two characters are skipped when searching the name + * Note that the first two characters are skipped when searching the name */ - CommandOptionId option_id = parse_short_option(argv[iarg].substr(1), cmd, cmd_context); + CommandOptionId option_id = + parse_short_option(argv[iarg].substr(1), cmd, cmd_context); if (CommandOptionId::INVALID() == option_id) { return false; @@ -133,9 +128,10 @@ bool parse_command(const std::vector& argv, } /* Ensure that all the required options have been satisfied - * If not, we echo the details about what are missing - */ - std::vector missing_options = cmd_context.check_required_options(cmd); + * If not, we echo the details about what are missing + */ + std::vector missing_options = + cmd_context.check_required_options(cmd); if (!missing_options.empty()) { for (const CommandOptionId& missing_opt : missing_options) { VTR_LOG("Required option '%s' is missing!\n", @@ -144,7 +140,8 @@ bool parse_command(const std::vector& argv, return false; } - std::vector missing_value_options = cmd_context.check_required_option_values(cmd); + std::vector missing_value_options = + cmd_context.check_required_option_values(cmd); if (!missing_value_options.empty()) { bool parse_fail = false; for (const CommandOptionId& missing_opt : missing_value_options) { diff --git a/libs/libopenfpgashell/src/command_parser.h b/libs/libopenfpgashell/src/command_parser.h index 568bb7ffc..e5d3146db 100644 --- a/libs/libopenfpgashell/src/command_parser.h +++ b/libs/libopenfpgashell/src/command_parser.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "command.h" #include "command_context.h" @@ -15,8 +16,7 @@ /* Begin namespace openfpga */ namespace openfpga { -bool parse_command(const std::vector& argv, - const Command& cmd, +bool parse_command(const std::vector& argv, const Command& cmd, CommandContext& cmd_context); } /* End namespace openfpga */ diff --git a/libs/libopenfpgashell/src/shell.h b/libs/libopenfpgashell/src/shell.h index 7f8e3a142..d2d1a7c91 100644 --- a/libs/libopenfpgashell/src/shell.h +++ b/libs/libopenfpgashell/src/shell.h @@ -1,18 +1,18 @@ #ifndef SHELL_H #define SHELL_H -#include -#include -#include -#include #include +#include +#include +#include +#include -#include "vtr_vector.h" -#include "vtr_range.h" #include "command.h" #include "command_context.h" #include "command_exit_codes.h" #include "shell_fwd.h" +#include "vtr_range.h" +#include "vtr_vector.h" /* Begin namespace openfpga */ namespace openfpga { @@ -22,205 +22,244 @@ namespace openfpga { * * An example of how to use * ----------------------- - * // Create a new shell with a name of 'OpenFPGA' which use data structure OpenfpgaContext for data exchange - * Shell shell("OpenFPGA"); + * // Create a new shell with a name of 'OpenFPGA' which use data structure + *OpenfpgaContext for data exchange Shell shell("OpenFPGA"); * * // Add a command 'read_arch' with a description - * ShellCommandId cmd_read_arch = shell.add_command("read_arch", "Command to read an architecture"); + * ShellCommandId cmd_read_arch = shell.add_command("read_arch", "Command to + *read an architecture"); * // Create a new category and classify the command to it * ShellCommandCategoryId cmd_category = shell.add_command_category("io"); * shell.set_command_category(cmd_read_arch, cmd_category); * * // Add options to the command 'read_arch' * const Command* cmd_read_arch_obj = shell.command(cmd_read_arch); - * // Detailed examples can be found in Command.h + * // Detailed examples can be found in Command.h * ... * * // Add execute function to the command 'read_arch' * // This is the function to be called when the command is used - * // Assume that you have a function read_arch() which does the job of read architecture - * // Note that the function read_arch() should return a void with only three arguments + * // Assume that you have a function read_arch() which does the job of read + *architecture + * // Note that the function read_arch() should return a void with only three + *arguments * // void read_arch(T, const Command&, const CommandContext&); * // The first argument is the template type you set when define the shell - * // The second argument is a read-only object storing the options for the command - * // The third argument is a read-only object storing the parsing results for the command - * shell.set_command_execute_function(cmd_read_arch, &read_arch); - * - * // Run a shell + * // The second argument is a read-only object storing the options for the + *command + * // The third argument is a read-only object storing the parsing results for + *the command shell.set_command_execute_function(cmd_read_arch, &read_arch); + * + * // Run a shell * shell.run(); * ********************************************************************/ -template +template class Shell { - public: /* Types */ - typedef vtr::vector::const_iterator shell_command_iterator; - /* Create range */ - typedef vtr::Range shell_command_range; - /* Enumeration of command types in a shell - * Built-in commands have their own execute functions inside the shell - */ - enum e_exec_func_type { - CONST_STANDARD, - STANDARD, - CONST_SHORT, - SHORT, - BUILTIN, - MACRO, - NUM_EXEC_FUNC_TYPES - }; - public: /* Constructor */ - Shell(const char* name); - public: /* Public accessors */ - std::string name() const; - std::string title() const; - shell_command_range commands() const; - ShellCommandId command(const std::string& name) const; - std::string command_description(const ShellCommandId& cmd_id) const; - ShellCommandClassId command_class(const ShellCommandId& cmd_id) const; - std::string command_class_name(const ShellCommandClassId& cmd_class_id) const; - /* We force a read-only return objects for command and command context - * because users should NOT modify any of them! - */ - const Command& command(const ShellCommandId& cmd_id) const; - const CommandContext& command_context(const ShellCommandId& cmd_id) const; - std::vector command_dependency(const ShellCommandId& cmd_id) const; - std::vector commands_by_class(const ShellCommandClassId& cmd_class_id) const; - public: /* Public mutators */ - void add_title(const char* title); - ShellCommandId add_command(const Command& cmd, const char* descr); - void set_command_class(const ShellCommandId& cmd_id, const ShellCommandClassId& cmd_class_id); - /* Link the execute function to a command - * We support here different types of functions to be executed in the shell - * Users just need to specify the function object and its type will be automatically inferred - * - * Note that all the function should return exit codes complying to the shell_exit_code.h - * execept the internal functions - */ + public: /* Types */ + typedef vtr::vector::const_iterator + shell_command_iterator; + /* Create range */ + typedef vtr::Range shell_command_range; + /* Enumeration of command types in a shell + * Built-in commands have their own execute functions inside the shell + */ + enum e_exec_func_type { + CONST_STANDARD, + STANDARD, + CONST_SHORT, + SHORT, + BUILTIN, + MACRO, + NUM_EXEC_FUNC_TYPES + }; - /* Standard function, including the data exchange and commands - * This function requires the data exchange to be constant - * This is designed for outputting functions requiring external data than the - */ - void set_command_const_execute_function(const ShellCommandId& cmd_id, - std::function exec_func); + public: /* Constructor */ + Shell(const char* name); - /* Standard function, including the data exchange and commands - * This function allows modification to the data exchange - * This is designed for implementing functions requiring external data than the - */ - void set_command_execute_function(const ShellCommandId& cmd_id, - std::function exec_func); + public: /* Public accessors */ + std::string name() const; + std::string title() const; + shell_command_range commands() const; + ShellCommandId command(const std::string& name) const; + std::string command_description(const ShellCommandId& cmd_id) const; + ShellCommandClassId command_class(const ShellCommandId& cmd_id) const; + std::string command_class_name(const ShellCommandClassId& cmd_class_id) const; + /* We force a read-only return objects for command and command context + * because users should NOT modify any of them! + */ + const Command& command(const ShellCommandId& cmd_id) const; + const CommandContext& command_context(const ShellCommandId& cmd_id) const; + std::vector command_dependency( + const ShellCommandId& cmd_id) const; + std::vector commands_by_class( + const ShellCommandClassId& cmd_class_id) const; - /* Short function, including only the data exchange - * This function requires the data exchange to be constant - * This is designed for outputting functions without external data than the - */ - void set_command_const_execute_function(const ShellCommandId& cmd_id, - std::function exec_func); + public: /* Public mutators */ + void add_title(const char* title); + ShellCommandId add_command(const Command& cmd, const char* descr); + void set_command_class(const ShellCommandId& cmd_id, + const ShellCommandClassId& cmd_class_id); + /* Link the execute function to a command + * We support here different types of functions to be executed in the shell + * Users just need to specify the function object and its type will be + * automatically inferred + * + * Note that all the function should return exit codes complying to the + * shell_exit_code.h execept the internal functions + */ - /* Short function, including only the data exchange - * This function allows modification to the data exchange - * This is designed for internal implementing functions without external data than the - */ - void set_command_execute_function(const ShellCommandId& cmd_id, - std::function exec_func); + /* Standard function, including the data exchange and commands + * This function requires the data exchange to be constant + * This is designed for outputting functions requiring external data than the + * + */ + void set_command_const_execute_function( + const ShellCommandId& cmd_id, + std::function + exec_func); - /* Built-in function, including only the shell envoriment variables */ - void set_command_execute_function(const ShellCommandId& cmd_id, - std::function exec_func); + /* Standard function, including the data exchange and commands + * This function allows modification to the data exchange + * This is designed for implementing functions requiring external data than + * the + */ + void set_command_execute_function( + const ShellCommandId& cmd_id, + std::function exec_func); - /* Marco function, which directly call a macro function without command parsing */ - void set_command_execute_function(const ShellCommandId& cmd_id, - std::function exec_func); + /* Short function, including only the data exchange + * This function requires the data exchange to be constant + * This is designed for outputting functions without external data than the + * + */ + void set_command_const_execute_function( + const ShellCommandId& cmd_id, std::function exec_func); - void set_command_dependency(const ShellCommandId& cmd_id, - const std::vector& cmd_dependency); - ShellCommandClassId add_command_class(const char* name); - public: /* Public validators */ - bool valid_command_id(const ShellCommandId& cmd_id) const; - bool valid_command_class_id(const ShellCommandClassId& cmd_class_id) const; - public: /* Public executors */ - /* Start the interactive mode, where users will type-in command by command */ - void run_interactive_mode(T& context, const bool& quiet_mode = false); - /* Start the script mode, where users provide a file which includes all the commands to run */ - void run_script_mode(const char* script_file_name, - T& context, - const bool& batch_mode = false); - /* Print all the commands by their classes. This is actually the help desk */ - void print_commands() const; - /* Find the exit code (assume quit shell now) */ - int exit_code() const; - /* Show statistics of errors during command execution */ - int execution_errors() const; - /* Quit the shell */ - void exit(const int& init_err = 0) const; - private: /* Private executors */ - /* Execute a command, the command line is the user's input to launch a command - * The common_context is the data structure to exchange data between commands - */ - int execute_command(const char* cmd_line, T& common_context); - private: /* Internal data */ - /* Name of the shell, this will appear in the interactive mode */ - std::string name_; + /* Short function, including only the data exchange + * This function allows modification to the data exchange + * This is designed for internal implementing functions without external data + * than the + */ + void set_command_execute_function(const ShellCommandId& cmd_id, + std::function exec_func); - /* Title of the shell, this will appear in the interactive mode as an introduction */ - std::string title_; + /* Built-in function, including only the shell envoriment variables */ + void set_command_execute_function(const ShellCommandId& cmd_id, + std::function exec_func); - /* Unique ids for each class of command */ - vtr::vector command_class_ids_; + /* Marco function, which directly call a macro function without command + * parsing */ + void set_command_execute_function(const ShellCommandId& cmd_id, + std::function exec_func); - /* Names for each class of command */ - vtr::vector command_class_names_; + void set_command_dependency( + const ShellCommandId& cmd_id, + const std::vector& cmd_dependency); + ShellCommandClassId add_command_class(const char* name); - /* Unique ids for each command */ - vtr::vector command_ids_; + public: /* Public validators */ + bool valid_command_id(const ShellCommandId& cmd_id) const; + bool valid_command_class_id(const ShellCommandClassId& cmd_class_id) const; - /* Objects for each command */ - vtr::vector commands_; + public: /* Public executors */ + /* Start the interactive mode, where users will type-in command by command */ + void run_interactive_mode(T& context, const bool& quiet_mode = false); + /* Start the script mode, where users provide a file which includes all the + * commands to run */ + void run_script_mode(const char* script_file_name, T& context, + const bool& batch_mode = false); + /* Print all the commands by their classes. This is actually the help desk */ + void print_commands() const; + /* Find the exit code (assume quit shell now) */ + int exit_code() const; + /* Show statistics of errors during command execution */ + int execution_errors() const; + /* Quit the shell */ + void exit(const int& init_err = 0) const; - /* Parsing results for each command */ - vtr::vector command_contexts_; + private: /* Private executors */ + /* Execute a command, the command line is the user's input to launch a command + * The common_context is the data structure to exchange data between commands + */ + int execute_command(const char* cmd_line, T& common_context); - /* Description of the command, this is going to be printed out in the help desk */ - vtr::vector command_description_; + private: /* Internal data */ + /* Name of the shell, this will appear in the interactive mode */ + std::string name_; - /* Class ids for each command */ - vtr::vector command_classes_; + /* Title of the shell, this will appear in the interactive mode as an + * introduction */ + std::string title_; - /* Function pointers to execute each command - * We support here three types of functions to be executed in the shell - * 1. Standard function, including the data exchange and commands - * 2. Short function, including only the data exchange - * 3. Built-in function, including only the shell envoriment variables - * 4. Marco function, which directly call a macro function without command parsing - */ - vtr::vector> command_const_execute_functions_; - vtr::vector> command_standard_execute_functions_; - vtr::vector> command_short_const_execute_functions_; - vtr::vector> command_short_execute_functions_; - vtr::vector> command_builtin_execute_functions_; - vtr::vector> command_macro_execute_functions_; + /* Unique ids for each class of command */ + vtr::vector command_class_ids_; - /* Type of execute functions for each command. - * This is supposed to be an internal data ONLY - */ - vtr::vector command_execute_function_types_; + /* Names for each class of command */ + vtr::vector command_class_names_; - /* A flag to indicate if the command has been executed */ - vtr::vector command_status_; + /* Unique ids for each command */ + vtr::vector command_ids_; - /* Dependency graph for different commands, - * This helps the shell interface to check if a command need other commands to be run before its execution - */ - vtr::vector> command_dependencies_; + /* Objects for each command */ + vtr::vector commands_; - /* Fast name look-up */ - std::map command_name2ids_; - std::map command_class2ids_; - vtr::vector> commands_by_classes_; + /* Parsing results for each command */ + vtr::vector command_contexts_; - /* Timer */ - std::clock_t time_start_; + /* Description of the command, this is going to be printed out in the help + * desk */ + vtr::vector command_description_; + + /* Class ids for each command */ + vtr::vector command_classes_; + + /* Function pointers to execute each command + * We support here three types of functions to be executed in the shell + * 1. Standard function, including the data exchange and commands + * 2. Short function, including only the data exchange + * 3. Built-in function, including only the shell envoriment variables + * 4. Marco function, which directly call a macro function without command + * parsing + */ + vtr::vector> + command_const_execute_functions_; + vtr::vector> + command_standard_execute_functions_; + vtr::vector> + command_short_const_execute_functions_; + vtr::vector> + command_short_execute_functions_; + vtr::vector> + command_builtin_execute_functions_; + vtr::vector> + command_macro_execute_functions_; + + /* Type of execute functions for each command. + * This is supposed to be an internal data ONLY + */ + vtr::vector command_execute_function_types_; + + /* A flag to indicate if the command has been executed */ + vtr::vector command_status_; + + /* Dependency graph for different commands, + * This helps the shell interface to check if a command need other commands to + * be run before its execution + */ + vtr::vector> + command_dependencies_; + + /* Fast name look-up */ + std::map command_name2ids_; + std::map command_class2ids_; + vtr::vector> + commands_by_classes_; + + /* Timer */ + std::clock_t time_start_; }; } /* End namespace openfpga */ diff --git a/libs/libopenfpgashell/src/shell_fwd.h b/libs/libopenfpgashell/src/shell_fwd.h index 5a1557210..04b941eef 100644 --- a/libs/libopenfpgashell/src/shell_fwd.h +++ b/libs/libopenfpgashell/src/shell_fwd.h @@ -7,7 +7,7 @@ namespace openfpga { /********************************************************************* - * A strong id for the options used by a command + * A strong id for the options used by a command ********************************************************************/ struct shell_command_id_tag; struct shell_command_class_id_tag; diff --git a/libs/libopenfpgashell/test/test_command_parser.cpp b/libs/libopenfpgashell/test/test_command_parser.cpp index c3e004137..1a48ca097 100644 --- a/libs/libopenfpgashell/test/test_command_parser.cpp +++ b/libs/libopenfpgashell/test/test_command_parser.cpp @@ -1,8 +1,8 @@ /******************************************************************** - * Test the command parser by pre-defining a simple command + * Test the command parser by pre-defining a simple command *******************************************************************/ -#include "command_parser.h" #include "command_echo.h" +#include "command_parser.h" using namespace openfpga; @@ -11,19 +11,22 @@ int main(int argc, char** argv) { Command cmd("read_openfpga_arch"); /* Add options to the command */ /* Option to specify architecture file */ - CommandOptionId opt_arch_file = cmd.add_option("file", true, "Specify the OpenFPGA architecture file"); + CommandOptionId opt_arch_file = + cmd.add_option("file", true, "Specify the OpenFPGA architecture file"); cmd.set_option_require_value(opt_arch_file, OPT_STRING); cmd.set_option_short_name(opt_arch_file, "f"); - CommandOptionId opt_echo_arch = cmd.add_option("echo", false, "Echo the parsed result to file"); + CommandOptionId opt_echo_arch = + cmd.add_option("echo", false, "Echo the parsed result to file"); cmd.set_option_require_value(opt_echo_arch, OPT_STRING); cmd.set_option_short_name(opt_echo_arch, "e"); - CommandOptionId opt_help = cmd.add_option("help", false, "Help desk"); + CommandOptionId opt_help = cmd.add_option("help", false, "Help desk"); cmd.set_option_short_name(opt_help, "h"); - /* Parse the option, to avoid issues, we use the command name to replace the argv[0] */ - std::vector cmd_opts; + /* Parse the option, to avoid issues, we use the command name to replace the + * argv[0] */ + std::vector cmd_opts; cmd_opts.push_back(cmd.name()); for (int iarg = 1; iarg < argc; ++iarg) { cmd_opts.push_back(std::string(argv[iarg])); @@ -34,7 +37,7 @@ int main(int argc, char** argv) { /* Echo the command */ print_command_options(cmd); } else { - /* Let user to confirm selected options */ + /* Let user to confirm selected options */ print_command_context(cmd, cmd_context); } diff --git a/libs/libopenfpgashell/test/test_shell.cpp b/libs/libopenfpgashell/test/test_shell.cpp index 0edc257dd..c871848c6 100644 --- a/libs/libopenfpgashell/test/test_shell.cpp +++ b/libs/libopenfpgashell/test/test_shell.cpp @@ -2,61 +2,60 @@ * Test the shell interface by pre-defining simple commands * like exit() and help() *******************************************************************/ -#include "vtr_log.h" -#include "command_parser.h" #include "command_echo.h" +#include "command_parser.h" #include "shell.h" +#include "vtr_log.h" using namespace openfpga; class ShellContext { - public: - int a; + public: + int a; }; -static -int shell_execute_set(ShellContext& context, - const Command& cmd, const CommandContext& cmd_context) { +static int shell_execute_set(ShellContext& context, const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_id = cmd.option("value"); /* Get the value of a in the command context */ context.a = std::atoi(cmd_context.option_value(cmd, opt_id).c_str()); - return CMD_EXEC_SUCCESS; + return CMD_EXEC_SUCCESS; } -static -int shell_execute_print(ShellContext& context) { +static int shell_execute_print(ShellContext& context) { VTR_LOG("a=%d\n", context.a); - return CMD_EXEC_SUCCESS; + return CMD_EXEC_SUCCESS; } -static -int shell_execute_print_macro(int argc, char** argv) { +static int shell_execute_print_macro(int argc, char** argv) { VTR_LOG("Number of arguments: %d\n", argc); VTR_LOG("Detailed arguments:\n"); for (int iarg = 0; iarg < argc; ++iarg) { VTR_LOG("\t[%d]: %s\n", iarg, argv[iarg]); } - return CMD_EXEC_SUCCESS; + return CMD_EXEC_SUCCESS; } int main(int argc, char** argv) { /* Create the command to launch shell in different modes */ Command start_cmd("test_shell"); /* Add two options: - * '--interactive', -i': launch the interactive mode - * '--file', -f': launch the script mode + * '--interactive', -i': launch the interactive mode + * '--file', -f': launch the script mode */ - CommandOptionId opt_interactive = start_cmd.add_option("interactive", false, "Launch the shell in interactive mode"); + CommandOptionId opt_interactive = start_cmd.add_option( + "interactive", false, "Launch the shell in interactive mode"); start_cmd.set_option_short_name(opt_interactive, "i"); - CommandOptionId opt_script_mode = start_cmd.add_option("file", false, "Launch the shell in script mode"); + CommandOptionId opt_script_mode = + start_cmd.add_option("file", false, "Launch the shell in script mode"); start_cmd.set_option_require_value(opt_script_mode, OPT_STRING); start_cmd.set_option_short_name(opt_script_mode, "f"); - CommandOptionId opt_help = start_cmd.add_option("help", false, "Help desk"); + CommandOptionId opt_help = start_cmd.add_option("help", false, "Help desk"); start_cmd.set_option_short_name(opt_help, "h"); /* Create a shell object @@ -69,24 +68,49 @@ int main(int argc, char** argv) { shell_title += std::string("The MIT License\n"); shell_title += std::string("\n"); - shell_title += std::string("Copyright (c) 2018 LNIS - The University of Utah\n"); + shell_title += + std::string("Copyright (c) 2018 LNIS - The University of Utah\n"); shell_title += std::string("\n"); - shell_title += std::string("Permission is hereby granted, free of charge, to any person obtaining a copy\n"); - shell_title += std::string("of this software and associated documentation files (the \"Software\"), to deal\n"); - shell_title += std::string("in the Software without restriction, including without limitation the rights\n"); - shell_title += std::string("to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n"); - shell_title += std::string("copies of the Software, and to permit persons to whom the Software is\n"); - shell_title += std::string("furnished to do so, subject to the following conditions:\n"); + shell_title += std::string( + "Permission is hereby granted, free of charge, to any person obtaining a " + "copy\n"); + shell_title += std::string( + "of this software and associated documentation files (the \"Software\"), " + "to deal\n"); + shell_title += std::string( + "in the Software without restriction, including without limitation the " + "rights\n"); + shell_title += std::string( + "to use, copy, modify, merge, publish, distribute, sublicense, and/or " + "sell\n"); + shell_title += std::string( + "copies of the Software, and to permit persons to whom the Software is\n"); + shell_title += + std::string("furnished to do so, subject to the following conditions:\n"); shell_title += std::string("\n"); - shell_title += std::string("The above copyright notice and this permission notice shall be included in\n"); - shell_title += std::string("all copies or substantial portions of the Software.\n"); + shell_title += std::string( + "The above copyright notice and this permission notice shall be included " + "in\n"); + shell_title += + std::string("all copies or substantial portions of the Software.\n"); shell_title += std::string("\n"); - shell_title += std::string("THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"); - shell_title += std::string("IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"); - shell_title += std::string("FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n"); - shell_title += std::string("AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"); - shell_title += std::string("LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n"); - shell_title += std::string("OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n"); + shell_title += std::string( + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS " + "OR\n"); + shell_title += std::string( + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF " + "MERCHANTABILITY,\n"); + shell_title += std::string( + "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL " + "THE\n"); + shell_title += std::string( + "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"); + shell_title += std::string( + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING " + "FROM,\n"); + shell_title += std::string( + "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS " + "IN\n"); shell_title += std::string("THE SOFTWARE.\n"); shell.add_title(shell_title.c_str()); @@ -94,53 +118,65 @@ int main(int argc, char** argv) { /* Add a new class of commands */ ShellCommandClassId arith_cmd_class = shell.add_command_class("Arithmetic"); - /* Create a command of 'set' with a required option 'value' with a value - * This function sets a value to an internal variable of ShellContext + /* Create a command of 'set' with a required option 'value' with a value + * This function sets a value to an internal variable of ShellContext */ Command shell_cmd_set("set"); - CommandOptionId set_opt_value = shell_cmd_set.add_option("value", true, "value of variable"); + CommandOptionId set_opt_value = + shell_cmd_set.add_option("value", true, "value of variable"); shell_cmd_set.set_option_require_value(set_opt_value, OPT_STRING); - ShellCommandId shell_cmd_set_id = shell.add_command(shell_cmd_set, "Set a value to internal variable 'a'"); + ShellCommandId shell_cmd_set_id = + shell.add_command(shell_cmd_set, "Set a value to internal variable 'a'"); shell.set_command_class(shell_cmd_set_id, arith_cmd_class); shell.set_command_execute_function(shell_cmd_set_id, shell_execute_set); - /* Create a command of 'print' - * This function will print the value of an internal variable of ShellContext + /* Create a command of 'print' + * This function will print the value of an internal variable of ShellContext * We set a dependency to this command as it MUST be executed after 'set' */ Command shell_cmd_print("print"); - ShellCommandId shell_cmd_print_id = shell.add_command(shell_cmd_print, "Print the value of internal variable 'a'"); + ShellCommandId shell_cmd_print_id = shell.add_command( + shell_cmd_print, "Print the value of internal variable 'a'"); shell.set_command_class(shell_cmd_print_id, arith_cmd_class); shell.set_command_execute_function(shell_cmd_print_id, shell_execute_print); - shell.set_command_dependency(shell_cmd_print_id, std::vector(1, shell_cmd_set_id)); + shell.set_command_dependency( + shell_cmd_print_id, std::vector(1, shell_cmd_set_id)); - /* Create a macro command of 'print_macro' - * This function will print the value of an internal variable of ShellContext + /* Create a macro command of 'print_macro' + * This function will print the value of an internal variable of ShellContext */ Command shell_cmd_print_macro("print_macro"); - ShellCommandId shell_cmd_print_macro_id = shell.add_command(shell_cmd_print_macro, "A macro function to print arguments"); + ShellCommandId shell_cmd_print_macro_id = shell.add_command( + shell_cmd_print_macro, "A macro function to print arguments"); shell.set_command_class(shell_cmd_print_macro_id, arith_cmd_class); - shell.set_command_execute_function(shell_cmd_print_macro_id, shell_execute_print_macro); + shell.set_command_execute_function(shell_cmd_print_macro_id, + shell_execute_print_macro); /* Add a new class of commands */ ShellCommandClassId basic_cmd_class = shell.add_command_class("Basic"); Command shell_cmd_exit("exit"); - ShellCommandId shell_cmd_exit_id = shell.add_command(shell_cmd_exit, "Exit the shell"); + ShellCommandId shell_cmd_exit_id = + shell.add_command(shell_cmd_exit, "Exit the shell"); shell.set_command_class(shell_cmd_exit_id, basic_cmd_class); - shell.set_command_execute_function(shell_cmd_exit_id, [shell](){shell.exit();}); + shell.set_command_execute_function(shell_cmd_exit_id, + [shell]() { shell.exit(); }); - /* Note: help must be the last to add because the linking to execute function will do a snapshot on the shell */ + /* Note: help must be the last to add because the linking to execute function + * will do a snapshot on the shell */ Command shell_cmd_help("help"); - ShellCommandId shell_cmd_help_id = shell.add_command(shell_cmd_help, "Launch help desk"); + ShellCommandId shell_cmd_help_id = + shell.add_command(shell_cmd_help, "Launch help desk"); shell.set_command_class(shell_cmd_help_id, basic_cmd_class); - shell.set_command_execute_function(shell_cmd_help_id, [shell](){shell.print_commands();}); + shell.set_command_execute_function(shell_cmd_help_id, + [shell]() { shell.print_commands(); }); /* Create the data base for the shell */ ShellContext shell_context; - /* Parse the option, to avoid issues, we use the command name to replace the argv[0] */ - std::vector cmd_opts; + /* Parse the option, to avoid issues, we use the command name to replace the + * argv[0] */ + std::vector cmd_opts; cmd_opts.push_back(start_cmd.name()); for (int iarg = 1; iarg < argc; ++iarg) { cmd_opts.push_back(std::string(argv[iarg])); @@ -151,15 +187,16 @@ int main(int argc, char** argv) { /* Parse fail: Echo the command */ print_command_options(start_cmd); } else { - /* Parse succeed. Start a shell */ + /* Parse succeed. Start a shell */ if (true == start_cmd_context.option_enable(start_cmd, opt_interactive)) { shell.run_interactive_mode(shell_context); return 0; - } + } if (true == start_cmd_context.option_enable(start_cmd, opt_script_mode)) { - shell.run_script_mode(start_cmd_context.option_value(start_cmd, opt_script_mode).c_str(), - shell_context); + shell.run_script_mode( + start_cmd_context.option_value(start_cmd, opt_script_mode).c_str(), + shell_context); return 0; } /* Reach here there is something wrong, show the help desk */ diff --git a/libs/libopenfpgautil/src/openfpga_decode.cpp b/libs/libopenfpgautil/src/openfpga_decode.cpp index bc45e9682..988bec456 100644 --- a/libs/libopenfpgautil/src/openfpga_decode.cpp +++ b/libs/libopenfpgautil/src/openfpga_decode.cpp @@ -1,20 +1,19 @@ /*************************************************************************************** - * This file includes functions that are used to decode integer to binary vectors - * or the reverse operation + * This file includes functions that are used to decode integer to binary + *vectors or the reverse operation ***************************************************************************************/ #include /* Headers from vtrutil library */ -#include "vtr_assert.h" - #include "openfpga_decode.h" +#include "vtr_assert.h" /* begin namespace openfpga */ namespace openfpga { -/******************************************************************** +/******************************************************************** * Convert an integer to an one-hot encoding integer array - * For example: + * For example: * Input integer: 3 * Binary length : 4 * Output: @@ -22,18 +21,17 @@ namespace openfpga { * ret | 0 | 0 | 0 | 1 * * If you need all zero code, set the input integer same as the binary length - * For example: + * For example: * Input integer: 4 * Binary length : 4 * Output: * index | 0 | 1 | 2 | 3 * ret | 0 | 0 | 0 | 0 - * + * ********************************************************************/ -std::vector ito1hot_vec(const size_t& in_int, - const size_t& bin_len) { +std::vector ito1hot_vec(const size_t& in_int, const size_t& bin_len) { /* Make sure we do not have any overflow! */ - VTR_ASSERT ( (in_int <= bin_len) ); + VTR_ASSERT((in_int <= bin_len)); /* Initialize */ std::vector ret(bin_len, 0); @@ -42,13 +40,13 @@ std::vector ito1hot_vec(const size_t& in_int, return ret; /* all zero case */ } ret[in_int] = 1; /* Keep a good sequence of bits */ - + return ret; } -/******************************************************************** +/******************************************************************** * Convert an integer to an one-hot encoding character array - * For example: + * For example: * Input integer: 3 * Binary length : 4 * Output: @@ -56,19 +54,18 @@ std::vector ito1hot_vec(const size_t& in_int, * ret | 0 | 0 | 0 | 1 * * If you need all zero code, set the input integer same as the binary length - * For example: + * For example: * Input integer: 4 * Binary length : 4 * Output: * index | 0 | 1 | 2 | 3 * ret | 0 | 0 | 0 | 0 - * + * ********************************************************************/ -std::vector ito1hot_charvec(const size_t& in_int, - const size_t& bin_len, +std::vector ito1hot_charvec(const size_t& in_int, const size_t& bin_len, const char& default_bit) { /* Make sure we do not have any overflow! */ - VTR_ASSERT ( (in_int <= bin_len) ); + VTR_ASSERT((in_int <= bin_len)); /* Initialize */ std::vector ret(bin_len, default_bit); @@ -77,12 +74,11 @@ std::vector ito1hot_charvec(const size_t& in_int, return ret; /* all zero case */ } ret[in_int] = '1'; /* Keep a good sequence of bits */ - + return ret; } -void replace_str_bits(std::string& str_to_convert, - const char& bit_in_place, +void replace_str_bits(std::string& str_to_convert, const char& bit_in_place, const char& bit_to_replace) { for (char& bit : str_to_convert) { if (bit_in_place == bit) { @@ -96,7 +92,8 @@ std::string combine_two_1hot_str(const std::string& code1, VTR_ASSERT(code1.length() == code2.length()); std::string ret = code1; for (size_t ichar = 0; ichar < code2.length(); ichar++) { - VTR_ASSERT('0' == code2[ichar] || '1' == code2[ichar] || 'x' == code2[ichar]); + VTR_ASSERT('0' == code2[ichar] || '1' == code2[ichar] || + 'x' == code2[ichar]); if ('1' == code2[ichar] || '0' == code2[ichar]) { ret[ichar] = code2[ichar]; } @@ -104,70 +101,68 @@ std::string combine_two_1hot_str(const std::string& code1, return ret; } -/******************************************************************** - * Converter an integer to a binary vector - * For example: +/******************************************************************** + * Converter an integer to a binary vector + * For example: * Input integer: 4 * Binary length : 3 * Output: * index | 0 | 1 | 2 - * ret | 0 | 0 | 1 + * ret | 0 | 0 | 1 ********************************************************************/ -std::vector itobin_vec(const size_t& in_int, - const size_t& bin_len) { +std::vector itobin_vec(const size_t& in_int, const size_t& bin_len) { std::vector ret(bin_len, 0); /* Make sure we do not have any overflow! */ - VTR_ASSERT ( (in_int < pow(2., bin_len)) ); - + VTR_ASSERT((in_int < pow(2., bin_len))); + size_t temp = in_int; for (size_t i = 0; i < bin_len; i++) { - if (1 == temp % 2) { + if (1 == temp % 2) { ret[i] = 1; /* Keep a good sequence of bits */ } temp = temp / 2; } - + return ret; } -/******************************************************************** - * Converter an integer to a binary vector - * For example: +/******************************************************************** + * Converter an integer to a binary vector + * For example: * Input integer: 4 * Binary length : 3 * Output: * index | 0 | 1 | 2 - * ret | 0 | 0 | 1 + * ret | 0 | 0 | 1 * * This function is optimized to return a vector of char * which has a smaller memory footprint than size_t ********************************************************************/ -std::vector itobin_charvec(const size_t& in_int, - const size_t& bin_len) { +std::vector itobin_charvec(const size_t& in_int, const size_t& bin_len) { std::vector ret(bin_len, '0'); /* Make sure we do not have any overflow! */ - VTR_ASSERT ( (in_int < pow(2., bin_len)) ); - + VTR_ASSERT((in_int < pow(2., bin_len))); + size_t temp = in_int; for (size_t i = 0; i < bin_len; i++) { - if (1 == temp % 2) { + if (1 == temp % 2) { ret[i] = '1'; /* Keep a good sequence of bits */ } temp = temp / 2; } - + return ret; } -/******************************************************************** +/******************************************************************** * Converter a binary vector to an integer - * For example: + * For example: * Binary length : 3 * Input: * index | 0 | 1 | 2 - * ret | 0 | 0 | 1 + * ret | 0 | 0 | 1 * * Output integer: 4 * @@ -186,8 +181,8 @@ size_t bintoi_charvec(const std::vector& bin) { return ret; } -/******************************************************************** - * Expand all the don't care bits in a string +/******************************************************************** + * Expand all the don't care bits in a string * A don't care 'x' can be decoded to either '0' or '1' * For example: * input: 0x1x @@ -198,7 +193,8 @@ size_t bintoi_charvec(const std::vector& bin) { * * Return all the strings ********************************************************************/ -std::vector expand_dont_care_bin_str(const std::string& input_str) { +std::vector expand_dont_care_bin_str( + const std::string& input_str) { std::vector ret; /* If the input is don't care free, we can retrun */ @@ -220,13 +216,15 @@ std::vector expand_dont_care_bin_str(const std::string& input_str) if (DONT_CARE_CHAR == input_str[i]) { std::string temp_input_str = input_str; /* Flip to '0' and go recursively */ - temp_input_str[i] = '0'; - for (const std::string& expanded_str : expand_dont_care_bin_str(temp_input_str)) { + temp_input_str[i] = '0'; + for (const std::string& expanded_str : + expand_dont_care_bin_str(temp_input_str)) { ret.push_back(expanded_str); } /* Flip to '1' and go recursively */ - temp_input_str[i] = '1'; - for (const std::string& expanded_str : expand_dont_care_bin_str(temp_input_str)) { + temp_input_str[i] = '1'; + for (const std::string& expanded_str : + expand_dont_care_bin_str(temp_input_str)) { ret.push_back(expanded_str); } break; diff --git a/libs/libopenfpgautil/src/openfpga_decode.h b/libs/libopenfpgautil/src/openfpga_decode.h index 6b3029e6e..221fdad13 100644 --- a/libs/libopenfpgautil/src/openfpga_decode.h +++ b/libs/libopenfpgautil/src/openfpga_decode.h @@ -5,8 +5,9 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include + #include +#include /******************************************************************** * Function declaration @@ -14,16 +15,14 @@ /* namespace openfpga begins */ namespace openfpga { -/**************************************** - * Constants +/**************************************** + * Constants */ constexpr const char DONT_CARE_CHAR = 'x'; -std::vector ito1hot_vec(const size_t& in_int, - const size_t& bin_len); +std::vector ito1hot_vec(const size_t& in_int, const size_t& bin_len); -std::vector ito1hot_charvec(const size_t& in_int, - const size_t& bin_len, +std::vector ito1hot_charvec(const size_t& in_int, const size_t& bin_len, const char& default_bit = '0'); /** @brief Replace the characters in a string with a given replacement @@ -31,16 +30,15 @@ std::vector ito1hot_charvec(const size_t& in_int, * @param bit_in_place the charater to be replaced * @param bit_to_replace the charater to replace the bit_in_place */ -void replace_str_bits(std::string& str_to_convert, - const char& bit_in_place, +void replace_str_bits(std::string& str_to_convert, const char& bit_in_place, const char& bit_to_replace); -/******************************************************************** +/******************************************************************** * @brief Combine to two 1-hot codes which are in string format * Any unique '1' or '0' will be merged * @note Where there are both '0' or '1' in the code1 and code2, * code2 bits will overwrite - * For example: + * For example: * Code 1: xx1x0x110 * Code 2: 01xx01xx1 * Output: 011x01111 @@ -49,16 +47,14 @@ void replace_str_bits(std::string& str_to_convert, std::string combine_two_1hot_str(const std::string& code1, const std::string& code2); -std::vector itobin_vec(const size_t& in_int, - const size_t& bin_len); +std::vector itobin_vec(const size_t& in_int, const size_t& bin_len); -std::vector itobin_charvec(const size_t& in_int, - const size_t& bin_len); +std::vector itobin_charvec(const size_t& in_int, const size_t& bin_len); size_t bintoi_charvec(const std::vector& bin); std::vector expand_dont_care_bin_str(const std::string& input_str); -} /* namespace openfpga ends */ +} // namespace openfpga #endif diff --git a/libs/libopenfpgautil/src/openfpga_digest.cpp b/libs/libopenfpgautil/src/openfpga_digest.cpp index dbbc9b5ff..1df3c7004 100644 --- a/libs/libopenfpgautil/src/openfpga_digest.cpp +++ b/libs/libopenfpgautil/src/openfpga_digest.cpp @@ -3,20 +3,21 @@ * in OpenFPGA framework *******************************************************************/ #include -#include + #include +#include /* Headers from vtrutil library */ #include "vtr_log.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" +#include "openfpga_digest.h" namespace openfpga { /******************************************************************** * A most utilized function to validate the file stream - * This function will return true or false for a valid/invalid file stream + * This function will return true or false for a valid/invalid file stream *******************************************************************/ bool valid_file_stream(std::fstream& fp) { /* Validate the file stream */ @@ -29,29 +30,25 @@ bool valid_file_stream(std::fstream& fp) { /******************************************************************** * A most utilized function to validate the file stream - * This function will error out for a valid/invalid file stream + * This function will error out for a valid/invalid file stream *******************************************************************/ -void check_file_stream(const char* fname, - std::fstream& fp) { - +void check_file_stream(const char* fname, std::fstream& fp) { if (false == valid_file_stream(fp)) { - VTR_LOG("Invalid file stream for file: %s\n", - fname); + VTR_LOG("Invalid file stream for file: %s\n", fname); exit(1); } } /******************************************************************** * Format a directory path: - * 1. Replace "\" with "/" + * 1. Replace "\" with "/" * 2. add a "/" if the string does not end with a "/" *******************************************************************/ std::string format_dir_path(const std::string& dir_path_to_format) { std::string formatted_dir_path = dir_path_to_format; - #ifdef _WIN32 -/* For windows OS, replace any '/' with '\' */ + /* For windows OS, replace any '/' with '\' */ char illegal_back_slash = '/'; char legal_back_slash = '\\'; #else @@ -65,30 +62,29 @@ std::string format_dir_path(const std::string& dir_path_to_format) { } /* Replace "\" with "/" */ - std::replace(formatted_dir_path.begin(), formatted_dir_path.end(), illegal_back_slash, legal_back_slash); + std::replace(formatted_dir_path.begin(), formatted_dir_path.end(), + illegal_back_slash, legal_back_slash); /* Add a back slash the string is not ended like this! */ if (legal_back_slash != formatted_dir_path.back()) { formatted_dir_path.push_back(legal_back_slash); } - - return formatted_dir_path; + + return formatted_dir_path; } -/******************************************************************** - * Extract full file name from a full path of file +/******************************************************************** + * Extract full file name from a full path of file * For example: / * This function will return ********************************************************************/ std::string find_path_file_name(const std::string& file_name) { - - #ifdef _WIN32 -/* For windows OS, replace any '/' with '\' */ + /* For windows OS, replace any '/' with '\' */ char back_slash = '\\'; #else char back_slash = '/'; -#endif +#endif /* Find the last '/' in the string and return the left part */ size_t found = file_name.rfind(back_slash); @@ -99,20 +95,18 @@ std::string find_path_file_name(const std::string& file_name) { return file_name; } -/******************************************************************** +/******************************************************************** * Extract full directory path from a full path of file * For example: / * This function will return ********************************************************************/ std::string find_path_dir_name(const std::string& file_name) { - - #ifdef _WIN32 -/* For windows OS, replace any '/' with '\' */ + /* For windows OS, replace any '/' with '\' */ char back_slash = '\\'; #else char back_slash = '/'; -#endif +#endif /* Find the last '/' in the string and return the left part */ size_t found = file_name.rfind(back_slash); @@ -123,12 +117,10 @@ std::string find_path_dir_name(const std::string& file_name) { return std::string(); } -/******************************************************************** +/******************************************************************** * Create a directory with a given path ********************************************************************/ -static -bool create_dir_path(const std::string& dir_path, - const bool& verbose) { +static bool create_dir_path(const std::string& dir_path, const bool& verbose) { /* Give up if the path is empty */ if (true == dir_path.empty()) { VTR_LOG_WARN("Directory path is empty and nothing will be created.\n"); @@ -138,48 +130,43 @@ bool create_dir_path(const std::string& dir_path, /* Try to create a directory */ #ifdef _WIN32 int ret = mkdir(dir_path.c_str()); -#else - int ret = mkdir(dir_path.c_str(), S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH); +#else + int ret = mkdir(dir_path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); #endif /* Analyze the return flag and output status */ switch (ret) { - case 0: - VTR_LOGV(verbose, - "Succeed to create directory '%s'\n", - dir_path.c_str()); - return true; - case -1: - if (EEXIST == errno) { - VTR_LOGV_WARN(verbose, - "Directory '%s' already exists. Will overwrite contents\n", - dir_path.c_str()); + case 0: + VTR_LOGV(verbose, "Succeed to create directory '%s'\n", dir_path.c_str()); return true; - } - VTR_LOG_ERROR("Create directory '%s'...Failed!\n", - dir_path.c_str()); - exit(1); - break; - default: - VTR_LOG_ERROR("Create directory '%s'...Failed!\n", - dir_path.c_str()); - exit(1); - return false; + case -1: + if (EEXIST == errno) { + VTR_LOGV_WARN( + verbose, "Directory '%s' already exists. Will overwrite contents\n", + dir_path.c_str()); + return true; + } + VTR_LOG_ERROR("Create directory '%s'...Failed!\n", dir_path.c_str()); + exit(1); + break; + default: + VTR_LOG_ERROR("Create directory '%s'...Failed!\n", dir_path.c_str()); + exit(1); + return false; } return false; } -/******************************************************************** +/******************************************************************** * Recursively create a directory with a given path * The create_dir_path() function will only try to create a directory * in the last level. If any parent directory is not created, it will * always fail. - * This function will try to create all the parent directory before - * creating the last level. + * This function will try to create all the parent directory before + * creating the last level. ********************************************************************/ -static -bool rec_create_dir_path(const std::string& dir_path) { +static bool rec_create_dir_path(const std::string& dir_path) { /* Give up if the path is empty */ if (true == dir_path.empty()) { VTR_LOG_WARN("Directory path is empty and nothing will be created.\n"); @@ -191,25 +178,24 @@ bool rec_create_dir_path(const std::string& dir_path) { */ #ifdef _WIN32 -/* For windows OS, replace any '/' with '\' */ + /* For windows OS, replace any '/' with '\' */ char back_slash = '\\'; #else char back_slash = '/'; -#endif +#endif + + std::vector slash_pos; - std::vector slash_pos; - /* Keep searching until we reach the end of the string */ for (size_t pos = 0; pos < dir_path.size(); ++pos) { /* Skip the pos = 0, we should avoid creating any root directory */ - if ( (back_slash == dir_path.at(pos)) - && (0 != pos)) { + if ((back_slash == dir_path.at(pos)) && (0 != pos)) { slash_pos.push_back(pos); } } /* Create directory by following the position of back slash - * For each back slash, create a sub string from the beginning + * For each back slash, create a sub string from the beginning * and try to create directory */ for (const size_t& pos : slash_pos) { @@ -218,25 +204,25 @@ bool rec_create_dir_path(const std::string& dir_path) { /* Turn on verbose output only for the last position: the leaf directory */ if (false == create_dir_path(sub_dir, &pos == &slash_pos.back())) { return false; - } + } } return true; } -/******************************************************************** +/******************************************************************** * Top function to create a directory with a given path * Allow users to select if use the recursive way or not * * Strongly recommend to use the recursive way, as it can maximum * guarantee the success in creation of directories ********************************************************************/ -void create_directory(const std::string& dir_path, const bool& recursive) { +void create_directory(const std::string& dir_path, const bool& recursive) { std::string formatted_dir_path = format_dir_path(dir_path); bool status = false; if (true == recursive) { - status = rec_create_dir_path(formatted_dir_path); + status = rec_create_dir_path(formatted_dir_path); } else { status = create_dir_path(formatted_dir_path, true); } @@ -248,11 +234,10 @@ void create_directory(const std::string& dir_path, const bool& recursive) { } } -/******************************************************************** - * Write a number of space to a file +/******************************************************************** + * Write a number of space to a file ********************************************************************/ -bool write_space_to_file(std::fstream& fp, - const size_t& num_space) { +bool write_space_to_file(std::fstream& fp, const size_t& num_space) { if (false == valid_file_stream(fp)) { return false; } @@ -264,11 +249,10 @@ bool write_space_to_file(std::fstream& fp, return true; } -/******************************************************************** - * Write a number of tab to a file +/******************************************************************** + * Write a number of tab to a file ********************************************************************/ -bool write_tab_to_file(std::fstream& fp, - const size_t& num_tab) { +bool write_tab_to_file(std::fstream& fp, const size_t& num_tab) { if (false == valid_file_stream(fp)) { return false; } @@ -280,4 +264,4 @@ bool write_tab_to_file(std::fstream& fp, return true; } -} /* namespace openfpga ends */ +} // namespace openfpga diff --git a/libs/libopenfpgautil/src/openfpga_digest.h b/libs/libopenfpgautil/src/openfpga_digest.h index c1a80ce99..741ff976c 100644 --- a/libs/libopenfpgautil/src/openfpga_digest.h +++ b/libs/libopenfpgautil/src/openfpga_digest.h @@ -14,8 +14,7 @@ namespace openfpga { bool valid_file_stream(std::fstream& fp); -void check_file_stream(const char* fname, - std::fstream& fp); +void check_file_stream(const char* fname, std::fstream& fp); std::string format_dir_path(const std::string& dir_path_to_format); @@ -23,14 +22,13 @@ std::string find_path_file_name(const std::string& file_name); std::string find_path_dir_name(const std::string& file_name); -void create_directory(const std::string& dir_path, const bool& recursive = true); +void create_directory(const std::string& dir_path, + const bool& recursive = true); -bool write_space_to_file(std::fstream& fp, - const size_t& num_space); +bool write_space_to_file(std::fstream& fp, const size_t& num_space); -bool write_tab_to_file(std::fstream& fp, - const size_t& num_tab); +bool write_tab_to_file(std::fstream& fp, const size_t& num_tab); -} /* namespace openfpga ends */ +} // namespace openfpga #endif diff --git a/libs/libopenfpgautil/src/openfpga_pb_parser.cpp b/libs/libopenfpgautil/src/openfpga_pb_parser.cpp index 3c174f589..842e56f73 100644 --- a/libs/libopenfpgautil/src/openfpga_pb_parser.cpp +++ b/libs/libopenfpgautil/src/openfpga_pb_parser.cpp @@ -1,25 +1,24 @@ /************************************************************************ * Member functions for Pb parsers ***********************************************************************/ +#include "openfpga_pb_parser.h" + #include -#include "vtr_assert.h" - #include "openfpga_tokenizer.h" - -#include "openfpga_pb_parser.h" +#include "vtr_assert.h" /* namespace openfpga begins */ namespace openfpga { /************************************************************************ - * Member functions for PbParser class + * Member functions for PbParser class ***********************************************************************/ /************************************************************************ * Constructors ***********************************************************************/ -PbParser::PbParser (const std::string& data) { +PbParser::PbParser(const std::string& data) { set_default_bracket(); set_default_delim(); set_data(data); @@ -29,21 +28,13 @@ PbParser::PbParser (const std::string& data) { * Public Accessors ***********************************************************************/ /* Get the data string */ -std::string PbParser::data() const { - return data_; -} +std::string PbParser::data() const { return data_; } -std::string PbParser::leaf() const { - return leaf_; -} +std::string PbParser::leaf() const { return leaf_; } -std::vector PbParser::parents() const { - return parents_; -} +std::vector PbParser::parents() const { return parents_; } -std::vector PbParser::modes() const { - return modes_; -} +std::vector PbParser::modes() const { return modes_; } /************************************************************************ * Public Mutators @@ -65,7 +56,7 @@ void PbParser::parse() { std::vector pb_tokens = tokenizer.split(delim_); /* The last pb is the leaf node. - * It should NOT be empty and should NOT contain any brackets! + * It should NOT be empty and should NOT contain any brackets! */ VTR_ASSERT(0 < pb_tokens.size()); VTR_ASSERT(false == pb_tokens.back().empty()); @@ -80,7 +71,7 @@ void PbParser::parse() { StringToken pb_tokenizer(pb_tokens[itok]); std::vector tokens = pb_tokenizer.split(bracket_.x()); /* Make sure we have a port name! */ - VTR_ASSERT_SAFE ((1 == tokens.size()) || (2 == tokens.size())); + VTR_ASSERT_SAFE((1 == tokens.size()) || (2 == tokens.size())); /* Store the pb_type name */ parents_.push_back(tokens[0]); @@ -92,9 +83,9 @@ void PbParser::parse() { modes_.push_back(std::string("default")); continue; /* We can finish here */ } - + /* If there is a mode name, extract it */ - VTR_ASSERT_SAFE (2 == tokens.size()); + VTR_ASSERT_SAFE(2 == tokens.size()); /* Chomp the ']' */ pb_tokenizer.set_data(tokens[1]); @@ -111,8 +102,6 @@ void PbParser::set_default_bracket() { bracket_.set_y(']'); } -void PbParser::set_default_delim() { - delim_ = '.'; -} +void PbParser::set_default_delim() { delim_ = '.'; } -} /* namespace openfpga ends */ +} // namespace openfpga diff --git a/libs/libopenfpgautil/src/openfpga_pb_parser.h b/libs/libopenfpgautil/src/openfpga_pb_parser.h index d59286136..7cbc829f7 100644 --- a/libs/libopenfpgautil/src/openfpga_pb_parser.h +++ b/libs/libopenfpgautil/src/openfpga_pb_parser.h @@ -7,9 +7,8 @@ #include #include -#include "vtr_geometry.h" - #include "openfpga_tokenizer.h" +#include "vtr_geometry.h" /************************************************************************ * This file includes parsers for pb_type definition in the architecture XML @@ -25,32 +24,35 @@ namespace openfpga { * 1. [].[] ... . * 2. . ... . * where each pb_type may be specified by a mode or use the default mode - * (mode name not given) + * (mode name not given) ***********************************************************************/ -class PbParser{ - public : /* Constructors*/ - PbParser (const std::string& data); - public : /* Public Accessors */ - std::string data() const; - std::string leaf() const; - std::vector parents() const; - std::vector modes() const; - public : /* Public Mutators */ - void set_data(const std::string& data); - private : /* Private Mutators */ - void parse(); - void set_default_bracket(); - void set_default_delim(); - private: /* Internal data */ - std::string data_; /* Lines to be splited */ - vtr::Point bracket_; - char delim_; - std::vector parents_; - std::vector modes_; - std::string leaf_; +class PbParser { + public: /* Constructors*/ + PbParser(const std::string& data); + + public: /* Public Accessors */ + std::string data() const; + std::string leaf() const; + std::vector parents() const; + std::vector modes() const; + + public: /* Public Mutators */ + void set_data(const std::string& data); + + private: /* Private Mutators */ + void parse(); + void set_default_bracket(); + void set_default_delim(); + + private: /* Internal data */ + std::string data_; /* Lines to be splited */ + vtr::Point bracket_; + char delim_; + std::vector parents_; + std::vector modes_; + std::string leaf_; }; -} /* namespace openfpga ends */ +} // namespace openfpga #endif - diff --git a/libs/libopenfpgautil/src/openfpga_port.cpp b/libs/libopenfpgautil/src/openfpga_port.cpp index 570fdf603..5d583bc6b 100644 --- a/libs/libopenfpgautil/src/openfpga_port.cpp +++ b/libs/libopenfpgautil/src/openfpga_port.cpp @@ -1,17 +1,16 @@ -#include #include #include +#include /* Headers from vtrutil library */ -#include "vtr_assert.h" - #include "openfpga_port.h" +#include "vtr_assert.h" /* namespace openfpga begins */ namespace openfpga { /************************************************************************ - * Member functions for BasicPort class + * Member functions for BasicPort class ***********************************************************************/ /************************************************************************ @@ -33,7 +32,8 @@ BasicPort::BasicPort(const char* name, const size_t& lsb, const size_t& msb) { set_origin_port_width(-1); } -BasicPort::BasicPort(const std::string& name, const size_t& lsb, const size_t& msb) { +BasicPort::BasicPort(const std::string& name, const size_t& lsb, + const size_t& msb) { set_name(name); set_width(lsb, msb); set_origin_port_width(-1); @@ -52,34 +52,28 @@ BasicPort::BasicPort(const std::string& name, const size_t& width) { } /************************************************************************ - * Accessors + * Accessors ***********************************************************************/ /* get the port width */ size_t BasicPort::get_width() const { if (true == is_valid()) { - return msb_ - lsb_ + 1; + return msb_ - lsb_ + 1; } return 0; /* invalid port has a zero width */ } - -/* get the LSB */ -size_t BasicPort::get_msb() const { - return msb_; -} /* get the LSB */ -size_t BasicPort::get_lsb() const { - return lsb_; -} +size_t BasicPort::get_msb() const { return msb_; } + +/* get the LSB */ +size_t BasicPort::get_lsb() const { return lsb_; } /* get the name */ -std::string BasicPort::get_name() const { - return name_; -} +std::string BasicPort::get_name() const { return name_; } /* Make a range of the pin indices */ std::vector BasicPort::pins() const { - std::vector pin_indices; + std::vector pin_indices; /* Return if the port is invalid */ if (false == is_valid()) { @@ -88,100 +82,98 @@ std::vector BasicPort::pins() const { /* For valid ports, create a vector whose length is the port width */ pin_indices.resize(get_width()); /* Fill in an incremental sequence */ - std::iota(pin_indices.begin(), pin_indices.end(), get_lsb()); + std::iota(pin_indices.begin(), pin_indices.end(), get_lsb()); /* Ensure the last one is MSB */ VTR_ASSERT(get_msb() == pin_indices.back()); return pin_indices; } -/* Check if a port can be merged with this port: their name should be the same */ +/* Check if a port can be merged with this port: their name should be the same + */ bool BasicPort::mergeable(const BasicPort& portA) const { return (0 == this->get_name().compare(portA.get_name())); -} +} /* Check if a port is contained by this port: - * this function will check if the (LSB, MSB) of portA - * is contained by the (LSB, MSB) of this port + * this function will check if the (LSB, MSB) of portA + * is contained by the (LSB, MSB) of this port */ bool BasicPort::contained(const BasicPort& portA) const { - return ( lsb_ <= portA.get_lsb() && portA.get_msb() <= msb_ ); + return (lsb_ <= portA.get_lsb() && portA.get_msb() <= msb_); } /* Set original port width */ -size_t BasicPort::get_origin_port_width() const { - return origin_port_width_; -} +size_t BasicPort::get_origin_port_width() const { return origin_port_width_; } /************************************************************************ - * Overloaded operators + * Overloaded operators ***********************************************************************/ -/* Two ports are the same only when: +/* Two ports are the same only when: * 1. port names are the same * 2. LSBs are the same - * 3. MSBs are the same + * 3. MSBs are the same */ -bool BasicPort::operator== (const BasicPort& portA) const { - if ( (0 == this->get_name().compare(portA.get_name())) - && (this->get_lsb() == portA.get_lsb()) - && (this->get_msb() == portA.get_msb()) ) { +bool BasicPort::operator==(const BasicPort& portA) const { + if ((0 == this->get_name().compare(portA.get_name())) && + (this->get_lsb() == portA.get_lsb()) && + (this->get_msb() == portA.get_msb())) { return true; } return false; } -bool BasicPort::operator< (const BasicPort& portA) const { - if ( (0 == this->get_name().compare(portA.get_name())) - && (this->get_lsb() < portA.get_lsb()) - && (this->get_msb() < portA.get_msb()) ) { +bool BasicPort::operator<(const BasicPort& portA) const { + if ((0 == this->get_name().compare(portA.get_name())) && + (this->get_lsb() < portA.get_lsb()) && + (this->get_msb() < portA.get_msb())) { return true; } return false; } - /************************************************************************ - * Mutators + * Mutators ***********************************************************************/ /* copy */ void BasicPort::set(const BasicPort& basic_port) { name_ = basic_port.get_name(); - lsb_ = basic_port.get_lsb(); - msb_ = basic_port.get_msb(); + lsb_ = basic_port.get_lsb(); + msb_ = basic_port.get_msb(); origin_port_width_ = basic_port.get_origin_port_width(); return; } /* set the port LSB and MSB */ -void BasicPort::set_name(const std::string& name) { +void BasicPort::set_name(const std::string& name) { name_ = name; return; } - + /* set the port LSB and MSB */ void BasicPort::set_width(const size_t& width) { if (0 == width) { make_invalid(); return; - } + } lsb_ = 0; msb_ = width - 1; return; } - + /* set the port LSB and MSB */ void BasicPort::set_width(const size_t& lsb, const size_t& msb) { /* If lsb and msb is invalid, we make a default port */ if (lsb > msb) { make_invalid(); return; - } + } set_lsb(lsb); set_msb(msb); return; } - + void BasicPort::set_lsb(const size_t& lsb) { lsb_ = lsb; return; @@ -198,7 +190,7 @@ void BasicPort::set_origin_port_width(const size_t& origin_port_width) { } /* Increase the port width */ -void BasicPort::expand(const size_t& width) { +void BasicPort::expand(const size_t& width) { if (0 == width) { return; /* ignore zero-width port */ } @@ -218,7 +210,7 @@ void BasicPort::revert() { std::swap(lsb_, msb_); return; } - + /* rotate: increase both lsb and msb by an offset */ bool BasicPort::rotate(const size_t& offset) { /* If offset is 0, we do nothing */ @@ -231,10 +223,10 @@ bool BasicPort::rotate(const size_t& offset) { set_width(offset); return true; } - /* check if leads to overflow: + /* check if leads to overflow: * if limits - msb is larger than offset */ - if ( (std::numeric_limits::max() - msb_ < offset) ) { + if ((std::numeric_limits::max() - msb_ < offset)) { return false; } /* Increase LSB and MSB */ @@ -245,16 +237,16 @@ bool BasicPort::rotate(const size_t& offset) { /* rotate: decrease both lsb and msb by an offset */ bool BasicPort::counter_rotate(const size_t& offset) { - /* If current port is invalid or offset is 0, - * we do nothing + /* If current port is invalid or offset is 0, + * we do nothing */ if ((0 == offset) || (0 == get_width())) { return true; } - /* check if leads to overflow: + /* check if leads to overflow: * if limits is larger than offset */ - if ( (std::numeric_limits::min() + lsb_ < offset) ) { + if ((std::numeric_limits::min() + lsb_ < offset)) { return false; } /* decrease LSB and MSB */ @@ -262,18 +254,18 @@ bool BasicPort::counter_rotate(const size_t& offset) { msb_ -= offset; return true; } - + /* Reset to initial port */ void BasicPort::reset() { make_invalid(); return; -} +} /* Combine two ports */ void BasicPort::combine(const BasicPort& port) { /* LSB follows the current LSB */ /* MSB increases */ - VTR_ASSERT(0 < port.get_width() ); /* Make sure port is valid */ + VTR_ASSERT(0 < port.get_width()); /* Make sure port is valid */ /* If current port is invalid, we do not combine */ if (0 == get_width()) { return; @@ -281,12 +273,12 @@ void BasicPort::combine(const BasicPort& port) { /* Increase MSB */ msb_ += port.get_width(); return; -} +} /* A restricted combine function for two ports, * Following conditions will be applied: * 1. the two ports have the same name - * Note: you must run mergable() function first + * Note: you must run mergable() function first * to make sure this assumption is valid * 2. the new MSB will be the maximum MSB of the two ports * 3. the new LSB will be the minimum LSB of the two ports @@ -320,30 +312,28 @@ void BasicPort::make_invalid() { /* check if port size is valid > 0 */ bool BasicPort::is_valid() const { /* msb should be equal or greater than lsb, if this is a valid port */ - if ( msb_ < lsb_ ) { + if (msb_ < lsb_) { return false; } return true; -} +} /************************************************************************ - * ConfPorts member functions + * ConfPorts member functions ***********************************************************************/ /************************************************************************ - * Constructor + * Constructor ***********************************************************************/ /* Default constructor */ -ConfPorts::ConfPorts() { +ConfPorts::ConfPorts() { /* default port */ reserved_.reset(); regular_.reset(); } /* copy */ -ConfPorts::ConfPorts(const ConfPorts& conf_ports) { - set(conf_ports); -} +ConfPorts::ConfPorts(const ConfPorts& conf_ports) { set(conf_ports); } /************************************************************************ * Accessors @@ -352,32 +342,25 @@ size_t ConfPorts::get_reserved_port_width() const { return reserved_.get_width(); } -size_t ConfPorts::get_reserved_port_lsb() const { - return reserved_.get_lsb(); -} +size_t ConfPorts::get_reserved_port_lsb() const { return reserved_.get_lsb(); } -size_t ConfPorts::get_reserved_port_msb() const { - return reserved_.get_msb(); -} +size_t ConfPorts::get_reserved_port_msb() const { return reserved_.get_msb(); } size_t ConfPorts::get_regular_port_width() const { return regular_.get_width(); } -size_t ConfPorts::get_regular_port_lsb() const { - return regular_.get_lsb(); -} +size_t ConfPorts::get_regular_port_lsb() const { return regular_.get_lsb(); } -size_t ConfPorts::get_regular_port_msb() const { - return regular_.get_msb(); -} +size_t ConfPorts::get_regular_port_msb() const { return regular_.get_msb(); } /************************************************************************ - * Mutators + * Mutators ***********************************************************************/ void ConfPorts::set(const ConfPorts& conf_ports) { set_reserved_port(conf_ports.get_reserved_port_width()); - set_regular_port(conf_ports.get_regular_port_lsb(), conf_ports.get_regular_port_msb()); + set_regular_port(conf_ports.get_regular_port_lsb(), + conf_ports.get_regular_port_msb()); return; } @@ -411,15 +394,15 @@ void ConfPorts::expand_reserved_port(size_t width) { reserved_.expand(width); return; } - + /* Increase the port width of regular port */ -void ConfPorts::expand_regular_port(size_t width) { +void ConfPorts::expand_regular_port(size_t width) { regular_.expand(width); return; } /* Increase the port width of both ports */ -void ConfPorts::expand(size_t width) { +void ConfPorts::expand(size_t width) { expand_reserved_port(width); expand_regular_port(width); } @@ -427,7 +410,7 @@ void ConfPorts::expand(size_t width) { /* rotate */ bool ConfPorts::rotate_regular_port(size_t offset) { return regular_.rotate(offset); -} +} /* counter rotate */ bool ConfPorts::counter_rotate_regular_port(size_t offset) { @@ -439,6 +422,6 @@ void ConfPorts::reset() { reserved_.reset(); regular_.reset(); return; -} +} -} /* namespace openfpga ends */ +} // namespace openfpga diff --git a/libs/libopenfpgautil/src/openfpga_port.h b/libs/libopenfpgautil/src/openfpga_port.h index 3df6d0efa..b2759f273 100644 --- a/libs/libopenfpgautil/src/openfpga_port.h +++ b/libs/libopenfpgautil/src/openfpga_port.h @@ -12,85 +12,95 @@ namespace openfpga { /* A basic port */ class BasicPort { - public: /* Constructors */ - BasicPort(); - BasicPort(const char* name, const size_t& lsb, const size_t& msb); - BasicPort(const char* name, const size_t& width); - BasicPort(const std::string& name, const size_t& lsb, const size_t& msb); - BasicPort(const std::string& name, const size_t& width); - public: /* Overloaded operators */ - bool operator== (const BasicPort& portA) const; - bool operator< (const BasicPort& portA) const; - public: /* Accessors */ - size_t get_width() const; /* get the port width */ - size_t get_msb() const; /* get the LSB */ - size_t get_lsb() const; /* get the LSB */ - std::string get_name() const; /* get the name */ - bool is_valid() const; /* check if port size is valid > 0 */ - std::vector pins() const; /* Make a range of the pin indices */ - bool mergeable(const BasicPort& portA) const; /* Check if a port can be merged with this port */ - bool contained(const BasicPort& portA) const; /* Check if a port is contained by this port */ - size_t get_origin_port_width() const; - public: /* Mutators */ - void set(const BasicPort& basic_port); /* copy */ - void set_name(const std::string& name); /* set the port LSB and MSB */ - void set_width(const size_t& width); /* set the port LSB and MSB */ - void set_width(const size_t& lsb, const size_t& msb); /* set the port LSB and MSB */ - void set_lsb(const size_t& lsb); - void set_msb(const size_t& msb); - void expand(const size_t& width); /* Increase the port width */ - void revert(); /* Swap lsb and msb */ - bool rotate(const size_t& offset); /* rotate */ - bool counter_rotate(const size_t& offset); /* counter rotate */ - void reset(); /* Reset to initial port */ - void combine(const BasicPort& port); /* Combine two ports */ - void merge(const BasicPort& portA); - void set_origin_port_width(const size_t& origin_port_width); - private: /* internal functions */ - void make_invalid(); /* Make a port invalid */ - private: /* Internal Data */ - std::string name_; /* Name of this port */ - size_t msb_; /* Most Significant Bit of this port */ - size_t lsb_; /* Least Significant Bit of this port */ - size_t origin_port_width_; /* Original port width of a port, used by traceback port conversion history */ + public: /* Constructors */ + BasicPort(); + BasicPort(const char* name, const size_t& lsb, const size_t& msb); + BasicPort(const char* name, const size_t& width); + BasicPort(const std::string& name, const size_t& lsb, const size_t& msb); + BasicPort(const std::string& name, const size_t& width); + + public: /* Overloaded operators */ + bool operator==(const BasicPort& portA) const; + bool operator<(const BasicPort& portA) const; + + public: /* Accessors */ + size_t get_width() const; /* get the port width */ + size_t get_msb() const; /* get the LSB */ + size_t get_lsb() const; /* get the LSB */ + std::string get_name() const; /* get the name */ + bool is_valid() const; /* check if port size is valid > 0 */ + std::vector pins() const; /* Make a range of the pin indices */ + bool mergeable(const BasicPort& portA) + const; /* Check if a port can be merged with this port */ + bool contained(const BasicPort& portA) + const; /* Check if a port is contained by this port */ + size_t get_origin_port_width() const; + + public: /* Mutators */ + void set(const BasicPort& basic_port); /* copy */ + void set_name(const std::string& name); /* set the port LSB and MSB */ + void set_width(const size_t& width); /* set the port LSB and MSB */ + void set_width(const size_t& lsb, + const size_t& msb); /* set the port LSB and MSB */ + void set_lsb(const size_t& lsb); + void set_msb(const size_t& msb); + void expand(const size_t& width); /* Increase the port width */ + void revert(); /* Swap lsb and msb */ + bool rotate(const size_t& offset); /* rotate */ + bool counter_rotate(const size_t& offset); /* counter rotate */ + void reset(); /* Reset to initial port */ + void combine(const BasicPort& port); /* Combine two ports */ + void merge(const BasicPort& portA); + void set_origin_port_width(const size_t& origin_port_width); + + private: /* internal functions */ + void make_invalid(); /* Make a port invalid */ + private: /* Internal Data */ + std::string name_; /* Name of this port */ + size_t msb_; /* Most Significant Bit of this port */ + size_t lsb_; /* Least Significant Bit of this port */ + size_t origin_port_width_; /* Original port width of a port, used by traceback + port conversion history */ }; /* Configuration ports: * 1. reserved configuration port, which is used by RRAM FPGA architecture - * 2. regular configuration port, which is used by any FPGA architecture + * 2. regular configuration port, which is used by any FPGA architecture */ class ConfPorts { - public: /* Constructors */ - ConfPorts(); /* default port */ - ConfPorts(const ConfPorts& conf_ports); /* copy */ - public: /* Accessors */ - size_t get_reserved_port_width() const; - size_t get_reserved_port_lsb() const; - size_t get_reserved_port_msb() const; - size_t get_regular_port_width() const; - size_t get_regular_port_lsb() const; - size_t get_regular_port_msb() const; - public: /* Mutators */ - void set(const ConfPorts& conf_ports); - void set_reserved_port(size_t width); - void set_regular_port(size_t width); - void set_regular_port(size_t lsb, size_t msb); - void set_regular_port_lsb(size_t lsb); - void set_regular_port_msb(size_t msb); - void expand_reserved_port(size_t width); /* Increase the port width of reserved port */ - void expand_regular_port(size_t width); /* Increase the port width of regular port */ - void expand(size_t width); /* Increase the port width of both ports */ - bool rotate_regular_port(size_t offset); /* rotate */ - bool counter_rotate_regular_port(size_t offset); /* counter rotate */ - void reset(); /* Reset to initial port */ - private: /* Internal Data */ - BasicPort reserved_; - BasicPort regular_; + public: /* Constructors */ + ConfPorts(); /* default port */ + ConfPorts(const ConfPorts& conf_ports); /* copy */ + public: /* Accessors */ + size_t get_reserved_port_width() const; + size_t get_reserved_port_lsb() const; + size_t get_reserved_port_msb() const; + size_t get_regular_port_width() const; + size_t get_regular_port_lsb() const; + size_t get_regular_port_msb() const; + + public: /* Mutators */ + void set(const ConfPorts& conf_ports); + void set_reserved_port(size_t width); + void set_regular_port(size_t width); + void set_regular_port(size_t lsb, size_t msb); + void set_regular_port_lsb(size_t lsb); + void set_regular_port_msb(size_t msb); + void expand_reserved_port( + size_t width); /* Increase the port width of reserved port */ + void expand_regular_port( + size_t width); /* Increase the port width of regular port */ + void expand(size_t width); /* Increase the port width of both ports */ + bool rotate_regular_port(size_t offset); /* rotate */ + bool counter_rotate_regular_port(size_t offset); /* counter rotate */ + void reset(); /* Reset to initial port */ + private: /* Internal Data */ + BasicPort reserved_; + BasicPort regular_; }; /* TODO: create a class for BL and WL ports */ -} /* namespace openfpga ends */ +} // namespace openfpga #endif - diff --git a/libs/libopenfpgautil/src/openfpga_port_parser.cpp b/libs/libopenfpgautil/src/openfpga_port_parser.cpp index 2006275dc..93b7e0899 100644 --- a/libs/libopenfpgautil/src/openfpga_port_parser.cpp +++ b/libs/libopenfpgautil/src/openfpga_port_parser.cpp @@ -1,26 +1,25 @@ /************************************************************************ * Member functions for Port parsers ***********************************************************************/ +#include "openfpga_port_parser.h" + #include +#include "openfpga_tokenizer.h" #include "vtr_assert.h" #include "vtr_geometry.h" -#include "openfpga_tokenizer.h" - -#include "openfpga_port_parser.h" - /* namespace openfpga begins */ namespace openfpga { /************************************************************************ - * Member functions for PortParser class + * Member functions for PortParser class ***********************************************************************/ /************************************************************************ * Constructors ***********************************************************************/ -PortParser::PortParser (const std::string& data) { +PortParser::PortParser(const std::string& data) { set_default_bracket(); set_default_delim(); set_data(data); @@ -30,13 +29,9 @@ PortParser::PortParser (const std::string& data) { * Public Accessors ***********************************************************************/ /* Get the data string */ -std::string PortParser::data() const { - return data_; -} +std::string PortParser::data() const { return data_; } -BasicPort PortParser::port() const { - return port_; -} +BasicPort PortParser::port() const { return port_; } /************************************************************************ * Public Mutators @@ -58,13 +53,13 @@ void PortParser::parse() { /* Split the data into and */ std::vector port_tokens = tokenizer.split(bracket_.x()); /* Make sure we have a port name! */ - VTR_ASSERT_SAFE ((1 == port_tokens.size()) || (2 == port_tokens.size())); + VTR_ASSERT_SAFE((1 == port_tokens.size()) || (2 == port_tokens.size())); /* Store the port name! */ port_.set_name(port_tokens[0]); /* If we only have one token */ if (1 == port_tokens.size()) { - port_.set_width(1); + port_.set_width(1); return; /* We can finish here */ } @@ -72,28 +67,28 @@ void PortParser::parse() { tokenizer.set_data(port_tokens[1]); std::vector pin_tokens = tokenizer.split(bracket_.y()); /* Make sure we have a valid string! */ - VTR_ASSERT_SAFE (1 == port_tokens.size()); + VTR_ASSERT_SAFE(1 == port_tokens.size()); /* Split the pin string now */ tokenizer.set_data(pin_tokens[0]); pin_tokens = tokenizer.split(delim_); /* Check if we have LSB and MSB or just one */ - if ( 1 == pin_tokens.size() ) { + if (1 == pin_tokens.size()) { /* Single pin */ - port_.set_width(std::stoi(pin_tokens[0]), std::stoi(pin_tokens[0])); - } else if ( 2 == pin_tokens.size() ) { - /* A number of pins. - * Note that we always use the LSB for token[0] and MSB for token[1] + port_.set_width(std::stoi(pin_tokens[0]), std::stoi(pin_tokens[0])); + } else if (2 == pin_tokens.size()) { + /* A number of pins. + * Note that we always use the LSB for token[0] and MSB for token[1] */ if (std::stoi(pin_tokens[1]) < std::stoi(pin_tokens[0])) { - port_.set_width(std::stoi(pin_tokens[1]), std::stoi(pin_tokens[0])); + port_.set_width(std::stoi(pin_tokens[1]), std::stoi(pin_tokens[0])); } else { - port_.set_width(std::stoi(pin_tokens[0]), std::stoi(pin_tokens[1])); + port_.set_width(std::stoi(pin_tokens[0]), std::stoi(pin_tokens[1])); } } - return; + return; } void PortParser::set_default_bracket() { @@ -108,13 +103,13 @@ void PortParser::set_default_delim() { } /************************************************************************ - * Member functions for MultiPortParser class + * Member functions for MultiPortParser class ***********************************************************************/ /************************************************************************ * Constructors ***********************************************************************/ -MultiPortParser::MultiPortParser (const std::string& data) { +MultiPortParser::MultiPortParser(const std::string& data) { set_default_delim(); set_data(data); } @@ -123,13 +118,9 @@ MultiPortParser::MultiPortParser (const std::string& data) { * Public Accessors ***********************************************************************/ /* Get the data string */ -std::string MultiPortParser::data() const { - return data_; -} +std::string MultiPortParser::data() const { return data_; } -std::vector MultiPortParser::ports() const { - return ports_; -} +std::vector MultiPortParser::ports() const { return ports_; } /************************************************************************ * Public Mutators @@ -153,7 +144,7 @@ void MultiPortParser::parse() { /* Split the data into and */ std::vector port_tokens = tokenizer.split(delim_); - + /* Use PortParser for each token */ for (const auto& port : port_tokens) { PortParser port_parser(port); @@ -175,13 +166,13 @@ void MultiPortParser::clear() { } /************************************************************************ - * Member functions for PortDelayParser class + * Member functions for PortDelayParser class ***********************************************************************/ /************************************************************************ * Constructors ***********************************************************************/ -PortDelayParser::PortDelayParser (const std::string& data) { +PortDelayParser::PortDelayParser(const std::string& data) { set_default_element_delim(); set_default_line_delim(); set_data(data); @@ -191,18 +182,12 @@ PortDelayParser::PortDelayParser (const std::string& data) { * Public Accessors ***********************************************************************/ /* Get the data string */ -std::string PortDelayParser::data() const { - return data_; -} +std::string PortDelayParser::data() const { return data_; } /* Get the size of delay matrix [height, width]*/ -size_t PortDelayParser::height() const { - return delay_matrix_.dim_size(0); -} +size_t PortDelayParser::height() const { return delay_matrix_.dim_size(0); } -size_t PortDelayParser::width() const { - return delay_matrix_.dim_size(1); -} +size_t PortDelayParser::width() const { return delay_matrix_.dim_size(1); } vtr::Point PortDelayParser::delay_size() const { vtr::Point matrix_size(height(), width()); @@ -211,7 +196,7 @@ vtr::Point PortDelayParser::delay_size() const { float PortDelayParser::delay(size_t x, size_t y) const { /* Make sure x and y are in range */ - VTR_ASSERT_SAFE( (x < width()) && (y < height()) ); + VTR_ASSERT_SAFE((x < width()) && (y < height())); return delay_matrix_[x][y]; } @@ -234,7 +219,8 @@ void PortDelayParser::parse() { /* Create a tokenizer */ StringToken delay_tokenizer(data_); - /* Ensure a clean start! Trim whitespace at the beginning and end of the string */ + /* Ensure a clean start! Trim whitespace at the beginning and end of the + * string */ delay_tokenizer.trim(); /* Split the data into different lines */ @@ -248,7 +234,8 @@ void PortDelayParser::parse() { for (const auto& line : delay_lines) { /* Create a tokenizer for each line */ StringToken line_tokenizer(line); - std::vector delay_elements = line_tokenizer.split(element_delim_); + std::vector delay_elements = + line_tokenizer.split(element_delim_); /* Get maximum number of length, which is the width of delay matrix */ matrix_width = std::max(matrix_width, delay_elements.size()); } @@ -260,10 +247,12 @@ void PortDelayParser::parse() { for (const auto& line : delay_lines) { /* Create a tokenizer for each line */ StringToken line_tokenizer(line); - std::vector delay_elements = line_tokenizer.split(element_delim_); + std::vector delay_elements = + line_tokenizer.split(element_delim_); /* Get maximum number of length, which is the width of delay matrix */ for (const auto& element : delay_elements) { - delay_matrix_[size_t(&line - &delay_lines[0])][size_t(&element - &delay_elements[0])] = stof(element); + delay_matrix_[size_t(&line - &delay_lines[0])] + [size_t(&element - &delay_elements[0])] = stof(element); } } @@ -291,4 +280,4 @@ void PortDelayParser::clear() { return; } -} /* namespace openfpga ends */ +} // namespace openfpga diff --git a/libs/libopenfpgautil/src/openfpga_port_parser.h b/libs/libopenfpgautil/src/openfpga_port_parser.h index dfa4ca466..f596fd309 100644 --- a/libs/libopenfpgautil/src/openfpga_port_parser.h +++ b/libs/libopenfpgautil/src/openfpga_port_parser.h @@ -7,11 +7,10 @@ #include #include -#include "vtr_ndmatrix.h" -#include "vtr_geometry.h" - #include "openfpga_port.h" #include "openfpga_tokenizer.h" +#include "vtr_geometry.h" +#include "vtr_ndmatrix.h" /************************************************************************ * This file includes parsers for port definition in the architecture XML @@ -28,77 +27,88 @@ namespace openfpga { * 1. [:] * 2. [:] * 3. [] - * 4. [] - * 5. + * 4. [] + * 5. * In case 4 and 5, we will assign (-1,-1) for LSB and MSB ***********************************************************************/ -class PortParser{ - public : /* Constructors*/ - PortParser (const std::string& data); - public : /* Public Accessors */ - std::string data() const; - BasicPort port() const; - public : /* Public Mutators */ - void set_data(const std::string& data); - private : /* Private Mutators */ - void parse(); - void set_default_bracket(); - void set_default_delim(); - private: /* Internal data */ - std::string data_; /* Lines to be splited */ - vtr::Point bracket_; - char delim_; - BasicPort port_; +class PortParser { + public: /* Constructors*/ + PortParser(const std::string& data); + + public: /* Public Accessors */ + std::string data() const; + BasicPort port() const; + + public: /* Public Mutators */ + void set_data(const std::string& data); + + private: /* Private Mutators */ + void parse(); + void set_default_bracket(); + void set_default_delim(); + + private: /* Internal data */ + std::string data_; /* Lines to be splited */ + vtr::Point bracket_; + char delim_; + BasicPort port_; }; /************************************************************************ - * MultiPortParser: a parser for multiple ports in one line + * MultiPortParser: a parser for multiple ports in one line ***********************************************************************/ class MultiPortParser { - public : /* Constructors*/ - MultiPortParser (const std::string& data); - public : /* Public Accessors */ - std::string data() const; - std::vector ports() const; - public : /* Public Mutators */ - void set_data(const std::string& data); - private : /* Private Mutators */ - void parse(); - void set_default_delim(); - void clear(); - private: /* Internal data */ - std::string data_; /* Lines to be splited */ - char delim_; - std::vector ports_; + public: /* Constructors*/ + MultiPortParser(const std::string& data); + + public: /* Public Accessors */ + std::string data() const; + std::vector ports() const; + + public: /* Public Mutators */ + void set_data(const std::string& data); + + private: /* Private Mutators */ + void parse(); + void set_default_delim(); + void clear(); + + private: /* Internal data */ + std::string data_; /* Lines to be splited */ + char delim_; + std::vector ports_; }; /************************************************************************ * PortDelayParser: a parser for 2D delay matrix ***********************************************************************/ class PortDelayParser { - public : /* Constructors*/ - PortDelayParser (const std::string& data); - public : /* Public Accessors */ - std::string data() const; - size_t height() const; - size_t width() const; - vtr::Point delay_size() const; - float delay(size_t x, size_t y) const; - public : /* Public Mutators */ - void set_data(const std::string& data); - private : /* Private Mutators */ - void parse(); - void set_default_element_delim(); - void set_default_line_delim(); - void clear(); - private: /* Internal data */ - std::string data_; /* Lines to be splited */ - std::vector element_delim_; - std::vector line_delim_; - vtr::Matrix delay_matrix_; + public: /* Constructors*/ + PortDelayParser(const std::string& data); + + public: /* Public Accessors */ + std::string data() const; + size_t height() const; + size_t width() const; + vtr::Point delay_size() const; + float delay(size_t x, size_t y) const; + + public: /* Public Mutators */ + void set_data(const std::string& data); + + private: /* Private Mutators */ + void parse(); + void set_default_element_delim(); + void set_default_line_delim(); + void clear(); + + private: /* Internal data */ + std::string data_; /* Lines to be splited */ + std::vector element_delim_; + std::vector line_delim_; + vtr::Matrix delay_matrix_; }; -} /* namespace openfpga ends */ +} // namespace openfpga #endif - diff --git a/libs/libopenfpgautil/src/openfpga_reserved_words.h b/libs/libopenfpgautil/src/openfpga_reserved_words.h index 255c7ae5d..05d1e2d2e 100644 --- a/libs/libopenfpgautil/src/openfpga_reserved_words.h +++ b/libs/libopenfpgautil/src/openfpga_reserved_words.h @@ -31,13 +31,13 @@ constexpr const char* WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME = "wl_sr_wlr_out"; constexpr const char* GIO_INOUT_PREFIX = "gfpga_pad_"; /* Grid naming constant strings */ -constexpr const char* GRID_MODULE_NAME_PREFIX = "grid_"; -constexpr const char* LOGICAL_MODULE_NAME_PREFIX = "logical_tile_"; +constexpr const char* GRID_MODULE_NAME_PREFIX = "grid_"; +constexpr const char* LOGICAL_MODULE_NAME_PREFIX = "logical_tile_"; /* Memory naming constant strings */ -constexpr const char* GRID_MEM_INSTANCE_PREFIX = "mem_"; -constexpr const char* SWITCH_BLOCK_MEM_INSTANCE_PREFIX = "mem_"; -constexpr const char* CONNECTION_BLOCK_MEM_INSTANCE_PREFIX = "mem_"; +constexpr const char* GRID_MEM_INSTANCE_PREFIX = "mem_"; +constexpr const char* SWITCH_BLOCK_MEM_INSTANCE_PREFIX = "mem_"; +constexpr const char* CONNECTION_BLOCK_MEM_INSTANCE_PREFIX = "mem_"; constexpr const char* MEMORY_MODULE_POSTFIX = "_mem"; constexpr const char* MEMORY_BL_PORT_NAME = "bl"; constexpr const char* MEMORY_WL_PORT_NAME = "wl"; @@ -45,9 +45,9 @@ constexpr const char* MEMORY_WLR_PORT_NAME = "wlr"; /* Multiplexer naming constant strings */ constexpr const char* MUX_BASIS_MODULE_POSTFIX = "_basis"; -constexpr const char* GRID_MUX_INSTANCE_PREFIX = "mux_"; -constexpr const char* SWITCH_BLOCK_MUX_INSTANCE_PREFIX = "mux_"; -constexpr const char* CONNECTION_BLOCK_MUX_INSTANCE_PREFIX = "mux_"; +constexpr const char* GRID_MUX_INSTANCE_PREFIX = "mux_"; +constexpr const char* SWITCH_BLOCK_MUX_INSTANCE_PREFIX = "mux_"; +constexpr const char* CONNECTION_BLOCK_MUX_INSTANCE_PREFIX = "mux_"; /* Decoder naming constant strings */ constexpr const char* DECODER_ENABLE_PORT_NAME = "enable"; diff --git a/libs/libopenfpgautil/src/openfpga_scale.cpp b/libs/libopenfpgautil/src/openfpga_scale.cpp index 222d1c41b..7d9c1b75d 100644 --- a/libs/libopenfpgautil/src/openfpga_scale.cpp +++ b/libs/libopenfpgautil/src/openfpga_scale.cpp @@ -9,26 +9,23 @@ #include "vtr_log.h" /* Headers from openfpgautil library */ -#include "openfpga_scale.h" +#include "openfpga_scale.h" namespace openfpga { -/* A small ratio for float number comparison - * If the float number B is in the range of the referance A +/- epsilon +/* A small ratio for float number comparison + * If the float number B is in the range of the referance A +/- epsilon * we regard A == B - * A - A * EPSILON <= B <= A + A * EPSILON + * A - A * EPSILON <= B <= A + A * EPSILON */ #define EPSILON_RATIO 1e-3 -bool same_float_number(const float& a, - const float& b, - const float& epsilon) { +bool same_float_number(const float& a, const float& b, const float& epsilon) { /* Always use a positive epsilon */ - if ( (a - a * std::abs(epsilon) <= b) - && (b <= a + a * std::abs(epsilon)) ) { + if ((a - a * std::abs(epsilon) <= b) && (b <= a + a * std::abs(epsilon))) { return true; } - + return false; } @@ -38,18 +35,18 @@ bool same_float_number(const float& a, * - 1e9 -> B * - 1e6 -> M * - 1e3 -> k - * - 1. -> + * - 1. -> * - 1e-3 -> m - * - 1e-6 -> u + * - 1e-6 -> u * - 1e-9 -> n * - 1e-12 -> p - * - 1e-15 -> f - * - 1e-18 -> a + * - 1e-15 -> f + * - 1e-18 -> a *******************************************************************/ std::string unit_to_string(const float& unit) { if (true == same_float_number(unit, 1., EPSILON_RATIO)) { return std::string(); - /* Larger than 1 unit */ + /* Larger than 1 unit */ } else if (true == same_float_number(unit, 1e3, EPSILON_RATIO)) { return std::string("k"); } else if (true == same_float_number(unit, 1e6, EPSILON_RATIO)) { @@ -58,7 +55,7 @@ std::string unit_to_string(const float& unit) { return std::string("B"); } else if (true == same_float_number(unit, 1e12, EPSILON_RATIO)) { return std::string("T"); - /* Less than 1 unit */ + /* Less than 1 unit */ } else if (true == same_float_number(unit, 1e-3, EPSILON_RATIO)) { return std::string("m"); } else if (true == same_float_number(unit, 1e-6, EPSILON_RATIO)) { @@ -75,8 +72,9 @@ std::string unit_to_string(const float& unit) { /* Invalid unit report error */ VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid unit %g!\nAcceptable units are [1e12|1e9|1e6|1e3|1|1e-3|1e-6|1e-9|1e-12|1e-15|1e-18]\n", - unit); + "Invalid unit %g!\nAcceptable units are " + "[1e12|1e9|1e6|1e3|1|1e-3|1e-6|1e-9|1e-12|1e-15|1e-18]\n", + unit); exit(1); } @@ -88,8 +86,9 @@ std::string time_unit_to_string(const float& unit, const std::string& postfix) { /* For larger than 1 unit, we do not accept */ if (1e6 < unit) { VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid time unit %g!\nAcceptable units are [1e6|1e3|1|1e-3|1e-6|1e-9|1e-12|1e-15|1e-18]\n", - unit); + "Invalid time unit %g!\nAcceptable units are " + "[1e6|1e3|1|1e-3|1e-6|1e-9|1e-12|1e-15|1e-18]\n", + unit); exit(1); } @@ -99,12 +98,12 @@ std::string time_unit_to_string(const float& unit, const std::string& postfix) { /******************************************************************** * Convert string unit to numeric: * - T -> 1e12 - * - B -> 1e9 + * - B -> 1e9 * - M -> 1e6 * - k -> 1e3 - * - "" -> 1. + * - "" -> 1. * - m -> 1e-3 - * - u -> 1e-6 + * - u -> 1e-6 * - n -> 1e-9 * - p -> 1e-12 * - f -> 1e-15 @@ -113,7 +112,7 @@ std::string time_unit_to_string(const float& unit, const std::string& postfix) { float string_to_unit(const std::string& scale) { if (true == scale.empty()) { return 1.; - /* Larger than 1 unit */ + /* Larger than 1 unit */ } else if (std::string("T") == scale) { return 1e12; } else if (std::string("B") == scale) { @@ -122,7 +121,7 @@ float string_to_unit(const std::string& scale) { return 1e6; } else if (std::string("k") == scale) { return 1e3; - /* Less than 1 unit */ + /* Less than 1 unit */ } else if (std::string("m") == scale) { return 1e-3; } else if (std::string("u") == scale) { @@ -138,9 +137,10 @@ float string_to_unit(const std::string& scale) { } /* Invalid unit report error */ - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid unit %s!\nAcceptable units are [a|f|p|n|u|k|M|B|T] or empty\n", - scale.c_str()); + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Invalid unit %s!\nAcceptable units are [a|f|p|n|u|k|M|B|T] or empty\n", + scale.c_str()); exit(1); } @@ -149,22 +149,20 @@ float string_to_unit(const std::string& scale) { * e.g. ps -> 1e-12 *******************************************************************/ float string_to_time_unit(const std::string& scale) { - if ( (1 != scale.length()) - && (2 != scale.length()) ) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Time unit (='%s') must contain only one or two characters!\n", - scale.c_str()); - } + if ((1 != scale.length()) && (2 != scale.length())) { + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Time unit (='%s') must contain only one or two characters!\n", + scale.c_str()); + } /* The last character must be 's' */ if ('s' != scale.back()) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Time unit (='%s') must end with 's'!\n", + VTR_LOGF_ERROR(__FILE__, __LINE__, "Time unit (='%s') must end with 's'!\n", scale.c_str()); } float unit = 1.; - VTR_ASSERT ( (1 == scale.length()) - || (2 == scale.length()) ); + VTR_ASSERT((1 == scale.length()) || (2 == scale.length())); if (2 == scale.length()) { unit = string_to_unit(scale.substr(0, 1)); } @@ -172,12 +170,13 @@ float string_to_time_unit(const std::string& scale) { /* For larger than 1 unit, we do not accept */ if (1e6 < unit) { VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid time unit %g!\nAcceptable units are [1e6|1e3|1|1e-3|1e-6|1e-9|1e-12|1e-15|1e-18]\n", - unit); + "Invalid time unit %g!\nAcceptable units are " + "[1e6|1e3|1|1e-3|1e-6|1e-9|1e-12|1e-15|1e-18]\n", + unit); exit(1); } return unit; } -} /* namespace openfpga ends */ +} // namespace openfpga diff --git a/libs/libopenfpgautil/src/openfpga_scale.h b/libs/libopenfpgautil/src/openfpga_scale.h index f10abcca6..2fb46fc90 100644 --- a/libs/libopenfpgautil/src/openfpga_scale.h +++ b/libs/libopenfpgautil/src/openfpga_scale.h @@ -12,18 +12,17 @@ /* namespace openfpga begins */ namespace openfpga { -bool same_float_number(const float& a, - const float& b, - const float& epsilon); +bool same_float_number(const float& a, const float& b, const float& epsilon); std::string unit_to_string(const float& unit); -std::string time_unit_to_string(const float& unit, const std::string& postfix = "s"); +std::string time_unit_to_string(const float& unit, + const std::string& postfix = "s"); float string_to_unit(const std::string& scale); -float string_to_time_unit(const std::string& scale); +float string_to_time_unit(const std::string& scale); -} /* namespace openfpga ends */ +} // namespace openfpga #endif diff --git a/libs/libopenfpgautil/src/openfpga_side_manager.cpp b/libs/libopenfpgautil/src/openfpga_side_manager.cpp index 00ff9912c..4540984c8 100644 --- a/libs/libopenfpgautil/src/openfpga_side_manager.cpp +++ b/libs/libopenfpgautil/src/openfpga_side_manager.cpp @@ -7,67 +7,59 @@ namespace openfpga { /* Constructors */ -SideManager::SideManager(enum e_side side) { - side_ = side; -} +SideManager::SideManager(enum e_side side) { side_ = side; } -SideManager::SideManager() { - side_ = NUM_SIDES; -} +SideManager::SideManager() { side_ = NUM_SIDES; } -SideManager::SideManager(size_t side) { - set_side(side); -} +SideManager::SideManager(size_t side) { set_side(side); } /* Public Accessors */ -enum e_side SideManager::get_side() const { - return side_; -} +enum e_side SideManager::get_side() const { return side_; } enum e_side SideManager::get_opposite() const { switch (side_) { - case TOP: - return BOTTOM; - case RIGHT: - return LEFT; - case BOTTOM: - return TOP; - case LEFT: - return RIGHT; - default: - return NUM_SIDES; + case TOP: + return BOTTOM; + case RIGHT: + return LEFT; + case BOTTOM: + return TOP; + case LEFT: + return RIGHT; + default: + return NUM_SIDES; } } enum e_side SideManager::get_rotate_clockwise() const { switch (side_) { - case TOP: - return RIGHT; - case RIGHT: - return BOTTOM; - case BOTTOM: - return LEFT; - case LEFT: - return TOP; - default: - return NUM_SIDES; + case TOP: + return RIGHT; + case RIGHT: + return BOTTOM; + case BOTTOM: + return LEFT; + case LEFT: + return TOP; + default: + return NUM_SIDES; } -} +} enum e_side SideManager::get_rotate_counterclockwise() const { switch (side_) { - case TOP: - return LEFT; - case RIGHT: - return TOP; - case BOTTOM: - return RIGHT; - case LEFT: - return BOTTOM; - default: - return NUM_SIDES; + case TOP: + return LEFT; + case RIGHT: + return TOP; + case BOTTOM: + return RIGHT; + case LEFT: + return BOTTOM; + default: + return NUM_SIDES; } -} +} bool SideManager::validate() const { if (NUM_SIDES == side_) { @@ -78,98 +70,98 @@ bool SideManager::validate() const { size_t SideManager::to_size_t() const { switch (side_) { - case TOP: - return 0; - case RIGHT: - return 1; - case BOTTOM: - return 2; - case LEFT: - return 3; - default: - return 4; + case TOP: + return 0; + case RIGHT: + return 1; + case BOTTOM: + return 2; + case LEFT: + return 3; + default: + return 4; } } /* Convert to char* */ -const char* SideManager::c_str() const { +const char* SideManager::c_str() const { switch (side_) { - case TOP: - return "top"; - case RIGHT: - return "right"; - case BOTTOM: - return "bottom"; - case LEFT: - return "left"; - default: - return "invalid_side"; + case TOP: + return "top"; + case RIGHT: + return "right"; + case BOTTOM: + return "bottom"; + case LEFT: + return "left"; + default: + return "invalid_side"; } -} +} /* Convert to char* */ -std::string SideManager::to_string() const { +std::string SideManager::to_string() const { std::string ret; switch (side_) { - case TOP: - ret.assign("top"); - break; - case RIGHT: - ret.assign("right"); - break; - case BOTTOM: - ret.assign("bottom"); - break; - case LEFT: - ret.assign("left"); - break; - default: - ret.assign("invalid_side"); - break; + case TOP: + ret.assign("top"); + break; + case RIGHT: + ret.assign("right"); + break; + case BOTTOM: + ret.assign("bottom"); + break; + case LEFT: + ret.assign("left"); + break; + default: + ret.assign("invalid_side"); + break; } return ret; -} +} /* Public Mutators */ -void SideManager::set_side(size_t side) { +void SideManager::set_side(size_t side) { switch (side) { - case 0: - side_ = TOP; - return; - case 1: - side_ = RIGHT; - return; - case 2: - side_ = BOTTOM; - return; - case 3: - side_ = LEFT; - return; - default: - side_ = NUM_SIDES; - return; + case 0: + side_ = TOP; + return; + case 1: + side_ = RIGHT; + return; + case 2: + side_ = BOTTOM; + return; + case 3: + side_ = LEFT; + return; + default: + side_ = NUM_SIDES; + return; } } -void SideManager::set_side(enum e_side side) { - side_ = side; +void SideManager::set_side(enum e_side side) { + side_ = side; return; } -void SideManager::set_opposite() { - side_ = get_opposite(); +void SideManager::set_opposite() { + side_ = get_opposite(); return; } - + void SideManager::rotate_clockwise() { - side_ = get_rotate_clockwise(); + side_ = get_rotate_clockwise(); return; -} +} void SideManager::rotate_counterclockwise() { - side_ = get_rotate_counterclockwise(); + side_ = get_rotate_counterclockwise(); return; -} +} -} /* namespace openfpga ends */ +} // namespace openfpga diff --git a/libs/libopenfpgautil/src/openfpga_side_manager.h b/libs/libopenfpgautil/src/openfpga_side_manager.h index 4903f7b4b..3edf9aa4a 100644 --- a/libs/libopenfpgautil/src/openfpga_side_manager.h +++ b/libs/libopenfpgautil/src/openfpga_side_manager.h @@ -16,34 +16,37 @@ namespace openfpga { /******************************************************************** * Define a class for the sides of a physical block in FPGA architecture * Basically, each block has four sides : - * TOP, RIGHT, BOTTOM, LEFT - * This class aims to provide a easy proctol for manipulating a side + * TOP, RIGHT, BOTTOM, LEFT + * This class aims to provide a easy proctol for manipulating a side ********************************************************************/ class SideManager { - public: /* Constructor */ - SideManager(enum e_side side); - SideManager(); - SideManager(size_t side); - public: /* Accessors */ - enum e_side get_side() const; - enum e_side get_opposite() const; - enum e_side get_rotate_clockwise() const; - enum e_side get_rotate_counterclockwise() const; - bool validate() const; - size_t to_size_t() const; - const char* c_str() const; - std::string to_string() const; - public: /* Mutators */ - void set_side(size_t side); - void set_side(enum e_side side); - void set_opposite(); - void rotate_clockwise(); - void rotate_counterclockwise(); - private: /* internal data */ - enum e_side side_; + public: /* Constructor */ + SideManager(enum e_side side); + SideManager(); + SideManager(size_t side); + + public: /* Accessors */ + enum e_side get_side() const; + enum e_side get_opposite() const; + enum e_side get_rotate_clockwise() const; + enum e_side get_rotate_counterclockwise() const; + bool validate() const; + size_t to_size_t() const; + const char* c_str() const; + std::string to_string() const; + + public: /* Mutators */ + void set_side(size_t side); + void set_side(enum e_side side); + void set_opposite(); + void rotate_clockwise(); + void rotate_counterclockwise(); + + private: /* internal data */ + enum e_side side_; }; -} /* namespace openfpga ends */ +} // namespace openfpga #endif diff --git a/libs/libopenfpgautil/src/openfpga_tokenizer.cpp b/libs/libopenfpgautil/src/openfpga_tokenizer.cpp index 6ce121ee0..21e4449a5 100644 --- a/libs/libopenfpgautil/src/openfpga_tokenizer.cpp +++ b/libs/libopenfpgautil/src/openfpga_tokenizer.cpp @@ -1,12 +1,11 @@ /************************************************************************ - * Member functions for StringToken class + * Member functions for StringToken class ***********************************************************************/ #include /* Headers from vtrutil library */ -#include "vtr_assert.h" - #include "openfpga_tokenizer.h" +#include "vtr_assert.h" /* namespace openfpga begins */ namespace openfpga { @@ -14,17 +13,13 @@ namespace openfpga { /************************************************************************ * Constructors ***********************************************************************/ -StringToken::StringToken (const std::string& data) { - set_data(data); -} +StringToken::StringToken(const std::string& data) { set_data(data); } /************************************************************************ * Public Accessors ***********************************************************************/ /* Get the data string */ -std::string StringToken::data() const { - return data_; -} +std::string StringToken::data() const { return data_; } /* Split the string using a given delim */ std::vector StringToken::split(const std::string& delims) const { @@ -68,7 +63,8 @@ std::vector StringToken::split(const char* delim) const { } /* Split the string using a given delim */ -std::vector StringToken::split(const std::vector& delims) const { +std::vector StringToken::split( + const std::vector& delims) const { /* Create delims */ std::string delims_str; for (const auto& delim : delims) { @@ -78,10 +74,9 @@ std::vector StringToken::split(const std::vector& delims) con return split(delims_str); } - /* Split the string */ std::vector StringToken::split() { - /* Add a default delim */ + /* Add a default delim */ if (true == delims_.empty()) { add_default_delim(); } @@ -103,9 +98,7 @@ void StringToken::set_data(const std::string& data) { } /* Add a delima to the list */ -void StringToken::add_delim(const char& delim) { - delims_.push_back(delim); -} +void StringToken::add_delim(const char& delim) { delims_.push_back(delim); } /* Remove the string repeated at the beginning of string */ void StringToken::ltrim(const std::string& sensitive_word) { @@ -136,4 +129,4 @@ void StringToken::add_default_delim() { return; } -} /* namespace openfpga ends */ +} // namespace openfpga diff --git a/libs/libopenfpgautil/src/openfpga_tokenizer.h b/libs/libopenfpgautil/src/openfpga_tokenizer.h index d57403d55..af803c7d6 100644 --- a/libs/libopenfpgautil/src/openfpga_tokenizer.h +++ b/libs/libopenfpgautil/src/openfpga_tokenizer.h @@ -17,28 +17,32 @@ namespace openfpga { ***********************************************************************/ class StringToken { - public : /* Constructors*/ - StringToken (const std::string& data); - public : /* Public Accessors */ - std::string data() const; - std::vector split(const std::string& delims) const; - std::vector split(const char& delim) const; - std::vector split(const char* delim) const; - std::vector split(const std::vector& delim) const; - std::vector split(); - public : /* Public Mutators */ - void set_data(const std::string& data); - void add_delim(const char& delim); - void ltrim(const std::string& sensitive_word); - void rtrim(const std::string& sensitive_word); - void trim(); - private : /* Private Mutators */ - void add_default_delim(); - private: /* Internal data */ - std::string data_; /* Lines to be splited */ - std::vector delims_; + public: /* Constructors*/ + StringToken(const std::string& data); + + public: /* Public Accessors */ + std::string data() const; + std::vector split(const std::string& delims) const; + std::vector split(const char& delim) const; + std::vector split(const char* delim) const; + std::vector split(const std::vector& delim) const; + std::vector split(); + + public: /* Public Mutators */ + void set_data(const std::string& data); + void add_delim(const char& delim); + void ltrim(const std::string& sensitive_word); + void rtrim(const std::string& sensitive_word); + void trim(); + + private: /* Private Mutators */ + void add_default_delim(); + + private: /* Internal data */ + std::string data_; /* Lines to be splited */ + std::vector delims_; }; -} /* namespace openfpga ends */ +} // namespace openfpga #endif diff --git a/libs/libopenfpgautil/src/openfpga_version.h b/libs/libopenfpgautil/src/openfpga_version.h index 99d2f2ba9..66ee84ee3 100644 --- a/libs/libopenfpgautil/src/openfpga_version.h +++ b/libs/libopenfpgautil/src/openfpga_version.h @@ -15,6 +15,6 @@ extern const char* VCS_REVISION; extern const char* COMPILER; extern const char* BUILD_TIMESTAMP; extern const char* BUILD_INFO; -} // namespace openfpga +} // namespace openfpga #endif diff --git a/libs/libopenfpgautil/src/openfpga_wildcard_string.cpp b/libs/libopenfpgautil/src/openfpga_wildcard_string.cpp index 67031a2a5..35fd02d87 100644 --- a/libs/libopenfpgautil/src/openfpga_wildcard_string.cpp +++ b/libs/libopenfpgautil/src/openfpga_wildcard_string.cpp @@ -1,30 +1,25 @@ /************************************************************************ - * Member functions for WildCardString class + * Member functions for WildCardString class ***********************************************************************/ #include /* Headers from vtrutil library */ +#include "openfpga_wildcard_string.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "openfpga_wildcard_string.h" - /* namespace openfpga begins */ namespace openfpga { /************************************************************************ * Constructors ***********************************************************************/ -WildCardString::WildCardString(const std::string& data) { - set_data(data); -} +WildCardString::WildCardString(const std::string& data) { set_data(data); } /************************************************************************ * Public Accessors ***********************************************************************/ -std::string WildCardString::data() const { - return data_; -} +std::string WildCardString::data() const { return data_; } /************************************************************************ * Public Mutators @@ -32,18 +27,16 @@ std::string WildCardString::data() const { void WildCardString::set_data(const std::string& data) { data_ = data; - set_default_wildcard_char(); - set_default_sensitive_chars(); - apply_wildcard_char(); + set_default_wildcard_char(); + set_default_sensitive_chars(); + apply_wildcard_char(); compress(); } /************************************************************************ * Internal Mutators ***********************************************************************/ -void WildCardString::set_default_wildcard_char() { - wildcard_char_ = '*'; -} +void WildCardString::set_default_wildcard_char() { wildcard_char_ = '*'; } void WildCardString::set_default_sensitive_chars() { sensitive_chars_.clear(); @@ -68,7 +61,8 @@ void WildCardString::apply_wildcard_char() { for (const char& char_to_replace : sensitive_chars_) { size_t cur_pos = 0; std::string::size_type found; - while (std::string::npos != (found = data_.find_first_of(char_to_replace, cur_pos))) { + while (std::string::npos != + (found = data_.find_first_of(char_to_replace, cur_pos))) { data_.replace(found, 1, 1, wildcard_char_); cur_pos = found + 1; } @@ -87,7 +81,7 @@ void WildCardString::compress() { break; } - /* Try to find the next element and see if the same as wild card + /* Try to find the next element and see if the same as wild card * Keep erase the next element until we have a non-wildcard character */ while (data_[i] == data_[i + 1]) { @@ -102,4 +96,4 @@ void WildCardString::compress() { } } -} /* namespace openfpga ends */ +} // namespace openfpga diff --git a/libs/libopenfpgautil/src/openfpga_wildcard_string.h b/libs/libopenfpgautil/src/openfpga_wildcard_string.h index 874641cf4..cd47f7c08 100644 --- a/libs/libopenfpgautil/src/openfpga_wildcard_string.h +++ b/libs/libopenfpgautil/src/openfpga_wildcard_string.h @@ -11,8 +11,8 @@ namespace openfpga { /************************************************************************ - * This file includes a object that can apply wildcard characters - * By default it will replace any digital numbers with a '*' character + * This file includes a object that can apply wildcard characters + * By default it will replace any digital numbers with a '*' character * Users can set the wildcard character on their needs * * Example: @@ -23,35 +23,35 @@ namespace openfpga { ***********************************************************************/ class WildCardString { - public : /* Constructors*/ - WildCardString (const std::string& data); + public: /* Constructors*/ + WildCardString(const std::string& data); - public : /* Public Accessors */ - std::string data() const; + public: /* Public Accessors */ + std::string data() const; - public : /* Public Mutators */ - /* Give a string to apply wildcards */ - void set_data(const std::string& data); + public: /* Public Mutators */ + /* Give a string to apply wildcards */ + void set_data(const std::string& data); - private : /* Private Mutators */ - /* Use default wildcard character '*' */ - void set_default_wildcard_char(); + private: /* Private Mutators */ + /* Use default wildcard character '*' */ + void set_default_wildcard_char(); - /* Use default sensitive words which are numbers */ - void set_default_sensitive_chars(); + /* Use default sensitive words which are numbers */ + void set_default_sensitive_chars(); - /* Replace sensitive words with wildcard characters */ - void apply_wildcard_char(); + /* Replace sensitive words with wildcard characters */ + void apply_wildcard_char(); - /* Remove redundant wildcard chars (which are next to each other) */ - void compress(); + /* Remove redundant wildcard chars (which are next to each other) */ + void compress(); - private : /* Internal data */ - std::string data_; /* Lines to be splited */ - std::vector sensitive_chars_; - char wildcard_char_; + private: /* Internal data */ + std::string data_; /* Lines to be splited */ + std::vector sensitive_chars_; + char wildcard_char_; }; -} /* namespace openfpga ends */ +} // namespace openfpga #endif diff --git a/libs/libpcf/src/base/io_location_map.cpp b/libs/libpcf/src/base/io_location_map.cpp index e34326331..994ebfa23 100644 --- a/libs/libpcf/src/base/io_location_map.cpp +++ b/libs/libpcf/src/base/io_location_map.cpp @@ -3,23 +3,22 @@ ******************************************************************************/ /* Headers from vtrutil library */ #include -#include "vtr_log.h" + #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - #include "io_location_map.h" +#include "openfpga_digest.h" /* begin namespace openfpga */ namespace openfpga { /************************************************** - * Public Accessors + * Public Accessors *************************************************/ -size_t IoLocationMap::io_index(const size_t& x, - const size_t& y, +size_t IoLocationMap::io_index(const size_t& x, const size_t& y, const size_t& z, const std::string& io_port_name) const { std::array coord = {x, y, z}; @@ -29,9 +28,11 @@ size_t IoLocationMap::io_index(const size_t& x, } for (const BasicPort& candidate : result->second) { if (candidate.get_name() == io_port_name) { - /* First found, first return. This may create bugs when FPGA architecture are more flexible - * FIXME: However, we should not have multiple I/O in the same name, mapped to the same coordindate - * For example, PAD[0] -> (1, 0, 1) and PAD[1] -> (1, 0, 1) + /* First found, first return. This may create bugs when FPGA architecture + * are more flexible + * FIXME: However, we should not have multiple I/O in the same name, + * mapped to the same coordindate For example, PAD[0] -> (1, 0, 1) and + * PAD[1] -> (1, 0, 1) */ return candidate.get_lsb(); } @@ -72,8 +73,7 @@ size_t IoLocationMap::io_z(const BasicPort& io_port) const { return size_t(-1); } -void IoLocationMap::set_io_index(const size_t& x, - const size_t& y, +void IoLocationMap::set_io_index(const size_t& x, const size_t& y, const size_t& z, const std::string& io_port_name, const size_t& io_index) { @@ -81,10 +81,13 @@ void IoLocationMap::set_io_index(const size_t& x, BasicPort port_to_add(io_port_name, io_index, io_index); auto result = io_indices_.find(coord); if (result != io_indices_.end()) { - if (io_indices_.at(coord).end() != std::find(io_indices_.at(coord).begin(), io_indices_.at(coord).end(), port_to_add)) { - VTR_LOG_WARN("Attempt to add duplicated io '%s[%lu]' to coordinate (%lu, %lu, %lu)! Skip to save memory\n", - io_port_name.c_str(), io_index, - x, y, z); + if (io_indices_.at(coord).end() != std::find(io_indices_.at(coord).begin(), + io_indices_.at(coord).end(), + port_to_add)) { + VTR_LOG_WARN( + "Attempt to add duplicated io '%s[%lu]' to coordinate (%lu, %lu, %lu)! " + "Skip to save memory\n", + io_port_name.c_str(), io_index, x, y, z); } } @@ -94,7 +97,9 @@ void IoLocationMap::set_io_index(const size_t& x, int IoLocationMap::write_to_xml_file(const std::string& fname, const bool& include_time_stamp, const bool& verbose) const { - std::string timer_message = std::string("Write fabric I/O information to an XML file '") + fname + std::string("'"); + std::string timer_message = + std::string("Write fabric I/O information to an XML file '") + fname + + std::string("'"); std::string dir_path = format_dir_path(find_path_dir_name(fname)); @@ -122,10 +127,10 @@ int IoLocationMap::write_to_xml_file(const std::string& fname, fp << "\t- FPGA Fabric I/O Information" << std::endl; fp << "\t- Generated by OpenFPGA" << std::endl; - auto end = std::chrono::system_clock::now(); + auto end = std::chrono::system_clock::now(); std::time_t end_time = std::chrono::system_clock::to_time_t(end); if (include_time_stamp) { - fp << "\t- Date: " << std::ctime(&end_time) ; + fp << "\t- Date: " << std::ctime(&end_time); } fp << "-->" << std::endl; @@ -138,15 +143,20 @@ int IoLocationMap::write_to_xml_file(const std::string& fname, /* Walk through the fabric I/O location map data structure */ for (auto pair : io_indices_) { for (const BasicPort& port : pair.second) { - fp << "\t" << ""; fp << "\n"; io_cnt++; } - } + } /* Print an end to the file here */ fp << "\n"; @@ -154,9 +164,7 @@ int IoLocationMap::write_to_xml_file(const std::string& fname, /* close a file */ fp.close(); - VTR_LOGV(verbose, - "Outputted %lu I/Os to XML file: %s\n", - io_cnt, + VTR_LOGV(verbose, "Outputted %lu I/Os to XML file: %s\n", io_cnt, fname.c_str()); return err_code; diff --git a/libs/libpcf/src/base/io_location_map.h b/libs/libpcf/src/base/io_location_map.h index eafaef5d6..19b751302 100644 --- a/libs/libpcf/src/base/io_location_map.h +++ b/libs/libpcf/src/base/io_location_map.h @@ -5,10 +5,12 @@ * Include header files required by the data structure definition *******************************************************************/ #include -#include -#include -#include + #include +#include +#include +#include + #include "openfpga_port.h" /* Begin namespace openfpga */ @@ -19,7 +21,7 @@ namespace openfpga { * in the FPGA fabric, i.e., the module graph, and logical location * of the I/O in VPR coordinate system * - * For example: + * For example: * * ioA[0] ioA[1] ioB[0] ioB[1] ioA[2] * +-----------------+ +--------+--------+ +--------+ @@ -31,29 +33,27 @@ namespace openfpga { * *******************************************************************/ class IoLocationMap { - public: /* Public aggregators */ - size_t io_index(const size_t& x, - const size_t& y, - const size_t& z, - const std::string& io_port_name) const; - size_t io_x(const BasicPort& io_port) const; - size_t io_y(const BasicPort& io_port) const; - size_t io_z(const BasicPort& io_port) const; - public: /* Public mutators */ - void set_io_index(const size_t& x, - const size_t& y, - const size_t& z, - const std::string& io_port_name, - const size_t& io_index); - public: /* Public writer */ - int write_to_xml_file(const std::string& fname, - const bool& include_time_stamp, - const bool& verbose) const; - private: /* Internal Data */ - /* I/O index fast lookup by [x][y][z] location - * Note that multiple I/Os may be assigned to the same coordinate! - */ - std::map, std::vector> io_indices_; + public: /* Public aggregators */ + size_t io_index(const size_t& x, const size_t& y, const size_t& z, + const std::string& io_port_name) const; + size_t io_x(const BasicPort& io_port) const; + size_t io_y(const BasicPort& io_port) const; + size_t io_z(const BasicPort& io_port) const; + + public: /* Public mutators */ + void set_io_index(const size_t& x, const size_t& y, const size_t& z, + const std::string& io_port_name, const size_t& io_index); + + public: /* Public writer */ + int write_to_xml_file(const std::string& fname, + const bool& include_time_stamp, + const bool& verbose) const; + + private: /* Internal Data */ + /* I/O index fast lookup by [x][y][z] location + * Note that multiple I/Os may be assigned to the same coordinate! + */ + std::map, std::vector> io_indices_; }; } /* End namespace openfpga*/ diff --git a/libs/libpcf/src/base/io_net_place.cpp b/libs/libpcf/src/base/io_net_place.cpp index 902103f29..5e6e4f774 100644 --- a/libs/libpcf/src/base/io_net_place.cpp +++ b/libs/libpcf/src/base/io_net_place.cpp @@ -2,20 +2,19 @@ * Memember functions for data structure IoNetPlace ******************************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - #include "io_net_place.h" +#include "openfpga_digest.h" /* begin namespace openfpga */ namespace openfpga { /************************************************** - * Public Accessors + * Public Accessors *************************************************/ size_t IoNetPlace::io_x(const std::string& net) const { auto result = io_coords_.find(net); @@ -44,17 +43,16 @@ size_t IoNetPlace::io_z(const std::string& net) const { return result->second[2]; } -void IoNetPlace::set_net_coord(const std::string& net, - const size_t& x, - const size_t& y, - const size_t& z) { - /* Warn when there is an attempt to overwrite */ +void IoNetPlace::set_net_coord(const std::string& net, const size_t& x, + const size_t& y, const size_t& z) { + /* Warn when there is an attempt to overwrite */ auto result = io_coords_.find(net); if (result != io_coords_.end()) { - VTR_LOG_WARN("Overwrite net '%s' coordinate from (%lu, %lu, %lu) to (%lu, %lu, %lu)!\n", - net.c_str(), - result->second[0], result->second[1], result->second[2], - x, y, z); + VTR_LOG_WARN( + "Overwrite net '%s' coordinate from (%lu, %lu, %lu) to (%lu, %lu, " + "%lu)!\n", + net.c_str(), result->second[0], result->second[1], result->second[2], x, + y, z); } io_coords_[net][0] = x; io_coords_[net][1] = y; @@ -64,7 +62,9 @@ void IoNetPlace::set_net_coord(const std::string& net, int IoNetPlace::write_to_place_file(const std::string& fname, const bool& include_time_stamp, const bool& verbose) const { - std::string timer_message = std::string("Write I/O coordinates to a place file '") + fname + std::string("'"); + std::string timer_message = + std::string("Write I/O coordinates to a place file '") + fname + + std::string("'"); std::string dir_path = format_dir_path(find_path_dir_name(fname)); @@ -91,10 +91,10 @@ int IoNetPlace::write_to_place_file(const std::string& fname, fp << "# FPGA Fixed I/O placement file" << std::endl; fp << "# Generated by OpenFPGA" << std::endl; - auto end = std::chrono::system_clock::now(); + auto end = std::chrono::system_clock::now(); std::time_t end_time = std::chrono::system_clock::to_time_t(end); if (include_time_stamp) { - fp << "# Date: " << std::ctime(&end_time) ; + fp << "# Date: " << std::ctime(&end_time); } fp << "#Block Name\tx\ty\tz" << std::endl; @@ -109,18 +109,15 @@ int IoNetPlace::write_to_place_file(const std::string& fname, fp << pair.second[1] << "\t"; fp << pair.second[2] << "\n"; io_cnt++; - } + } /* close a file */ fp.close(); - VTR_LOGV(verbose, - "Outputted %lu I/Os to place file: %s\n", - io_cnt, + VTR_LOGV(verbose, "Outputted %lu I/Os to place file: %s\n", io_cnt, fname.c_str()); return err_code; } - } /* end namespace openfpga */ diff --git a/libs/libpcf/src/base/io_net_place.h b/libs/libpcf/src/base/io_net_place.h index 6a841ec3e..fc8e42e9e 100644 --- a/libs/libpcf/src/base/io_net_place.h +++ b/libs/libpcf/src/base/io_net_place.h @@ -5,10 +5,11 @@ * Include header files required by the data structure definition *******************************************************************/ #include -#include -#include -#include + #include +#include +#include +#include /* Begin namespace openfpga */ namespace openfpga { @@ -17,7 +18,7 @@ namespace openfpga { * I/O net place is a data structure to store the coordinate of each nets * defined in users' HDL designs on FPGA fabric. * - * For example: + * For example: * netA netB * | | * v v @@ -31,22 +32,23 @@ namespace openfpga { * *******************************************************************/ class IoNetPlace { - public: /* Public aggregators */ - size_t io_x(const std::string& net) const; - size_t io_y(const std::string& net) const; - size_t io_z(const std::string& net) const; - public: /* Writers */ - int write_to_place_file(const std::string& fname, - const bool& include_time_stamp, - const bool& verbose) const; - public: /* Public mutators */ - void set_net_coord(const std::string& net, - const size_t& x, - const size_t& y, - const size_t& z); - private: /* Internal Data */ - /* I/O coordinate fast lookup by net name */ - std::map> io_coords_; + public: /* Public aggregators */ + size_t io_x(const std::string& net) const; + size_t io_y(const std::string& net) const; + size_t io_z(const std::string& net) const; + + public: /* Writers */ + int write_to_place_file(const std::string& fname, + const bool& include_time_stamp, + const bool& verbose) const; + + public: /* Public mutators */ + void set_net_coord(const std::string& net, const size_t& x, const size_t& y, + const size_t& z); + + private: /* Internal Data */ + /* I/O coordinate fast lookup by net name */ + std::map> io_coords_; }; } /* End namespace openfpga*/ diff --git a/libs/libpcf/src/base/io_pin_table.cpp b/libs/libpcf/src/base/io_pin_table.cpp index f54d332c2..64f304acf 100644 --- a/libs/libpcf/src/base/io_pin_table.cpp +++ b/libs/libpcf/src/base/io_pin_table.cpp @@ -1,10 +1,10 @@ +#include "io_pin_table.h" + #include #include "vtr_assert.h" #include "vtr_log.h" -#include "io_pin_table.h" - /* begin namespace openfpga */ namespace openfpga { @@ -15,9 +15,7 @@ namespace openfpga { /************************************************************************ * Constructors ***********************************************************************/ -IoPinTable::IoPinTable() { - return; -} +IoPinTable::IoPinTable() { return; } /************************************************************************ * Public Accessors : aggregates @@ -27,46 +25,46 @@ IoPinTable::io_pin_table_range IoPinTable::pins() const { } /************************************************************************ - * Public Accessors : Basic data query + * Public Accessors : Basic data query ***********************************************************************/ BasicPort IoPinTable::internal_pin(const IoPinTableId& pin_id) const { /* validate the pin_id */ VTR_ASSERT(valid_pin_id(pin_id)); - return internal_pins_[pin_id]; + return internal_pins_[pin_id]; } BasicPort IoPinTable::external_pin(const IoPinTableId& pin_id) const { /* validate the pin_id */ VTR_ASSERT(valid_pin_id(pin_id)); - return external_pins_[pin_id]; + return external_pins_[pin_id]; } e_side IoPinTable::pin_side(const IoPinTableId& pin_id) const { /* validate the pin_id */ VTR_ASSERT(valid_pin_id(pin_id)); - return pin_sides_[pin_id]; + return pin_sides_[pin_id]; } -IoPinTable::e_io_direction IoPinTable::pin_direction(const IoPinTableId& pin_id) const { +IoPinTable::e_io_direction IoPinTable::pin_direction( + const IoPinTableId& pin_id) const { /* validate the pin_id */ VTR_ASSERT(valid_pin_id(pin_id)); - return pin_directions_[pin_id]; + return pin_directions_[pin_id]; } -std::vector IoPinTable::find_internal_pin(const BasicPort& ext_pin, - const e_io_direction& pin_direction) const { +std::vector IoPinTable::find_internal_pin( + const BasicPort& ext_pin, const e_io_direction& pin_direction) const { std::vector int_pin_ids; for (auto pin_id : pin_ids_) { - if ((external_pins_[pin_id] == ext_pin) && (pin_directions_[pin_id] == pin_direction)) { + if ((external_pins_[pin_id] == ext_pin) && + (pin_directions_[pin_id] == pin_direction)) { int_pin_ids.push_back(pin_id); } } return int_pin_ids; } -bool IoPinTable::empty() const { - return 0 == pin_ids_.size(); -} +bool IoPinTable::empty() const { return 0 == pin_ids_.size(); } /************************************************************************ * Public Mutators @@ -82,22 +80,24 @@ void IoPinTable::reserve_pins(const size_t& num_pins) { IoPinTableId IoPinTable::create_pin() { /* Create a new id */ IoPinTableId pin_id = IoPinTableId(pin_ids_.size()); - + pin_ids_.push_back(pin_id); - internal_pins_.emplace_back(); - external_pins_.emplace_back(); - pin_sides_.emplace_back(NUM_SIDES); - pin_directions_.emplace_back(NUM_IO_DIRECTIONS); - + internal_pins_.emplace_back(); + external_pins_.emplace_back(); + pin_sides_.emplace_back(NUM_SIDES); + pin_directions_.emplace_back(NUM_IO_DIRECTIONS); + return pin_id; } -void IoPinTable::set_internal_pin(const IoPinTableId& pin_id, const BasicPort& pin) { +void IoPinTable::set_internal_pin(const IoPinTableId& pin_id, + const BasicPort& pin) { VTR_ASSERT(valid_pin_id(pin_id)); internal_pins_[pin_id] = pin; } -void IoPinTable::set_external_pin(const IoPinTableId& pin_id, const BasicPort& pin) { +void IoPinTable::set_external_pin(const IoPinTableId& pin_id, + const BasicPort& pin) { VTR_ASSERT(valid_pin_id(pin_id)); external_pins_[pin_id] = pin; } @@ -107,17 +107,18 @@ void IoPinTable::set_pin_side(const IoPinTableId& pin_id, const e_side& side) { pin_sides_[pin_id] = side; } -void IoPinTable::set_pin_direction(const IoPinTableId& pin_id, const e_io_direction& direction) { +void IoPinTable::set_pin_direction(const IoPinTableId& pin_id, + const e_io_direction& direction) { VTR_ASSERT(valid_pin_id(pin_id)); pin_directions_[pin_id] = direction; } /************************************************************************ - * Internal invalidators/validators + * Internal invalidators/validators ***********************************************************************/ /* Validators */ bool IoPinTable::valid_pin_id(const IoPinTableId& pin_id) const { - return ( size_t(pin_id) < pin_ids_.size() ) && ( pin_id == pin_ids_[pin_id] ); + return (size_t(pin_id) < pin_ids_.size()) && (pin_id == pin_ids_[pin_id]); } } /* end namespace openfpga */ diff --git a/libs/libpcf/src/base/io_pin_table.h b/libs/libpcf/src/base/io_pin_table.h index 3eb2c62ab..a965c4598 100644 --- a/libs/libpcf/src/base/io_pin_table.h +++ b/libs/libpcf/src/base/io_pin_table.h @@ -4,21 +4,20 @@ /******************************************************************** * This file include the declaration of pin constraints *******************************************************************/ -#include -#include #include +#include +#include /* Headers from vtrutil library */ -#include "vtr_vector.h" #include "vtr_geometry.h" +#include "vtr_vector.h" /* Headers from libarchfpga library */ #include "physical_types.h" /* Headers from openfpgautil library */ -#include "openfpga_port.h" - #include "io_pin_table_fwd.h" +#include "openfpga_port.h" /* begin namespace openfpga */ namespace openfpga { @@ -28,12 +27,14 @@ namespace openfpga { * This data structure may include a number of I/O pins * each of which contains the following information * - side: the side which this I/O locates on FPGA perimeter - * - external_pin_name: the name of the external I/O pin (typically on a packaged chip), which is exposed to end-users - * - internal_pin_name: the name of the internal I/O pin (typically inside the chip but on an FPGA fabric), which is defined in FPGA netlists - * - direction: the direction of the internal pin, can be input, output or inout + * - external_pin_name: the name of the external I/O pin (typically on a + *packaged chip), which is exposed to end-users + * - internal_pin_name: the name of the internal I/O pin (typically inside the + *chip but on an FPGA fabric), which is defined in FPGA netlists + * - direction: the direction of the internal pin, can be input, output or inout * - * The following figure illustrates the relationship between external and internal pins. - * FPGA Chip + * The following figure illustrates the relationship between external and + *internal pins. FPGA Chip * +---------------------------------------- * | FPGA fabric * | +---------------------- @@ -41,7 +42,7 @@ namespace openfpga { * CHIP_IO_TOP --->|--->| I/O |--->| FPGA_IN[0] * (External pin) | | Ctrl | | (internal pin as input) * | | |<---| FPGA_OUT[1] - * | +------+ | (internal pin as output) + * | +------+ | (internal pin as output) * * Typical usage: * -------------- @@ -50,61 +51,66 @@ namespace openfpga { * // Add a pin * openfpga::BasicPort ext_pin_info("CHIP_IO_TOP", 1); * openfpga::BasicPort int_pin_info("FPGA_IN", 1, 1); - * IoPinTableId pin_id = io_pin_table.create_io_pin(int_pin_info, ext_pin_info, TOP, INPUT); + * IoPinTableId pin_id = io_pin_table.create_io_pin(int_pin_info, + *ext_pin_info, TOP, INPUT); * *******************************************************************/ class IoPinTable { - public: /* Types */ - typedef vtr::vector::const_iterator io_pin_table_iterator; - /* Create range */ - typedef vtr::Range io_pin_table_range; - /* Logic value */ - enum e_io_direction { - INPUT, - OUTPUT, - NUM_IO_DIRECTIONS - }; - public: /* Constructors */ - IoPinTable(); - public: /* Accessors: aggregates */ - /* Walk through the internal pins. We do not walk through external pins because they are not unique in the table. - * An external pin may be accessible by two internal pins - */ - io_pin_table_range pins() const; - public: /* Public Accessors: Basic data query */ - /* Get the basic information for a pin */ - BasicPort internal_pin(const IoPinTableId& pin_id) const; - BasicPort external_pin(const IoPinTableId& pin_id) const; - e_side pin_side(const IoPinTableId& pin_id) const; - e_io_direction pin_direction(const IoPinTableId& pin_id) const; - /* Given an external pin, find all the internal pin that is mapped */ - std::vector find_internal_pin(const BasicPort& ext_pin, - const e_io_direction& pin_direction) const; - /* Check if there are any pins */ - bool empty() const; - public: /* Public Mutators */ - /* Reserve to be memory efficent */ - void reserve_pins(const size_t& num_pins); - /* Add a pin to storage */ - IoPinTableId create_pin(); - /* Set pin attributes */ - void set_internal_pin(const IoPinTableId& pin_id, const BasicPort& pin); - void set_external_pin(const IoPinTableId& pin_id, const BasicPort& pin); - void set_pin_side(const IoPinTableId& pin_id, const e_side& side); - void set_pin_direction(const IoPinTableId& pin_id, const e_io_direction& direction); + public: /* Types */ + typedef vtr::vector::const_iterator + io_pin_table_iterator; + /* Create range */ + typedef vtr::Range io_pin_table_range; + /* Logic value */ + enum e_io_direction { INPUT, OUTPUT, NUM_IO_DIRECTIONS }; - public: /* Public invalidators/validators */ - /* Show if the pin id is a valid for data queries */ - bool valid_pin_id(const IoPinTableId& pin_id) const; - private: /* Internal data */ - /* Unique ids for each design constraint */ - vtr::vector pin_ids_; + public: /* Constructors */ + IoPinTable(); - /* Pin information*/ - vtr::vector internal_pins_; - vtr::vector external_pins_; - vtr::vector pin_sides_; - vtr::vector pin_directions_; + public: /* Accessors: aggregates */ + /* Walk through the internal pins. We do not walk through external pins + * because they are not unique in the table. An external pin may be accessible + * by two internal pins + */ + io_pin_table_range pins() const; + + public: /* Public Accessors: Basic data query */ + /* Get the basic information for a pin */ + BasicPort internal_pin(const IoPinTableId& pin_id) const; + BasicPort external_pin(const IoPinTableId& pin_id) const; + e_side pin_side(const IoPinTableId& pin_id) const; + e_io_direction pin_direction(const IoPinTableId& pin_id) const; + /* Given an external pin, find all the internal pin that is mapped */ + std::vector find_internal_pin( + const BasicPort& ext_pin, const e_io_direction& pin_direction) const; + /* Check if there are any pins */ + bool empty() const; + + public: /* Public Mutators */ + /* Reserve to be memory efficent */ + void reserve_pins(const size_t& num_pins); + /* Add a pin to storage */ + IoPinTableId create_pin(); + /* Set pin attributes */ + void set_internal_pin(const IoPinTableId& pin_id, const BasicPort& pin); + void set_external_pin(const IoPinTableId& pin_id, const BasicPort& pin); + void set_pin_side(const IoPinTableId& pin_id, const e_side& side); + void set_pin_direction(const IoPinTableId& pin_id, + const e_io_direction& direction); + + public: /* Public invalidators/validators */ + /* Show if the pin id is a valid for data queries */ + bool valid_pin_id(const IoPinTableId& pin_id) const; + + private: /* Internal data */ + /* Unique ids for each design constraint */ + vtr::vector pin_ids_; + + /* Pin information*/ + vtr::vector internal_pins_; + vtr::vector external_pins_; + vtr::vector pin_sides_; + vtr::vector pin_directions_; }; } /* end namespace openfpga */ diff --git a/libs/libpcf/src/base/io_pin_table_fwd.h b/libs/libpcf/src/base/io_pin_table_fwd.h index 3b8c8e518..f86783c2e 100644 --- a/libs/libpcf/src/base/io_pin_table_fwd.h +++ b/libs/libpcf/src/base/io_pin_table_fwd.h @@ -1,11 +1,11 @@ /************************************************************************ * A header file for IoPinTable class, including critical data declaration * Please include this file only for using any IoPinTable data structure - * Refer to IoPinTable.h for more details + * Refer to IoPinTable.h for more details ***********************************************************************/ /************************************************************************ - * Create strong id for IoPinTable to avoid illegal type casting + * Create strong id for IoPinTable to avoid illegal type casting ***********************************************************************/ #ifndef IO_PIN_TABLE_FWD_H #define IO_PIN_TABLE_FWD_H diff --git a/libs/libpcf/src/base/pcf2place.cpp b/libs/libpcf/src/base/pcf2place.cpp index 98ce638ea..7895667e7 100644 --- a/libs/libpcf/src/base/pcf2place.cpp +++ b/libs/libpcf/src/base/pcf2place.cpp @@ -4,13 +4,12 @@ #include /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgautil library */ #include "openfpga_digest.h" - #include "pcf2place.h" /* begin namespace openfpga */ @@ -26,8 +25,7 @@ int pcf2place(const PcfData& pcf_data, const std::vector& input_nets, const std::vector& output_nets, const IoPinTable& io_pin_table, - const IoLocationMap& io_location_map, - IoNetPlace& io_net_place) { + const IoLocationMap& io_location_map, IoNetPlace& io_net_place) { vtr::ScopedStartFinishTimer timer("Convert PCF data to VPR I/O place data"); int num_err = 0; @@ -37,10 +35,10 @@ int pcf2place(const PcfData& pcf_data, * - the pin direction in io_pin_table matches the pin type defined in blif */ if (!pcf_data.validate()) { - VTR_LOG_ERROR("PCF contains invalid I/O assignment!\n"); + VTR_LOG_ERROR("PCF contains invalid I/O assignment!\n"); return 1; } else { - VTR_LOG("PCF basic check passed\n"); + VTR_LOG("PCF basic check passed\n"); } /* Build the I/O place */ @@ -51,31 +49,39 @@ int pcf2place(const PcfData& pcf_data, BasicPort ext_pin = pcf_data.io_pin(io_id); /* Find the pin direction from blif reader */ IoPinTable::e_io_direction pin_direction = IoPinTable::NUM_IO_DIRECTIONS; - if (input_nets.end() != std::find(input_nets.begin(), input_nets.end(), net)) { + if (input_nets.end() != + std::find(input_nets.begin(), input_nets.end(), net)) { pin_direction = IoPinTable::INPUT; - } else if (output_nets.end() != std::find(output_nets.begin(), output_nets.end(), net)) { + } else if (output_nets.end() != + std::find(output_nets.begin(), output_nets.end(), net)) { pin_direction = IoPinTable::OUTPUT; } else { /* Cannot find the pin, error out! */ - VTR_LOG_ERROR("Net '%s' from .pcf is neither defined as input nor output in .blif!\n", - net.c_str()); + VTR_LOG_ERROR( + "Net '%s' from .pcf is neither defined as input nor output in .blif!\n", + net.c_str()); num_err++; continue; } - /* Find the internal pin name from pin table, currently we only support 1-to-1 mapping */ + /* Find the internal pin name from pin table, currently we only support + * 1-to-1 mapping */ auto int_pin_ids = io_pin_table.find_internal_pin(ext_pin, pin_direction); if (0 == int_pin_ids.size()) { - VTR_LOG_ERROR("Cannot find any internal pin that net '%s' is mapped through an external pin '%s[%lu]'!\n", - net.c_str(), - ext_pin.get_name().c_str(), ext_pin.get_lsb()); + VTR_LOG_ERROR( + "Cannot find any internal pin that net '%s' is mapped through an " + "external pin '%s[%lu]'!\n", + net.c_str(), ext_pin.get_name().c_str(), ext_pin.get_lsb()); num_err++; continue; } else if (1 < int_pin_ids.size()) { - VTR_LOG_ERROR("Found multiple internal pins that net '%s' is mapped through an external pin '%s[%lu]'! Please double check your pin table!\n", - net.c_str(), - ext_pin.get_name().c_str(), ext_pin.get_lsb()); + VTR_LOG_ERROR( + "Found multiple internal pins that net '%s' is mapped through an " + "external pin '%s[%lu]'! Please double check your pin table!\n", + net.c_str(), ext_pin.get_name().c_str(), ext_pin.get_lsb()); for (auto int_pin_id : int_pin_ids) { - VTR_LOG("%s[%ld]\n", io_pin_table.internal_pin(int_pin_id).get_name().c_str(), io_pin_table.internal_pin(int_pin_id).get_lsb()); + VTR_LOG("%s[%ld]\n", + io_pin_table.internal_pin(int_pin_id).get_name().c_str(), + io_pin_table.internal_pin(int_pin_id).get_lsb()); } num_err++; continue; @@ -83,22 +89,22 @@ int pcf2place(const PcfData& pcf_data, VTR_ASSERT(1 == int_pin_ids.size()); BasicPort int_pin = io_pin_table.internal_pin(int_pin_ids[0]); /* Find the coordinate from io location map */ - size_t x = io_location_map.io_x(int_pin); - size_t y = io_location_map.io_y(int_pin); - size_t z = io_location_map.io_z(int_pin); + size_t x = io_location_map.io_x(int_pin); + size_t y = io_location_map.io_y(int_pin); + size_t z = io_location_map.io_z(int_pin); /* Sanity check */ if (size_t(-1) == x || size_t(-1) == y || size_t(-1) == z) { - VTR_LOG_ERROR("Invalid coordinate (%ld, %ld, %ld) found for net '%s' mapped to an external pin '%s[%lu]' through an internal pin '%s[%lu]'!\n", - x, y, z, - net.c_str(), - ext_pin.get_name().c_str(), ext_pin.get_lsb(), - int_pin.get_name().c_str(), int_pin.get_lsb()); + VTR_LOG_ERROR( + "Invalid coordinate (%ld, %ld, %ld) found for net '%s' mapped to an " + "external pin '%s[%lu]' through an internal pin '%s[%lu]'!\n", + x, y, z, net.c_str(), ext_pin.get_name().c_str(), ext_pin.get_lsb(), + int_pin.get_name().c_str(), int_pin.get_lsb()); continue; } /* Add a fixed prefix to net namei, this is hard coded by VPR */ if (IoPinTable::OUTPUT == pin_direction) { - net = "out:" + net; + net = "out:" + net; } /* Add the information to I/O place data */ io_net_place.set_net_coord(net, x, y, z); diff --git a/libs/libpcf/src/base/pcf2place.h b/libs/libpcf/src/base/pcf2place.h index 96bc3d4d3..096b075df 100644 --- a/libs/libpcf/src/base/pcf2place.h +++ b/libs/libpcf/src/base/pcf2place.h @@ -5,10 +5,11 @@ *******************************************************************/ #include #include -#include "pcf_data.h" -#include "io_pin_table.h" + #include "io_location_map.h" #include "io_net_place.h" +#include "io_pin_table.h" +#include "pcf_data.h" /* Begin namespace openfpga */ namespace openfpga { @@ -23,8 +24,7 @@ int pcf2place(const PcfData& pcf_data, const std::vector& input_nets, const std::vector& output_nets, const IoPinTable& io_pin_table, - const IoLocationMap& io_location_map, - IoNetPlace& io_net_place); + const IoLocationMap& io_location_map, IoNetPlace& io_net_place); } /* End namespace openfpga*/ diff --git a/libs/libpcf/src/base/pcf_data.cpp b/libs/libpcf/src/base/pcf_data.cpp index 721e8dc7a..e4a036666 100644 --- a/libs/libpcf/src/base/pcf_data.cpp +++ b/libs/libpcf/src/base/pcf_data.cpp @@ -1,11 +1,11 @@ +#include "pcf_data.h" + #include +#include "openfpga_port_parser.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "openfpga_port_parser.h" -#include "pcf_data.h" - /* Begin namespace openfpga */ namespace openfpga { @@ -16,9 +16,7 @@ namespace openfpga { /************************************************************************ * Constructors ***********************************************************************/ -PcfData::PcfData() { - return; -} +PcfData::PcfData() { return; } /************************************************************************ * Public Accessors : aggregates @@ -28,43 +26,41 @@ PcfData::pcf_io_constraint_range PcfData::io_constraints() const { } /************************************************************************ - * Public Accessors : Basic data query + * Public Accessors : Basic data query ***********************************************************************/ openfpga::BasicPort PcfData::io_pin(const PcfIoConstraintId& io_id) const { /* validate the io_id */ VTR_ASSERT(valid_io_constraint_id(io_id)); - return io_constraint_pins_[io_id]; + return io_constraint_pins_[io_id]; } std::string PcfData::io_net(const PcfIoConstraintId& io_id) const { /* validate the io_id */ VTR_ASSERT(valid_io_constraint_id(io_id)); - return io_constraint_nets_[io_id]; + return io_constraint_nets_[io_id]; } -bool PcfData::empty() const { - return 0 == io_constraint_ids_.size(); -} +bool PcfData::empty() const { return 0 == io_constraint_ids_.size(); } bool PcfData::validate() const { size_t num_err = 0; /* In principle, we do not expect duplicated assignment: 1 net -> 2 pins */ - std::map net2pin; + std::map net2pin; for (const PcfIoConstraintId& io_id : io_constraints()) { std::string curr_net = io_constraint_nets_[io_id]; BasicPort curr_pin = io_constraint_pins_[io_id]; auto result = net2pin.find(curr_net); if (result != net2pin.end()) { /* Found one nets assigned to two pins, throw warning */ - VTR_LOG_WARN("Net '%s' is assigned to two pins '%s[%lu]' and '%s[%lu]'!\n", - curr_net.c_str(), - curr_pin.get_name().c_str(), curr_pin.get_lsb(), - result->second.get_name().c_str(), result->second.get_lsb()); + VTR_LOG_WARN( + "Net '%s' is assigned to two pins '%s[%lu]' and '%s[%lu]'!\n", + curr_net.c_str(), curr_pin.get_name().c_str(), curr_pin.get_lsb(), + result->second.get_name().c_str(), result->second.get_lsb()); } net2pin[curr_net] = curr_pin; } /* We should not have duplicated pins in assignment: 1 pin -> 2 nets */ - std::map pin2net; + std::map pin2net; for (const PcfIoConstraintId& io_id : io_constraints()) { std::string curr_net = io_constraint_nets_[io_id]; BasicPort curr_pin = io_constraint_pins_[io_id]; @@ -95,11 +91,11 @@ void PcfData::reserve_io_constraints(const size_t& num_io_constraints) { PcfIoConstraintId PcfData::create_io_constraint() { /* Create a new id */ PcfIoConstraintId io_id = PcfIoConstraintId(io_constraint_ids_.size()); - + io_constraint_ids_.push_back(io_id); io_constraint_pins_.emplace_back(); io_constraint_nets_.emplace_back(); - + return io_id; } @@ -117,12 +113,12 @@ void PcfData::set_io_pin(const PcfIoConstraintId& io_id, } /************************************************************************ - * Internal invalidators/validators + * Internal invalidators/validators ***********************************************************************/ /* Validators */ bool PcfData::valid_io_constraint_id(const PcfIoConstraintId& io_id) const { - return ( size_t(io_id) < io_constraint_ids_.size() ) && ( io_id == io_constraint_ids_[io_id] ); + return (size_t(io_id) < io_constraint_ids_.size()) && + (io_id == io_constraint_ids_[io_id]); } } /* End namespace openfpga*/ - diff --git a/libs/libpcf/src/base/pcf_data.h b/libs/libpcf/src/base/pcf_data.h index 9ff314415..f58605a0e 100644 --- a/libs/libpcf/src/base/pcf_data.h +++ b/libs/libpcf/src/base/pcf_data.h @@ -4,17 +4,16 @@ /******************************************************************** * This file include the declaration of pcf data *******************************************************************/ -#include -#include #include +#include +#include /* Headers from vtrutil library */ -#include "vtr_vector.h" #include "vtr_geometry.h" +#include "vtr_vector.h" /* Headers from openfpgautil library */ #include "openfpga_port.h" - #include "pcf_data_fwd.h" /* Begin namespace openfpga */ @@ -30,61 +29,63 @@ namespace openfpga { * // Create an object * PcfData pcf_data; * // Add a constraint - * PcfIoConstraintId io_id = pcf_data.create_io_constraint(); + * PcfIoConstraintId io_id = pcf_data.create_io_constraint(); * pcf_data.set_io_net(io_id, net_name); * pcf_data.set_io_pin(io_id, pin_name); * *******************************************************************/ class PcfData { - public: /* Types */ - typedef vtr::vector::const_iterator pcf_io_constraint_iterator; - /* Create range */ - typedef vtr::Range pcf_io_constraint_range; - public: /* Constructors */ - PcfData(); - public: /* Accessors: aggregates */ - pcf_io_constraint_range io_constraints() const; - public: /* Public Accessors: Basic data query */ - /* Get the pin to be constrained */ - openfpga::BasicPort io_pin(const PcfIoConstraintId& io_id) const; + public: /* Types */ + typedef vtr::vector::const_iterator + pcf_io_constraint_iterator; + /* Create range */ + typedef vtr::Range pcf_io_constraint_range; - /* Get the net to be constrained */ - std::string io_net(const PcfIoConstraintId& io_id) const; + public: /* Constructors */ + PcfData(); - /* Check if there are any io constraints */ - bool empty() const; + public: /* Accessors: aggregates */ + pcf_io_constraint_range io_constraints() const; - /* Check if the data is valid: each pin can only be mapped to one net */ - bool validate() const; + public: /* Public Accessors: Basic data query */ + /* Get the pin to be constrained */ + openfpga::BasicPort io_pin(const PcfIoConstraintId& io_id) const; - public: /* Public Mutators */ - /* Reserve a number of design constraints to be memory efficent */ - void reserve_io_constraints(const size_t& num_io_constraints); + /* Get the net to be constrained */ + std::string io_net(const PcfIoConstraintId& io_id) const; - /* Add a pin constraint to storage */ - PcfIoConstraintId create_io_constraint(); + /* Check if there are any io constraints */ + bool empty() const; - /* Set the net for an io constraint */ - void set_io_net(const PcfIoConstraintId& io_id, - const std::string& net); + /* Check if the data is valid: each pin can only be mapped to one net */ + bool validate() const; - /* Set the net for an io constraint */ - void set_io_pin(const PcfIoConstraintId& io_id, - const std::string& pin); + public: /* Public Mutators */ + /* Reserve a number of design constraints to be memory efficent */ + void reserve_io_constraints(const size_t& num_io_constraints); - public: /* Public invalidators/validators */ - /* Show if the constraint id is a valid for data queries */ - bool valid_io_constraint_id(const PcfIoConstraintId& io_id) const; + /* Add a pin constraint to storage */ + PcfIoConstraintId create_io_constraint(); - private: /* Internal data */ - /* Unique ids for each design constraint */ - vtr::vector io_constraint_ids_; + /* Set the net for an io constraint */ + void set_io_net(const PcfIoConstraintId& io_id, const std::string& net); - /* Pins to constraint */ - vtr::vector io_constraint_pins_; + /* Set the net for an io constraint */ + void set_io_pin(const PcfIoConstraintId& io_id, const std::string& pin); - /* Nets to constraint */ - vtr::vector io_constraint_nets_; + public: /* Public invalidators/validators */ + /* Show if the constraint id is a valid for data queries */ + bool valid_io_constraint_id(const PcfIoConstraintId& io_id) const; + + private: /* Internal data */ + /* Unique ids for each design constraint */ + vtr::vector io_constraint_ids_; + + /* Pins to constraint */ + vtr::vector io_constraint_pins_; + + /* Nets to constraint */ + vtr::vector io_constraint_nets_; }; } /* End namespace openfpga*/ diff --git a/libs/libpcf/src/base/pcf_data_fwd.h b/libs/libpcf/src/base/pcf_data_fwd.h index 8091880ef..43cea2d0f 100644 --- a/libs/libpcf/src/base/pcf_data_fwd.h +++ b/libs/libpcf/src/base/pcf_data_fwd.h @@ -1,11 +1,11 @@ /************************************************************************ * A header file for PinConstraints class, including critical data declaration * Please include this file only for using any PinConstraints data structure - * Refer to pin_constraints.h for more details + * Refer to pin_constraints.h for more details ***********************************************************************/ /************************************************************************ - * Create strong id for PinConstraints to avoid illegal type casting + * Create strong id for PinConstraints to avoid illegal type casting ***********************************************************************/ #ifndef PCF_DATA_FWD_H #define PCF_DATA_FWD_H diff --git a/libs/libpcf/src/base/pin_constraints.cpp b/libs/libpcf/src/base/pin_constraints.cpp index bc68b3bd8..2e11ed1d6 100644 --- a/libs/libpcf/src/base/pin_constraints.cpp +++ b/libs/libpcf/src/base/pin_constraints.cpp @@ -1,10 +1,10 @@ +#include "pin_constraints.h" + #include #include "vtr_assert.h" #include "vtr_log.h" -#include "pin_constraints.h" - /************************************************************************ * Member functions for class PinConstraints ***********************************************************************/ @@ -12,37 +12,38 @@ /************************************************************************ * Constructors ***********************************************************************/ -PinConstraints::PinConstraints() { - return; -} +PinConstraints::PinConstraints() { return; } /************************************************************************ * Public Accessors : aggregates ***********************************************************************/ PinConstraints::pin_constraint_range PinConstraints::pin_constraints() const { - return vtr::make_range(pin_constraint_ids_.begin(), pin_constraint_ids_.end()); + return vtr::make_range(pin_constraint_ids_.begin(), + pin_constraint_ids_.end()); } /************************************************************************ - * Public Accessors : Basic data query + * Public Accessors : Basic data query ***********************************************************************/ -openfpga::BasicPort PinConstraints::pin(const PinConstraintId& pin_constraint_id) const { +openfpga::BasicPort PinConstraints::pin( + const PinConstraintId& pin_constraint_id) const { /* validate the pin_constraint_id */ VTR_ASSERT(valid_pin_constraint_id(pin_constraint_id)); - return pin_constraint_pins_[pin_constraint_id]; + return pin_constraint_pins_[pin_constraint_id]; } -std::string PinConstraints::net(const PinConstraintId& pin_constraint_id) const { +std::string PinConstraints::net( + const PinConstraintId& pin_constraint_id) const { /* validate the pin_constraint_id */ VTR_ASSERT(valid_pin_constraint_id(pin_constraint_id)); - return pin_constraint_nets_[pin_constraint_id]; + return pin_constraint_nets_[pin_constraint_id]; } std::string PinConstraints::pin_net(const openfpga::BasicPort& pin) const { std::string constrained_net_name; for (const PinConstraintId& pin_constraint : pin_constraints()) { if (pin == pin_constraint_pins_[pin_constraint]) { - constrained_net_name = net(pin_constraint); + constrained_net_name = net(pin_constraint); break; } } @@ -53,33 +54,37 @@ openfpga::BasicPort PinConstraints::net_pin(const std::string& net) const { openfpga::BasicPort constrained_pin; for (const PinConstraintId& pin_constraint : pin_constraints()) { if (net == pin_constraint_nets_[pin_constraint]) { - constrained_pin = pin(pin_constraint); + constrained_pin = pin(pin_constraint); break; } } return constrained_pin; -} +} -PinConstraints::e_logic_level PinConstraints::net_default_value(const std::string& net) const { +PinConstraints::e_logic_level PinConstraints::net_default_value( + const std::string& net) const { PinConstraints::e_logic_level logic_level = PinConstraints::NUM_LOGIC_LEVELS; for (const PinConstraintId& pin_constraint : pin_constraints()) { if (net == pin_constraint_nets_[pin_constraint]) { - logic_level = pin_constraint_net_default_values_[pin_constraint]; + logic_level = pin_constraint_net_default_values_[pin_constraint]; break; } } return logic_level; } -std::string PinConstraints::net_default_value_to_string(const PinConstraintId& pin_constraint) const { +std::string PinConstraints::net_default_value_to_string( + const PinConstraintId& pin_constraint) const { VTR_ASSERT(valid_pin_constraint_id(pin_constraint)); - if (PinConstraints::LOGIC_HIGH == pin_constraint_net_default_values_[pin_constraint]) { + if (PinConstraints::LOGIC_HIGH == + pin_constraint_net_default_values_[pin_constraint]) { return std::string("1"); - } else if (PinConstraints::LOGIC_LOW == pin_constraint_net_default_values_[pin_constraint]) { + } else if (PinConstraints::LOGIC_LOW == + pin_constraint_net_default_values_[pin_constraint]) { return std::string("0"); } return std::string(); -} +} size_t PinConstraints::net_default_value_to_int(const std::string& net) const { if (PinConstraints::LOGIC_HIGH == net_default_value(net)) { @@ -88,51 +93,56 @@ size_t PinConstraints::net_default_value_to_int(const std::string& net) const { return 0; } return -1; -} - -bool PinConstraints::empty() const { - return 0 == pin_constraint_ids_.size(); } +bool PinConstraints::empty() const { return 0 == pin_constraint_ids_.size(); } + /************************************************************************ * Public Mutators ***********************************************************************/ -void PinConstraints::reserve_pin_constraints(const size_t& num_pin_constraints) { +void PinConstraints::reserve_pin_constraints( + const size_t& num_pin_constraints) { pin_constraint_ids_.reserve(num_pin_constraints); pin_constraint_pins_.reserve(num_pin_constraints); pin_constraint_nets_.reserve(num_pin_constraints); pin_constraint_net_default_values_.reserve(num_pin_constraints); } -PinConstraintId PinConstraints::create_pin_constraint(const openfpga::BasicPort& pin, - const std::string& net) { +PinConstraintId PinConstraints::create_pin_constraint( + const openfpga::BasicPort& pin, const std::string& net) { /* Create a new id */ - PinConstraintId pin_constraint_id = PinConstraintId(pin_constraint_ids_.size()); - + PinConstraintId pin_constraint_id = + PinConstraintId(pin_constraint_ids_.size()); + pin_constraint_ids_.push_back(pin_constraint_id); pin_constraint_pins_.push_back(pin); pin_constraint_nets_.push_back(net); - pin_constraint_net_default_values_.push_back(PinConstraints::NUM_LOGIC_LEVELS); - + pin_constraint_net_default_values_.push_back( + PinConstraints::NUM_LOGIC_LEVELS); + return pin_constraint_id; } -void PinConstraints::set_net_default_value(const PinConstraintId& pin_constraint, - const std::string& default_value) { +void PinConstraints::set_net_default_value( + const PinConstraintId& pin_constraint, const std::string& default_value) { VTR_ASSERT(valid_pin_constraint_id(pin_constraint)); if (default_value == std::string("1")) { - pin_constraint_net_default_values_[pin_constraint] = PinConstraints::LOGIC_HIGH; + pin_constraint_net_default_values_[pin_constraint] = + PinConstraints::LOGIC_HIGH; } else if (default_value == std::string("0")) { - pin_constraint_net_default_values_[pin_constraint] = PinConstraints::LOGIC_LOW; + pin_constraint_net_default_values_[pin_constraint] = + PinConstraints::LOGIC_LOW; } } /************************************************************************ - * Internal invalidators/validators + * Internal invalidators/validators ***********************************************************************/ /* Validators */ -bool PinConstraints::valid_pin_constraint_id(const PinConstraintId& pin_constraint_id) const { - return ( size_t(pin_constraint_id) < pin_constraint_ids_.size() ) && ( pin_constraint_id == pin_constraint_ids_[pin_constraint_id] ); +bool PinConstraints::valid_pin_constraint_id( + const PinConstraintId& pin_constraint_id) const { + return (size_t(pin_constraint_id) < pin_constraint_ids_.size()) && + (pin_constraint_id == pin_constraint_ids_[pin_constraint_id]); } bool PinConstraints::unconstrained_net(const std::string& net) const { @@ -143,11 +153,13 @@ bool PinConstraints::unmapped_net(const std::string& net) const { return std::string(PIN_CONSTRAINT_OPEN_NET) == net; } -bool PinConstraints::valid_net_default_value(const PinConstraintId& pin_constraint) const { +bool PinConstraints::valid_net_default_value( + const PinConstraintId& pin_constraint) const { VTR_ASSERT(valid_pin_constraint_id(pin_constraint)); - return PinConstraints::NUM_LOGIC_LEVELS != pin_constraint_net_default_values_[pin_constraint]; + return PinConstraints::NUM_LOGIC_LEVELS != + pin_constraint_net_default_values_[pin_constraint]; } bool PinConstraints::valid_net_default_value(const std::string& net) const { - return PinConstraints::NUM_LOGIC_LEVELS != net_default_value(net); + return PinConstraints::NUM_LOGIC_LEVELS != net_default_value(net); } diff --git a/libs/libpcf/src/base/pin_constraints.h b/libs/libpcf/src/base/pin_constraints.h index a7af227cb..896804736 100644 --- a/libs/libpcf/src/base/pin_constraints.h +++ b/libs/libpcf/src/base/pin_constraints.h @@ -4,17 +4,16 @@ /******************************************************************** * This file include the declaration of pin constraints *******************************************************************/ -#include -#include #include +#include +#include /* Headers from vtrutil library */ -#include "vtr_vector.h" #include "vtr_geometry.h" +#include "vtr_vector.h" /* Headers from openfpgautil library */ #include "openfpga_port.h" - #include "pin_constraints_fwd.h" /* Constants */ @@ -33,111 +32,117 @@ constexpr const char* PIN_CONSTRAINT_OPEN_NET = "OPEN"; * // Add a pin assignment * openfpga::BasicPort pin_info(clk, 1); * std::string net_info("top_clock"); - * PinConstraintId pin_constraint_id = pin_constraints.create_pin_constraint(pin_info, net_info); + * PinConstraintId pin_constraint_id = + *pin_constraints.create_pin_constraint(pin_info, net_info); * *******************************************************************/ class PinConstraints { - public: /* Types */ - typedef vtr::vector::const_iterator pin_constraint_iterator; - /* Create range */ - typedef vtr::Range pin_constraint_range; - /* Logic value */ - enum e_logic_level { - LOGIC_HIGH, - LOGIC_LOW, - NUM_LOGIC_LEVELS - }; - public: /* Constructors */ - PinConstraints(); - public: /* Accessors: aggregates */ - pin_constraint_range pin_constraints() const; - public: /* Public Accessors: Basic data query */ - /* Get the pin to be constrained */ - openfpga::BasicPort pin(const PinConstraintId& pin_constraint_id) const; + public: /* Types */ + typedef vtr::vector::const_iterator + pin_constraint_iterator; + /* Create range */ + typedef vtr::Range pin_constraint_range; + /* Logic value */ + enum e_logic_level { LOGIC_HIGH, LOGIC_LOW, NUM_LOGIC_LEVELS }; - /* Get the net to be constrained */ - std::string net(const PinConstraintId& pin_constraint_id) const; + public: /* Constructors */ + PinConstraints(); - /* Find the net that is constrained on a pin - * TODO: this function will only return the first net found in the constraint list - */ - std::string pin_net(const openfpga::BasicPort& pin) const; + public: /* Accessors: aggregates */ + pin_constraint_range pin_constraints() const; - /* Find the pin that a net is constrained to - * If not found, the return port will be an invalid BasicPort - * TODO: this function will only return the first pin found in the constraint list - */ - openfpga::BasicPort net_pin(const std::string& net) const; + public: /* Public Accessors: Basic data query */ + /* Get the pin to be constrained */ + openfpga::BasicPort pin(const PinConstraintId& pin_constraint_id) const; - /* Find the default value that a net is constrained to - * If not found, return an invalid value - */ - e_logic_level net_default_value(const std::string& net) const; + /* Get the net to be constrained */ + std::string net(const PinConstraintId& pin_constraint_id) const; - /* Generate the string of the default value - * If not found, return an empty string - */ - std::string net_default_value_to_string(const PinConstraintId& pin_constraint) const; + /* Find the net that is constrained on a pin + * TODO: this function will only return the first net found in the constraint + * list + */ + std::string pin_net(const openfpga::BasicPort& pin) const; - /* Generate the integer representation of the default value - * If not found, return -1 - */ - size_t net_default_value_to_int(const std::string& net) const; + /* Find the pin that a net is constrained to + * If not found, the return port will be an invalid BasicPort + * TODO: this function will only return the first pin found in the constraint + * list + */ + openfpga::BasicPort net_pin(const std::string& net) const; - /* Check if there are any pin constraints */ - bool empty() const; + /* Find the default value that a net is constrained to + * If not found, return an invalid value + */ + e_logic_level net_default_value(const std::string& net) const; - public: /* Public Mutators */ - /* Reserve a number of design constraints to be memory efficent */ - void reserve_pin_constraints(const size_t& num_pin_constraints); + /* Generate the string of the default value + * If not found, return an empty string + */ + std::string net_default_value_to_string( + const PinConstraintId& pin_constraint) const; - /* Add a pin constraint to storage */ - PinConstraintId create_pin_constraint(const openfpga::BasicPort& pin, - const std::string& net); + /* Generate the integer representation of the default value + * If not found, return -1 + */ + size_t net_default_value_to_int(const std::string& net) const; - /* Set the default value for the net under a given pin constraint */ - void set_net_default_value(const PinConstraintId& pin_constraint, - const std::string& default_value); + /* Check if there are any pin constraints */ + bool empty() const; - public: /* Public invalidators/validators */ - /* Show if the pin constraint id is a valid for data queries */ - bool valid_pin_constraint_id(const PinConstraintId& pin_constraint_id) const; + public: /* Public Mutators */ + /* Reserve a number of design constraints to be memory efficent */ + void reserve_pin_constraints(const size_t& num_pin_constraints); - /* Show if the net has no constraints (free to map to any pin) - * This function is used to identify the net name returned by APIs: - * - pin_net() - * - net() - */ - bool unconstrained_net(const std::string& net) const; + /* Add a pin constraint to storage */ + PinConstraintId create_pin_constraint(const openfpga::BasicPort& pin, + const std::string& net); - /* Show if the net is defined specifically not to map to any pin - * This function is used to identify the net name returned by APIs: - * - pin_net() - * - net() - */ - bool unmapped_net(const std::string& net) const; + /* Set the default value for the net under a given pin constraint */ + void set_net_default_value(const PinConstraintId& pin_constraint, + const std::string& default_value); - /* Check if default value is a valid one or not - * This is to check if the default value is constrained or not - */ - bool valid_net_default_value(const PinConstraintId& pin_constraint) const; + public: /* Public invalidators/validators */ + /* Show if the pin constraint id is a valid for data queries */ + bool valid_pin_constraint_id(const PinConstraintId& pin_constraint_id) const; - /* Check if default value is a valid one or not - * This is to check if the default value is constrained or not - */ - bool valid_net_default_value(const std::string& net) const; - private: /* Internal data */ - /* Unique ids for each design constraint */ - vtr::vector pin_constraint_ids_; + /* Show if the net has no constraints (free to map to any pin) + * This function is used to identify the net name returned by APIs: + * - pin_net() + * - net() + */ + bool unconstrained_net(const std::string& net) const; - /* Pins to constraint */ - vtr::vector pin_constraint_pins_; + /* Show if the net is defined specifically not to map to any pin + * This function is used to identify the net name returned by APIs: + * - pin_net() + * - net() + */ + bool unmapped_net(const std::string& net) const; - /* Nets to constraint */ - vtr::vector pin_constraint_nets_; + /* Check if default value is a valid one or not + * This is to check if the default value is constrained or not + */ + bool valid_net_default_value(const PinConstraintId& pin_constraint) const; - /* Default value of the nets to constraint */ - vtr::vector pin_constraint_net_default_values_; + /* Check if default value is a valid one or not + * This is to check if the default value is constrained or not + */ + bool valid_net_default_value(const std::string& net) const; + + private: /* Internal data */ + /* Unique ids for each design constraint */ + vtr::vector pin_constraint_ids_; + + /* Pins to constraint */ + vtr::vector pin_constraint_pins_; + + /* Nets to constraint */ + vtr::vector pin_constraint_nets_; + + /* Default value of the nets to constraint */ + vtr::vector + pin_constraint_net_default_values_; }; #endif diff --git a/libs/libpcf/src/base/pin_constraints_fwd.h b/libs/libpcf/src/base/pin_constraints_fwd.h index 245e72ff3..88e807ca9 100644 --- a/libs/libpcf/src/base/pin_constraints_fwd.h +++ b/libs/libpcf/src/base/pin_constraints_fwd.h @@ -1,11 +1,11 @@ /************************************************************************ * A header file for PinConstraints class, including critical data declaration * Please include this file only for using any PinConstraints data structure - * Refer to pin_constraints.h for more details + * Refer to pin_constraints.h for more details ***********************************************************************/ /************************************************************************ - * Create strong id for PinConstraints to avoid illegal type casting + * Create strong id for PinConstraints to avoid illegal type casting ***********************************************************************/ #ifndef PIN_CONSTRAINTS_FWD_H #define PIN_CONSTRAINTS_FWD_H diff --git a/libs/libpcf/src/base/repack_design_constraints.cpp b/libs/libpcf/src/base/repack_design_constraints.cpp index c32ad6bb3..8e6fb52ac 100644 --- a/libs/libpcf/src/base/repack_design_constraints.cpp +++ b/libs/libpcf/src/base/repack_design_constraints.cpp @@ -1,10 +1,10 @@ +#include "repack_design_constraints.h" + #include #include "vtr_assert.h" #include "vtr_log.h" -#include "repack_design_constraints.h" - /************************************************************************ * Member functions for class RepackDesignConstraints ***********************************************************************/ @@ -12,51 +12,56 @@ /************************************************************************ * Constructors ***********************************************************************/ -RepackDesignConstraints::RepackDesignConstraints() { - return; -} +RepackDesignConstraints::RepackDesignConstraints() { return; } /************************************************************************ * Public Accessors : aggregates ***********************************************************************/ -RepackDesignConstraints::repack_design_constraint_range RepackDesignConstraints::design_constraints() const { - return vtr::make_range(repack_design_constraint_ids_.begin(), repack_design_constraint_ids_.end()); +RepackDesignConstraints::repack_design_constraint_range +RepackDesignConstraints::design_constraints() const { + return vtr::make_range(repack_design_constraint_ids_.begin(), + repack_design_constraint_ids_.end()); } /************************************************************************ - * Public Accessors : Basic data query + * Public Accessors : Basic data query ***********************************************************************/ -RepackDesignConstraints::e_design_constraint_type RepackDesignConstraints::type(const RepackDesignConstraintId& repack_design_constraint_id) const { +RepackDesignConstraints::e_design_constraint_type RepackDesignConstraints::type( + const RepackDesignConstraintId& repack_design_constraint_id) const { /* validate the design_constraint_id */ VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id)); - return repack_design_constraint_types_[repack_design_constraint_id]; + return repack_design_constraint_types_[repack_design_constraint_id]; } -std::string RepackDesignConstraints::pb_type(const RepackDesignConstraintId& repack_design_constraint_id) const { +std::string RepackDesignConstraints::pb_type( + const RepackDesignConstraintId& repack_design_constraint_id) const { /* validate the design_constraint_id */ VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id)); - return repack_design_constraint_pb_types_[repack_design_constraint_id]; + return repack_design_constraint_pb_types_[repack_design_constraint_id]; } -openfpga::BasicPort RepackDesignConstraints::pin(const RepackDesignConstraintId& repack_design_constraint_id) const { +openfpga::BasicPort RepackDesignConstraints::pin( + const RepackDesignConstraintId& repack_design_constraint_id) const { /* validate the design_constraint_id */ VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id)); - return repack_design_constraint_pins_[repack_design_constraint_id]; + return repack_design_constraint_pins_[repack_design_constraint_id]; } -std::string RepackDesignConstraints::net(const RepackDesignConstraintId& repack_design_constraint_id) const { +std::string RepackDesignConstraints::net( + const RepackDesignConstraintId& repack_design_constraint_id) const { /* validate the design_constraint_id */ VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id)); - return repack_design_constraint_nets_[repack_design_constraint_id]; + return repack_design_constraint_nets_[repack_design_constraint_id]; } -std::string RepackDesignConstraints::find_constrained_pin_net(const std::string& pb_type, - const openfpga::BasicPort& pin) const { +std::string RepackDesignConstraints::find_constrained_pin_net( + const std::string& pb_type, const openfpga::BasicPort& pin) const { std::string constrained_net_name; - for (const RepackDesignConstraintId& design_constraint : design_constraints()) { + for (const RepackDesignConstraintId& design_constraint : + design_constraints()) { /* If found a constraint, record the net name */ - if ( (pb_type == repack_design_constraint_pb_types_[design_constraint]) - && (pin == repack_design_constraint_pins_[design_constraint])) { + if ((pb_type == repack_design_constraint_pb_types_[design_constraint]) && + (pin == repack_design_constraint_pins_[design_constraint])) { constrained_net_name = repack_design_constraint_nets_[design_constraint]; break; } @@ -71,7 +76,8 @@ bool RepackDesignConstraints::empty() const { /************************************************************************ * Public Mutators ***********************************************************************/ -void RepackDesignConstraints::reserve_design_constraints(const size_t& num_design_constraints) { +void RepackDesignConstraints::reserve_design_constraints( + const size_t& num_design_constraints) { repack_design_constraint_ids_.reserve(num_design_constraints); repack_design_constraint_types_.reserve(num_design_constraints); repack_design_constraint_pb_types_.reserve(num_design_constraints); @@ -79,46 +85,56 @@ void RepackDesignConstraints::reserve_design_constraints(const size_t& num_desig repack_design_constraint_nets_.reserve(num_design_constraints); } -RepackDesignConstraintId RepackDesignConstraints::create_design_constraint(const RepackDesignConstraints::e_design_constraint_type& repack_design_constraint_type) { +RepackDesignConstraintId RepackDesignConstraints::create_design_constraint( + const RepackDesignConstraints::e_design_constraint_type& + repack_design_constraint_type) { /* Create a new id */ - RepackDesignConstraintId repack_design_constraint_id = RepackDesignConstraintId(repack_design_constraint_ids_.size()); - + RepackDesignConstraintId repack_design_constraint_id = + RepackDesignConstraintId(repack_design_constraint_ids_.size()); + repack_design_constraint_ids_.push_back(repack_design_constraint_id); repack_design_constraint_types_.push_back(repack_design_constraint_type); repack_design_constraint_pb_types_.emplace_back(); repack_design_constraint_pins_.emplace_back(); repack_design_constraint_nets_.emplace_back(); - + return repack_design_constraint_id; } -void RepackDesignConstraints::set_pb_type(const RepackDesignConstraintId& repack_design_constraint_id, - const std::string& pb_type) { +void RepackDesignConstraints::set_pb_type( + const RepackDesignConstraintId& repack_design_constraint_id, + const std::string& pb_type) { /* validate the design_constraint_id */ VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id)); repack_design_constraint_pb_types_[repack_design_constraint_id] = pb_type; } -void RepackDesignConstraints::set_pin(const RepackDesignConstraintId& repack_design_constraint_id, - const openfpga::BasicPort& pin) { +void RepackDesignConstraints::set_pin( + const RepackDesignConstraintId& repack_design_constraint_id, + const openfpga::BasicPort& pin) { /* validate the design_constraint_id */ VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id)); repack_design_constraint_pins_[repack_design_constraint_id] = pin; } -void RepackDesignConstraints::set_net(const RepackDesignConstraintId& repack_design_constraint_id, - const std::string& net) { +void RepackDesignConstraints::set_net( + const RepackDesignConstraintId& repack_design_constraint_id, + const std::string& net) { /* validate the design_constraint_id */ VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id)); repack_design_constraint_nets_[repack_design_constraint_id] = net; } /************************************************************************ - * Internal invalidators/validators + * Internal invalidators/validators ***********************************************************************/ /* Validators */ -bool RepackDesignConstraints::valid_design_constraint_id(const RepackDesignConstraintId& design_constraint_id) const { - return ( size_t(design_constraint_id) < repack_design_constraint_ids_.size() ) && ( design_constraint_id == repack_design_constraint_ids_[design_constraint_id] ); +bool RepackDesignConstraints::valid_design_constraint_id( + const RepackDesignConstraintId& design_constraint_id) const { + return (size_t(design_constraint_id) < + repack_design_constraint_ids_.size()) && + (design_constraint_id == + repack_design_constraint_ids_[design_constraint_id]); } bool RepackDesignConstraints::unconstrained_net(const std::string& net) const { diff --git a/libs/libpcf/src/base/repack_design_constraints.h b/libs/libpcf/src/base/repack_design_constraints.h index 6f6881aa0..35c5a8a1a 100644 --- a/libs/libpcf/src/base/repack_design_constraints.h +++ b/libs/libpcf/src/base/repack_design_constraints.h @@ -4,17 +4,16 @@ /******************************************************************** * This file include the declaration of repack design constraints *******************************************************************/ -#include -#include #include +#include +#include /* Headers from vtrutil library */ -#include "vtr_vector.h" #include "vtr_geometry.h" +#include "vtr_vector.h" /* Headers from openfpgautil library */ #include "openfpga_port.h" - #include "repack_design_constraints_fwd.h" /* Constants */ @@ -31,94 +30,109 @@ constexpr const char* REPACK_DESIGN_CONSTRAINT_OPEN_NET = "OPEN"; * // Create an object of design constraints * RepackDesignConstraints repack_design_constraints; * // Add a pin assignment - * RepackDesignConstraintId repack_dc_id = fabric_key.create_design_constraint(RepackDesignConstraints::PIN_ASSIGNMENT); + * RepackDesignConstraintId repack_dc_id = + *fabric_key.create_design_constraint(RepackDesignConstraints::PIN_ASSIGNMENT); * *******************************************************************/ class RepackDesignConstraints { - public: /* Type of design constraints */ - enum e_design_constraint_type { - PIN_ASSIGNMENT, - NUM_DESIGN_CONSTRAINT_TYPES - }; - public: /* Types */ - typedef vtr::vector::const_iterator repack_design_constraint_iterator; - /* Create range */ - typedef vtr::Range repack_design_constraint_range; - public: /* Constructors */ - RepackDesignConstraints(); - public: /* Accessors: aggregates */ - repack_design_constraint_range design_constraints() const; - public: /* Public Accessors: Basic data query */ - /* Get the type of constraint */ - e_design_constraint_type type(const RepackDesignConstraintId& repack_design_constraint_id) const; + public: /* Type of design constraints */ + enum e_design_constraint_type { PIN_ASSIGNMENT, NUM_DESIGN_CONSTRAINT_TYPES }; - /* Get the pb_type name to be constrained */ - std::string pb_type(const RepackDesignConstraintId& repack_design_constraint_id) const; + public: /* Types */ + typedef vtr::vector::const_iterator + repack_design_constraint_iterator; + /* Create range */ + typedef vtr::Range + repack_design_constraint_range; - /* Get the pin to be constrained */ - openfpga::BasicPort pin(const RepackDesignConstraintId& repack_design_constraint_id) const; + public: /* Constructors */ + RepackDesignConstraints(); - /* Get the net to be constrained */ - std::string net(const RepackDesignConstraintId& repack_design_constraint_id) const; + public: /* Accessors: aggregates */ + repack_design_constraint_range design_constraints() const; - /* Find a constrained net */ - std::string find_constrained_pin_net(const std::string& pb_type, - const openfpga::BasicPort& pin) const; + public: /* Public Accessors: Basic data query */ + /* Get the type of constraint */ + e_design_constraint_type type( + const RepackDesignConstraintId& repack_design_constraint_id) const; - /* Check if there are any design constraints */ - bool empty() const; + /* Get the pb_type name to be constrained */ + std::string pb_type( + const RepackDesignConstraintId& repack_design_constraint_id) const; - public: /* Public Mutators */ + /* Get the pin to be constrained */ + openfpga::BasicPort pin( + const RepackDesignConstraintId& repack_design_constraint_id) const; - /* Reserve a number of design constraints to be memory efficent */ - void reserve_design_constraints(const size_t& num_design_constraints); + /* Get the net to be constrained */ + std::string net( + const RepackDesignConstraintId& repack_design_constraint_id) const; - /* Add a design constraint to storage */ - RepackDesignConstraintId create_design_constraint(const e_design_constraint_type& repack_design_constraint_type); + /* Find a constrained net */ + std::string find_constrained_pin_net(const std::string& pb_type, + const openfpga::BasicPort& pin) const; - /* Set the pb_type name to be constrained */ - void set_pb_type(const RepackDesignConstraintId& repack_design_constraint_id, - const std::string& pb_type); + /* Check if there are any design constraints */ + bool empty() const; - /* Set the pin to be constrained */ - void set_pin(const RepackDesignConstraintId& repack_design_constraint_id, - const openfpga::BasicPort& pin); + public: /* Public Mutators */ + /* Reserve a number of design constraints to be memory efficent */ + void reserve_design_constraints(const size_t& num_design_constraints); - /* Set the net to be constrained */ - void set_net(const RepackDesignConstraintId& repack_design_constraint_id, - const std::string& net); + /* Add a design constraint to storage */ + RepackDesignConstraintId create_design_constraint( + const e_design_constraint_type& repack_design_constraint_type); - public: /* Public invalidators/validators */ - bool valid_design_constraint_id(const RepackDesignConstraintId& repack_design_constraint_id) const; - /* Show if the net has no constraints (free to map to any pin) - * This function is used to identify the net name returned by APIs: - * - find_constrained_pin_net() - * - net() - */ - bool unconstrained_net(const std::string& net) const; + /* Set the pb_type name to be constrained */ + void set_pb_type(const RepackDesignConstraintId& repack_design_constraint_id, + const std::string& pb_type); - /* Show if the net is defined specifically not to map to any pin - * This function is used to identify the net name returned by APIs: - * - find_constrained_pin_net() - * - net() - */ - bool unmapped_net(const std::string& net) const; + /* Set the pin to be constrained */ + void set_pin(const RepackDesignConstraintId& repack_design_constraint_id, + const openfpga::BasicPort& pin); - private: /* Internal data */ - /* Unique ids for each design constraint */ - vtr::vector repack_design_constraint_ids_; + /* Set the net to be constrained */ + void set_net(const RepackDesignConstraintId& repack_design_constraint_id, + const std::string& net); - /* Type for each design constraint */ - vtr::vector repack_design_constraint_types_; + public: /* Public invalidators/validators */ + bool valid_design_constraint_id( + const RepackDesignConstraintId& repack_design_constraint_id) const; + /* Show if the net has no constraints (free to map to any pin) + * This function is used to identify the net name returned by APIs: + * - find_constrained_pin_net() + * - net() + */ + bool unconstrained_net(const std::string& net) const; - /* Tiles to constraint */ - vtr::vector repack_design_constraint_pb_types_; + /* Show if the net is defined specifically not to map to any pin + * This function is used to identify the net name returned by APIs: + * - find_constrained_pin_net() + * - net() + */ + bool unmapped_net(const std::string& net) const; - /* Pins to constraint */ - vtr::vector repack_design_constraint_pins_; + private: /* Internal data */ + /* Unique ids for each design constraint */ + vtr::vector + repack_design_constraint_ids_; - /* Nets to constraint */ - vtr::vector repack_design_constraint_nets_; + /* Type for each design constraint */ + vtr::vector + repack_design_constraint_types_; + + /* Tiles to constraint */ + vtr::vector + repack_design_constraint_pb_types_; + + /* Pins to constraint */ + vtr::vector + repack_design_constraint_pins_; + + /* Nets to constraint */ + vtr::vector + repack_design_constraint_nets_; }; #endif diff --git a/libs/libpcf/src/base/repack_design_constraints_fwd.h b/libs/libpcf/src/base/repack_design_constraints_fwd.h index 9216a30b0..dfab4eda1 100644 --- a/libs/libpcf/src/base/repack_design_constraints_fwd.h +++ b/libs/libpcf/src/base/repack_design_constraints_fwd.h @@ -1,11 +1,11 @@ /************************************************************************ - * A header file for RepackDesignConstraints class, including critical data declaration - * Please include this file only for using any TechnologyLibrary data structure - * Refer to repack_design_constraints.h for more details + * A header file for RepackDesignConstraints class, including critical data + *declaration Please include this file only for using any TechnologyLibrary data + *structure Refer to repack_design_constraints.h for more details ***********************************************************************/ /************************************************************************ - * Create strong id for RepackDesignConstraints to avoid illegal type casting + * Create strong id for RepackDesignConstraints to avoid illegal type casting ***********************************************************************/ #ifndef REPACK_DESIGN_CONSTRAINTS_FWD_H #define REPACK_DESIGN_CONSTRAINTS_FWD_H diff --git a/libs/libpcf/src/io/blif_head_reader.cpp b/libs/libpcf/src/io/blif_head_reader.cpp index 02bfc1fbc..e74657439 100644 --- a/libs/libpcf/src/io/blif_head_reader.cpp +++ b/libs/libpcf/src/io/blif_head_reader.cpp @@ -1,16 +1,16 @@ -#include -#include - #include "blif_head_reader.h" +#include +#include + namespace blifparse { void BlifHeadReader::start_parse() { - //Pass + // Pass } void BlifHeadReader::finish_parse() { - //Pass + // Pass } void BlifHeadReader::begin_model(std::string model_name) { @@ -25,15 +25,19 @@ void BlifHeadReader::outputs(std::vector output_conns) { output_pins_ = output_conns; } -void BlifHeadReader::names(std::vector nets, std::vector> so_cover) { +void BlifHeadReader::names(std::vector nets, + std::vector> so_cover) { // Pass } -void BlifHeadReader::latch(std::string input, std::string output, LatchType type, std::string control, LogicValue init) { +void BlifHeadReader::latch(std::string input, std::string output, + LatchType type, std::string control, + LogicValue init) { // Pass } -void BlifHeadReader::subckt(std::string model, std::vector ports, std::vector nets) { +void BlifHeadReader::subckt(std::string model, std::vector ports, + std::vector nets) { // Pass } @@ -69,4 +73,4 @@ void BlifHeadReader::lineno(int line_num) { // Pass } -} +} // namespace blifparse diff --git a/libs/libpcf/src/io/blif_head_reader.h b/libs/libpcf/src/io/blif_head_reader.h index 7fe58c98d..772785f1c 100644 --- a/libs/libpcf/src/io/blif_head_reader.h +++ b/libs/libpcf/src/io/blif_head_reader.h @@ -1,54 +1,60 @@ #ifndef BLIF_HEAD_READER #define BLIF_HEAD_READER #include + #include "blifparse.hpp" #include "vtr_log.h" namespace blifparse { -//An example callback which pretty-prints to stdout -//the BLIF which is being parsed +// An example callback which pretty-prints to stdout +// the BLIF which is being parsed class BlifHeadReader : public Callback { - public: - void start_parse() override; - void filename(std::string fname) override; - void lineno(int line_num) override; - void begin_model(std::string model_name) override; - void inputs(std::vector inputs) override; - void outputs(std::vector outputs) override; + public: + void start_parse() override; + void filename(std::string fname) override; + void lineno(int line_num) override; + void begin_model(std::string model_name) override; + void inputs(std::vector inputs) override; + void outputs(std::vector outputs) override; - void names(std::vector nets, std::vector> so_cover) override; + void names(std::vector nets, + std::vector> so_cover) override; - void latch(std::string input, std::string output, LatchType type, std::string control, LogicValue init) override; + void latch(std::string input, std::string output, LatchType type, + std::string control, LogicValue init) override; - void subckt(std::string model, std::vector ports, std::vector nets) override; + void subckt(std::string model, std::vector ports, + std::vector nets) override; - void blackbox() override; + void blackbox() override; - void end_model() override; + void end_model() override; - //BLIF Extensions - void conn(std::string src, std::string dst) override; - void cname(std::string cell_name) override; - void attr(std::string name, std::string value) override; - void param(std::string name, std::string value) override; + // BLIF Extensions + void conn(std::string src, std::string dst) override; + void cname(std::string cell_name) override; + void attr(std::string name, std::string value) override; + void param(std::string name, std::string value) override; - void finish_parse() override; + void finish_parse() override; - void parse_error(const int curr_lineno, const std::string& near_text, const std::string& msg) override { - VTR_LOG_ERROR("Error when parsing .blif at line %d near '%s': %s\n", curr_lineno, near_text.c_str(), msg.c_str()); - had_error_ = true; - } - - bool had_error() { return had_error_; } - std::vector input_pins() { return input_pins_; } - std::vector output_pins() { return output_pins_; } + void parse_error(const int curr_lineno, const std::string& near_text, + const std::string& msg) override { + VTR_LOG_ERROR("Error when parsing .blif at line %d near '%s': %s\n", + curr_lineno, near_text.c_str(), msg.c_str()); + had_error_ = true; + } - private: - std::vector input_pins_; - std::vector output_pins_; - bool had_error_ = false; + bool had_error() { return had_error_; } + std::vector input_pins() { return input_pins_; } + std::vector output_pins() { return output_pins_; } + + private: + std::vector input_pins_; + std::vector output_pins_; + bool had_error_ = false; }; -} +} // namespace blifparse #endif diff --git a/libs/libpcf/src/io/pcf_reader.cpp b/libs/libpcf/src/io/pcf_reader.cpp index 63dc06ebd..8c2e70341 100644 --- a/libs/libpcf/src/io/pcf_reader.cpp +++ b/libs/libpcf/src/io/pcf_reader.cpp @@ -4,13 +4,12 @@ #include /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgautil library */ #include "openfpga_digest.h" - #include "pcf_reader.h" /* begin namespace openfpga */ @@ -28,8 +27,7 @@ constexpr const char COMMENT = '#'; * Return 1 if there are serious errors when parsing data * Return 2 if fail when opening files *******************************************************************/ -int read_pcf(const char* fname, - PcfData& pcf_data) { +int read_pcf(const char* fname, PcfData& pcf_data) { vtr::ScopedStartFinishTimer timer("Read " + std::string(fname)); /* Create a file handler */ @@ -37,7 +35,7 @@ int read_pcf(const char* fname, if (!fp.is_open()) { VTR_LOG_ERROR("Fail to open pcf file '%s'!", fname); return 2; - } + } int num_err = 0; @@ -54,16 +52,17 @@ int read_pcf(const char* fname, std::string pin_name; ss >> net_name >> pin_name; /* Decode data */ - PcfIoConstraintId io_id = pcf_data.create_io_constraint(); + PcfIoConstraintId io_id = pcf_data.create_io_constraint(); pcf_data.set_io_net(io_id, net_name); pcf_data.set_io_pin(io_id, pin_name); - } else if (word[0] == COMMENT) { // if it's a comment - break; //or ignore the full line comment and move on + } else if (word[0] == COMMENT) { // if it's a comment + break; // or ignore the full line comment and move on } else { /* Reach unknown command, error out */ VTR_LOG_ERROR("Unknown command '%s'!\n", word.c_str()); num_err++; - break; //and move onto next line. without this, it will accept more following values on this line + break; // and move onto next line. without this, it will accept more + // following values on this line } } } diff --git a/libs/libpcf/src/io/pcf_reader.h b/libs/libpcf/src/io/pcf_reader.h index 000b69c0c..347a50b68 100644 --- a/libs/libpcf/src/io/pcf_reader.h +++ b/libs/libpcf/src/io/pcf_reader.h @@ -4,17 +4,19 @@ * Include header files required by the data structure definition *******************************************************************/ #include + #include -#include #include +#include + #include "pcf_data.h" /* Begin namespace openfpga */ namespace openfpga { -/* Parse a .pcf file through a stream, return an object which contains all the data */ -int read_pcf(const char* fname, - PcfData& pcf_data); +/* Parse a .pcf file through a stream, return an object which contains all the + * data */ +int read_pcf(const char* fname, PcfData& pcf_data); } /* End namespace openfpga*/ diff --git a/libs/libpcf/src/io/pcf_writer.cpp b/libs/libpcf/src/io/pcf_writer.cpp index db8ef69c4..0499c2089 100644 --- a/libs/libpcf/src/io/pcf_writer.cpp +++ b/libs/libpcf/src/io/pcf_writer.cpp @@ -4,16 +4,15 @@ #include /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgautil library */ #include "openfpga_digest.h" /* Headers from arch openfpga library */ -#include "write_xml_utils.h" - #include "pcf_writer.h" +#include "write_xml_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -30,8 +29,7 @@ constexpr const char* CMD_SET_IO = "set_io"; * Return 1 if there are serious errors when parsing data * Return 2 if fail when opening files *******************************************************************/ -int write_pcf(const char* fname, - const PcfData& pcf_data) { +int write_pcf(const char* fname, const PcfData& pcf_data) { vtr::ScopedStartFinishTimer timer("Write " + std::string(fname)); /* Create a file handler */ @@ -41,9 +39,9 @@ int write_pcf(const char* fname, /* Write from data */ for (const PcfIoConstraintId& io_id : pcf_data.io_constraints()) { - fp << CMD_SET_IO << " "; - fp << pcf_data.io_net(io_id).c_str() << " "; - fp << generate_xml_port_name(pcf_data.io_pin(io_id)).c_str() << "\n"; + fp << CMD_SET_IO << " "; + fp << pcf_data.io_net(io_id).c_str() << " "; + fp << generate_xml_port_name(pcf_data.io_pin(io_id)).c_str() << "\n"; } return 0; diff --git a/libs/libpcf/src/io/pcf_writer.h b/libs/libpcf/src/io/pcf_writer.h index 4d7551efc..015a01b0f 100644 --- a/libs/libpcf/src/io/pcf_writer.h +++ b/libs/libpcf/src/io/pcf_writer.h @@ -4,18 +4,19 @@ * Include header files required by the data structure definition *******************************************************************/ #include + #include -#include #include +#include + #include "pcf_data.h" /* Begin namespace openfpga */ namespace openfpga { /* Write a .pcf file from an object */ -int write_pcf(const char* fname, - const PcfData& pcf_data); - +int write_pcf(const char* fname, const PcfData& pcf_data); + } /* End namespace openfpga*/ #endif diff --git a/libs/libpcf/src/io/rapidcsv.h b/libs/libpcf/src/io/rapidcsv.h index f8fb66630..a76f95252 100644 --- a/libs/libpcf/src/io/rapidcsv.h +++ b/libs/libpcf/src/io/rapidcsv.h @@ -7,7 +7,8 @@ * Copyright (C) 2017-2022 Kristofer Berggren * All rights reserved. * - * rapidcsv is distributed under the BSD 3-Clause license, see LICENSE for details. + * rapidcsv is distributed under the BSD 3-Clause license, see LICENSE for + * details. * */ @@ -34,1767 +35,1589 @@ typedef SSIZE_T ssize_t; #endif -namespace rapidcsv -{ +namespace rapidcsv { #if defined(_MSC_VER) - static const bool sPlatformHasCR = true; +static const bool sPlatformHasCR = true; #else - static const bool sPlatformHasCR = false; +static const bool sPlatformHasCR = false; #endif +/** + * @brief Datastructure holding parameters controlling how invalid numbers + * (including empty strings) should be handled. + */ +struct ConverterParams { /** - * @brief Datastructure holding parameters controlling how invalid numbers (including - * empty strings) should be handled. + * @brief Constructor + * @param pHasDefaultConverter specifies if conversion of non-numerical + * strings shall be converted to a default numerical value, instead of causing + * an exception to be thrown (default). + * @param pDefaultFloat floating-point default value to represent + * invalid numbers. + * @param pDefaultInteger integer default value to represent invalid + * numbers. + * @param pNumericLocale specifies whether to honor LC_NUMERIC locale + * (default true). */ - struct ConverterParams - { - /** - * @brief Constructor - * @param pHasDefaultConverter specifies if conversion of non-numerical strings shall be - * converted to a default numerical value, instead of causing - * an exception to be thrown (default). - * @param pDefaultFloat floating-point default value to represent invalid numbers. - * @param pDefaultInteger integer default value to represent invalid numbers. - * @param pNumericLocale specifies whether to honor LC_NUMERIC locale (default - * true). - */ - explicit ConverterParams(const bool pHasDefaultConverter = false, - const long double pDefaultFloat = std::numeric_limits::signaling_NaN(), - const long long pDefaultInteger = 0, - const bool pNumericLocale = true) - : mHasDefaultConverter(pHasDefaultConverter) - , mDefaultFloat(pDefaultFloat) - , mDefaultInteger(pDefaultInteger) - , mNumericLocale(pNumericLocale) - { - } - - /** - * @brief specifies if conversion of non-numerical strings shall be converted to a default - * numerical value, instead of causing an exception to be thrown (default). - */ - bool mHasDefaultConverter; - - /** - * @brief floating-point default value to represent invalid numbers. - */ - long double mDefaultFloat; - - /** - * @brief integer default value to represent invalid numbers. - */ - long long mDefaultInteger; - - /** - * @brief specifies whether to honor LC_NUMERIC locale. - */ - bool mNumericLocale; - }; + explicit ConverterParams(const bool pHasDefaultConverter = false, + const long double pDefaultFloat = + std::numeric_limits::signaling_NaN(), + const long long pDefaultInteger = 0, + const bool pNumericLocale = true) + : mHasDefaultConverter(pHasDefaultConverter), + mDefaultFloat(pDefaultFloat), + mDefaultInteger(pDefaultInteger), + mNumericLocale(pNumericLocale) {} /** - * @brief Exception thrown when attempting to access Document data in a datatype which - * is not supported by the Converter class. + * @brief specifies if conversion of non-numerical strings shall be + * converted to a default numerical value, instead of causing an exception to + * be thrown (default). */ - class no_converter : public std::exception - { - /** - * @brief Provides details about the exception - * @returns an explanatory string - */ - virtual const char* what() const throw() - { - return "unsupported conversion datatype"; - } - }; + bool mHasDefaultConverter; /** - * @brief Class providing conversion to/from numerical datatypes and strings. Only - * intended for rapidcsv internal usage, but exposed externally to allow - * specialization for custom datatype conversions. + * @brief floating-point default value to represent invalid numbers. */ - template - class Converter - { - public: - /** - * @brief Constructor - * @param pConverterParams specifies how conversion of non-numerical values to - * numerical datatype shall be handled. - */ - Converter(const ConverterParams& pConverterParams) - : mConverterParams(pConverterParams) - { + long double mDefaultFloat; + + /** + * @brief integer default value to represent invalid numbers. + */ + long long mDefaultInteger; + + /** + * @brief specifies whether to honor LC_NUMERIC locale. + */ + bool mNumericLocale; +}; + +/** + * @brief Exception thrown when attempting to access Document data in a + * datatype which is not supported by the Converter class. + */ +class no_converter : public std::exception { + /** + * @brief Provides details about the exception + * @returns an explanatory string + */ + virtual const char* what() const throw() { + return "unsupported conversion datatype"; + } +}; + +/** + * @brief Class providing conversion to/from numerical datatypes and + * strings. Only intended for rapidcsv internal usage, but exposed externally to + * allow specialization for custom datatype conversions. + */ +template +class Converter { + public: + /** + * @brief Constructor + * @param pConverterParams specifies how conversion of non-numerical + * values to numerical datatype shall be handled. + */ + Converter(const ConverterParams& pConverterParams) + : mConverterParams(pConverterParams) {} + + /** + * @brief Converts numerical value to string representation. + * @param pVal numerical value + * @param pStr output string + */ + void ToStr(const T& pVal, std::string& pStr) const { + if (typeid(T) == typeid(int) || typeid(T) == typeid(long) || + typeid(T) == typeid(long long) || typeid(T) == typeid(unsigned) || + typeid(T) == typeid(unsigned long) || + typeid(T) == typeid(unsigned long long) || typeid(T) == typeid(float) || + typeid(T) == typeid(double) || typeid(T) == typeid(long double) || + typeid(T) == typeid(char)) { + std::ostringstream out; + out << pVal; + pStr = out.str(); + } else { + throw no_converter(); } + } - /** - * @brief Converts numerical value to string representation. - * @param pVal numerical value - * @param pStr output string - */ - void ToStr(const T& pVal, std::string& pStr) const - { - if (typeid(T) == typeid(int) || - typeid(T) == typeid(long) || - typeid(T) == typeid(long long) || - typeid(T) == typeid(unsigned) || - typeid(T) == typeid(unsigned long) || - typeid(T) == typeid(unsigned long long) || - typeid(T) == typeid(float) || - typeid(T) == typeid(double) || - typeid(T) == typeid(long double) || - typeid(T) == typeid(char)) - { - std::ostringstream out; - out << pVal; - pStr = out.str(); - } - else - { - throw no_converter(); - } - } - - /** - * @brief Converts string holding a numerical value to numerical datatype representation. - * @param pVal numerical value - * @param pStr output string - */ - void ToVal(const std::string& pStr, T& pVal) const - { - try - { - if (typeid(T) == typeid(int)) - { - pVal = static_cast(std::stoi(pStr)); - return; - } - else if (typeid(T) == typeid(long)) - { - pVal = static_cast(std::stol(pStr)); - return; - } - else if (typeid(T) == typeid(long long)) - { - pVal = static_cast(std::stoll(pStr)); - return; - } - else if (typeid(T) == typeid(unsigned)) - { - pVal = static_cast(std::stoul(pStr)); - return; - } - else if (typeid(T) == typeid(unsigned long)) - { - pVal = static_cast(std::stoul(pStr)); - return; - } - else if (typeid(T) == typeid(unsigned long long)) - { - pVal = static_cast(std::stoull(pStr)); - return; - } - } - catch (...) - { - if (!mConverterParams.mHasDefaultConverter) - { - throw; - } - else - { - pVal = static_cast(mConverterParams.mDefaultInteger); - return; - } - } - - try - { - if (mConverterParams.mNumericLocale) - { - if (typeid(T) == typeid(float)) - { - pVal = static_cast(std::stof(pStr)); - return; - } - else if (typeid(T) == typeid(double)) - { - pVal = static_cast(std::stod(pStr)); - return; - } - else if (typeid(T) == typeid(long double)) - { - pVal = static_cast(std::stold(pStr)); - return; - } - } - else - { - if ((typeid(T) == typeid(float)) || - (typeid(T) == typeid(double)) || - (typeid(T) == typeid(long double))) - { - std::istringstream iss(pStr); - iss >> pVal; - if (iss.fail() || iss.bad() || !iss.eof()) - { - throw std::invalid_argument("istringstream: no conversion"); - } - return; - } - } - } - catch (...) - { - if (!mConverterParams.mHasDefaultConverter) - { - throw; - } - else - { - pVal = static_cast(mConverterParams.mDefaultFloat); - return; - } - } - - if (typeid(T) == typeid(char)) - { - pVal = static_cast(pStr[0]); + /** + * @brief Converts string holding a numerical value to numerical datatype + * representation. + * @param pVal numerical value + * @param pStr output string + */ + void ToVal(const std::string& pStr, T& pVal) const { + try { + if (typeid(T) == typeid(int)) { + pVal = static_cast(std::stoi(pStr)); + return; + } else if (typeid(T) == typeid(long)) { + pVal = static_cast(std::stol(pStr)); + return; + } else if (typeid(T) == typeid(long long)) { + pVal = static_cast(std::stoll(pStr)); + return; + } else if (typeid(T) == typeid(unsigned)) { + pVal = static_cast(std::stoul(pStr)); + return; + } else if (typeid(T) == typeid(unsigned long)) { + pVal = static_cast(std::stoul(pStr)); + return; + } else if (typeid(T) == typeid(unsigned long long)) { + pVal = static_cast(std::stoull(pStr)); return; } - else - { - throw no_converter(); + } catch (...) { + if (!mConverterParams.mHasDefaultConverter) { + throw; + } else { + pVal = static_cast(mConverterParams.mDefaultInteger); + return; } } - private: - const ConverterParams& mConverterParams; - }; + try { + if (mConverterParams.mNumericLocale) { + if (typeid(T) == typeid(float)) { + pVal = static_cast(std::stof(pStr)); + return; + } else if (typeid(T) == typeid(double)) { + pVal = static_cast(std::stod(pStr)); + return; + } else if (typeid(T) == typeid(long double)) { + pVal = static_cast(std::stold(pStr)); + return; + } + } else { + if ((typeid(T) == typeid(float)) || (typeid(T) == typeid(double)) || + (typeid(T) == typeid(long double))) { + std::istringstream iss(pStr); + iss >> pVal; + if (iss.fail() || iss.bad() || !iss.eof()) { + throw std::invalid_argument("istringstream: no conversion"); + } + return; + } + } + } catch (...) { + if (!mConverterParams.mHasDefaultConverter) { + throw; + } else { + pVal = static_cast(mConverterParams.mDefaultFloat); + return; + } + } + if (typeid(T) == typeid(char)) { + pVal = static_cast(pStr[0]); + return; + } else { + throw no_converter(); + } + } + + private: + const ConverterParams& mConverterParams; +}; + +/** + * @brief Specialized implementation handling string to string conversion. + * @param pVal string + * @param pStr string + */ +template <> +inline void Converter::ToStr(const std::string& pVal, + std::string& pStr) const { + pStr = pVal; +} + +/** + * @brief Specialized implementation handling string to string conversion. + * @param pVal string + * @param pStr string + */ +template <> +inline void Converter::ToVal(const std::string& pStr, + std::string& pVal) const { + pVal = pStr; +} + +template +using ConvFunc = std::function; + +/** + * @brief Datastructure holding parameters controlling which row and column + * should be treated as labels. + */ +struct LabelParams { /** - * @brief Specialized implementation handling string to string conversion. - * @param pVal string - * @param pStr string + * @brief Constructor + * @param pColumnNameIdx specifies the zero-based row index of the + * column labels, setting it to -1 prevents column lookup by label name, and + * gives access to all rows as document data. Default: 0 + * @param pRowNameIdx specifies the zero-based column index of the + * row labels, setting it to -1 prevents row lookup by label name, and gives + * access to all columns as document data. Default: -1 */ - template<> - inline void Converter::ToStr(const std::string& pVal, std::string& pStr) const - { - pStr = pVal; + explicit LabelParams(const ssize_t pColumnNameIdx = 0, + const ssize_t pRowNameIdx = -1) + : mColumnNameIdx(pColumnNameIdx), mRowNameIdx(pRowNameIdx) { + if (mColumnNameIdx < -1) { + const std::string errStr = + "invalid column name index " + std::to_string(mColumnNameIdx) + " < -1"; + throw std::out_of_range(errStr); + } + + if (mRowNameIdx < -1) { + const std::string errStr = + "invalid row name index " + std::to_string(mRowNameIdx) + " < -1"; + throw std::out_of_range(errStr); + } } /** - * @brief Specialized implementation handling string to string conversion. - * @param pVal string - * @param pStr string + * @brief specifies the zero-based row index of the column labels. */ - template<> - inline void Converter::ToVal(const std::string& pStr, std::string& pVal) const - { - pVal = pStr; - } - - template - using ConvFunc = std::function; + ssize_t mColumnNameIdx; /** - * @brief Datastructure holding parameters controlling which row and column should be - * treated as labels. + * @brief specifies the zero-based column index of the row labels. */ - struct LabelParams - { - /** - * @brief Constructor - * @param pColumnNameIdx specifies the zero-based row index of the column labels, setting - * it to -1 prevents column lookup by label name, and gives access - * to all rows as document data. Default: 0 - * @param pRowNameIdx specifies the zero-based column index of the row labels, setting - * it to -1 prevents row lookup by label name, and gives access - * to all columns as document data. Default: -1 - */ - explicit LabelParams(const ssize_t pColumnNameIdx = 0, const ssize_t pRowNameIdx = -1) - : mColumnNameIdx(pColumnNameIdx) - , mRowNameIdx(pRowNameIdx) - { - if (mColumnNameIdx < -1) - { - const std::string errStr = "invalid column name index " + - std::to_string(mColumnNameIdx) + " < -1"; - throw std::out_of_range(errStr); - } + ssize_t mRowNameIdx; +}; - if (mRowNameIdx < -1) - { - const std::string errStr = "invalid row name index " + - std::to_string(mRowNameIdx) + " < -1"; - throw std::out_of_range(errStr); - } - } - - /** - * @brief specifies the zero-based row index of the column labels. - */ - ssize_t mColumnNameIdx; - - /** - * @brief specifies the zero-based column index of the row labels. - */ - ssize_t mRowNameIdx; - }; +/** + * @brief Datastructure holding parameters controlling how the CSV data + * fields are separated. + */ +struct SeparatorParams { + /** + * @brief Constructor + * @param pSeparator specifies the column separator (default + * ','). + * @param pTrim specifies whether to trim leading and + * trailing spaces from cells read (default false). + * @param pHasCR specifies whether a new document (i.e. not + * an existing document read) should use CR/LF instead of only LF (default is + * to use standard behavior of underlying platforms - CR/LF for Win, and LF + * for others). + * @param pQuotedLinebreaks specifies whether to allow line breaks in + * quoted text (default false) + * @param pAutoQuote specifies whether to automatically dequote + * data during read, and add quotes during write (default true). + */ + explicit SeparatorParams(const char pSeparator = ',', + const bool pTrim = false, + const bool pHasCR = sPlatformHasCR, + const bool pQuotedLinebreaks = false, + const bool pAutoQuote = true) + : mSeparator(pSeparator), + mTrim(pTrim), + mHasCR(pHasCR), + mQuotedLinebreaks(pQuotedLinebreaks), + mAutoQuote(pAutoQuote) {} /** - * @brief Datastructure holding parameters controlling how the CSV data fields are separated. + * @brief specifies the column separator. */ - struct SeparatorParams - { - /** - * @brief Constructor - * @param pSeparator specifies the column separator (default ','). - * @param pTrim specifies whether to trim leading and trailing spaces from - * cells read (default false). - * @param pHasCR specifies whether a new document (i.e. not an existing document read) - * should use CR/LF instead of only LF (default is to use standard - * behavior of underlying platforms - CR/LF for Win, and LF for others). - * @param pQuotedLinebreaks specifies whether to allow line breaks in quoted text (default false) - * @param pAutoQuote specifies whether to automatically dequote data during read, and add - * quotes during write (default true). - */ - explicit SeparatorParams(const char pSeparator = ',', const bool pTrim = false, - const bool pHasCR = sPlatformHasCR, const bool pQuotedLinebreaks = false, - const bool pAutoQuote = true) - : mSeparator(pSeparator) - , mTrim(pTrim) - , mHasCR(pHasCR) - , mQuotedLinebreaks(pQuotedLinebreaks) - , mAutoQuote(pAutoQuote) - { - } - - /** - * @brief specifies the column separator. - */ - char mSeparator; - - /** - * @brief specifies whether to trim leading and trailing spaces from cells read. - */ - bool mTrim; - - /** - * @brief specifies whether new documents should use CR/LF instead of LF. - */ - bool mHasCR; - - /** - * @brief specifies whether to allow line breaks in quoted text. - */ - bool mQuotedLinebreaks; - - /** - * @brief specifies whether to automatically dequote cell data. - */ - bool mAutoQuote; - }; + char mSeparator; /** - * @brief Datastructure holding parameters controlling how special line formats should be - * treated. + * @brief specifies whether to trim leading and trailing spaces from cells + * read. */ - struct LineReaderParams - { - /** - * @brief Constructor - * @param pSkipCommentLines specifies whether to skip lines prefixed with - * mCommentPrefix. Default: false - * @param pCommentPrefix specifies which prefix character to indicate a comment - * line. Default: # - * @param pSkipEmptyLines specifies whether to skip empty lines. Default: false - */ - explicit LineReaderParams(const bool pSkipCommentLines = false, - const char pCommentPrefix = '#', - const bool pSkipEmptyLines = false) - : mSkipCommentLines(pSkipCommentLines) - , mCommentPrefix(pCommentPrefix) - , mSkipEmptyLines(pSkipEmptyLines) - { - } - - /** - * @brief specifies whether to skip lines prefixed with mCommentPrefix. - */ - bool mSkipCommentLines; - - /** - * @brief specifies which prefix character to indicate a comment line. - */ - char mCommentPrefix; - - /** - * @brief specifies whether to skip empty lines. - */ - bool mSkipEmptyLines; - }; + bool mTrim; /** - * @brief Class representing a CSV document. + * @brief specifies whether new documents should use CR/LF instead of LF. */ - class Document - { - public: - /** - * @brief Constructor - * @param pPath specifies the path of an existing CSV-file to populate the Document - * data with. - * @param pLabelParams specifies which row and column should be treated as labels. - * @param pSeparatorParams specifies which field and row separators should be used. - * @param pConverterParams specifies how invalid numbers (including empty strings) should be - * handled. - * @param pLineReaderParams specifies how special line formats should be treated. - */ - explicit Document(const std::string& pPath = std::string(), - const LabelParams& pLabelParams = LabelParams(), - const SeparatorParams& pSeparatorParams = SeparatorParams(), - const ConverterParams& pConverterParams = ConverterParams(), - const LineReaderParams& pLineReaderParams = LineReaderParams()) - : mPath(pPath) - , mLabelParams(pLabelParams) - , mSeparatorParams(pSeparatorParams) - , mConverterParams(pConverterParams) - , mLineReaderParams(pLineReaderParams) - { - if (!mPath.empty()) - { - ReadCsv(); - } - } + bool mHasCR; - /** - * @brief Constructor - * @param pStream specifies a binary input stream to read CSV data from. - * @param pLabelParams specifies which row and column should be treated as labels. - * @param pSeparatorParams specifies which field and row separators should be used. - * @param pConverterParams specifies how invalid numbers (including empty strings) should be - * handled. - * @param pLineReaderParams specifies how special line formats should be treated. - */ - explicit Document(std::istream& pStream, - const LabelParams& pLabelParams = LabelParams(), - const SeparatorParams& pSeparatorParams = SeparatorParams(), - const ConverterParams& pConverterParams = ConverterParams(), - const LineReaderParams& pLineReaderParams = LineReaderParams()) - : mPath() - , mLabelParams(pLabelParams) - , mSeparatorParams(pSeparatorParams) - , mConverterParams(pConverterParams) - , mLineReaderParams(pLineReaderParams) - { - ReadCsv(pStream); - } + /** + * @brief specifies whether to allow line breaks in quoted text. + */ + bool mQuotedLinebreaks; - /** - * @brief Read Document data from file. - * @param pPath specifies the path of an existing CSV-file to populate the Document - * data with. - * @param pLabelParams specifies which row and column should be treated as labels. - * @param pSeparatorParams specifies which field and row separators should be used. - * @param pConverterParams specifies how invalid numbers (including empty strings) should be - * handled. - * @param pLineReaderParams specifies how special line formats should be treated. - */ - void Load(const std::string& pPath, - const LabelParams& pLabelParams = LabelParams(), - const SeparatorParams& pSeparatorParams = SeparatorParams(), - const ConverterParams& pConverterParams = ConverterParams(), - const LineReaderParams& pLineReaderParams = LineReaderParams()) - { - mPath = pPath; - mLabelParams = pLabelParams; - mSeparatorParams = pSeparatorParams; - mConverterParams = pConverterParams; - mLineReaderParams = pLineReaderParams; + /** + * @brief specifies whether to automatically dequote cell data. + */ + bool mAutoQuote; +}; + +/** + * @brief Datastructure holding parameters controlling how special line + * formats should be treated. + */ +struct LineReaderParams { + /** + * @brief Constructor + * @param pSkipCommentLines specifies whether to skip lines prefixed + * with mCommentPrefix. Default: false + * @param pCommentPrefix specifies which prefix character to indicate + * a comment line. Default: # + * @param pSkipEmptyLines specifies whether to skip empty lines. + * Default: false + */ + explicit LineReaderParams(const bool pSkipCommentLines = false, + const char pCommentPrefix = '#', + const bool pSkipEmptyLines = false) + : mSkipCommentLines(pSkipCommentLines), + mCommentPrefix(pCommentPrefix), + mSkipEmptyLines(pSkipEmptyLines) {} + + /** + * @brief specifies whether to skip lines prefixed with mCommentPrefix. + */ + bool mSkipCommentLines; + + /** + * @brief specifies which prefix character to indicate a comment line. + */ + char mCommentPrefix; + + /** + * @brief specifies whether to skip empty lines. + */ + bool mSkipEmptyLines; +}; + +/** + * @brief Class representing a CSV document. + */ +class Document { + public: + /** + * @brief Constructor + * @param pPath specifies the path of an existing CSV-file + * to populate the Document data with. + * @param pLabelParams specifies which row and column should be + * treated as labels. + * @param pSeparatorParams specifies which field and row separators + * should be used. + * @param pConverterParams specifies how invalid numbers (including + * empty strings) should be handled. + * @param pLineReaderParams specifies how special line formats should be + * treated. + */ + explicit Document( + const std::string& pPath = std::string(), + const LabelParams& pLabelParams = LabelParams(), + const SeparatorParams& pSeparatorParams = SeparatorParams(), + const ConverterParams& pConverterParams = ConverterParams(), + const LineReaderParams& pLineReaderParams = LineReaderParams()) + : mPath(pPath), + mLabelParams(pLabelParams), + mSeparatorParams(pSeparatorParams), + mConverterParams(pConverterParams), + mLineReaderParams(pLineReaderParams) { + if (!mPath.empty()) { ReadCsv(); } + } - /** - * @brief Read Document data from stream. - * @param pStream specifies a binary input stream to read CSV data from. - * @param pLabelParams specifies which row and column should be treated as labels. - * @param pSeparatorParams specifies which field and row separators should be used. - * @param pConverterParams specifies how invalid numbers (including empty strings) should be - * handled. - * @param pLineReaderParams specifies how special line formats should be treated. - */ - void Load(std::istream& pStream, - const LabelParams& pLabelParams = LabelParams(), - const SeparatorParams& pSeparatorParams = SeparatorParams(), - const ConverterParams& pConverterParams = ConverterParams(), - const LineReaderParams& pLineReaderParams = LineReaderParams()) - { - mPath = ""; - mLabelParams = pLabelParams; - mSeparatorParams = pSeparatorParams; - mConverterParams = pConverterParams; - mLineReaderParams = pLineReaderParams; - ReadCsv(pStream); + /** + * @brief Constructor + * @param pStream specifies a binary input stream to read CSV + * data from. + * @param pLabelParams specifies which row and column should be + * treated as labels. + * @param pSeparatorParams specifies which field and row separators + * should be used. + * @param pConverterParams specifies how invalid numbers (including + * empty strings) should be handled. + * @param pLineReaderParams specifies how special line formats should be + * treated. + */ + explicit Document( + std::istream& pStream, const LabelParams& pLabelParams = LabelParams(), + const SeparatorParams& pSeparatorParams = SeparatorParams(), + const ConverterParams& pConverterParams = ConverterParams(), + const LineReaderParams& pLineReaderParams = LineReaderParams()) + : mPath(), + mLabelParams(pLabelParams), + mSeparatorParams(pSeparatorParams), + mConverterParams(pConverterParams), + mLineReaderParams(pLineReaderParams) { + ReadCsv(pStream); + } + + /** + * @brief Read Document data from file. + * @param pPath specifies the path of an existing CSV-file + * to populate the Document data with. + * @param pLabelParams specifies which row and column should be + * treated as labels. + * @param pSeparatorParams specifies which field and row separators + * should be used. + * @param pConverterParams specifies how invalid numbers (including + * empty strings) should be handled. + * @param pLineReaderParams specifies how special line formats should be + * treated. + */ + void Load(const std::string& pPath, + const LabelParams& pLabelParams = LabelParams(), + const SeparatorParams& pSeparatorParams = SeparatorParams(), + const ConverterParams& pConverterParams = ConverterParams(), + const LineReaderParams& pLineReaderParams = LineReaderParams()) { + mPath = pPath; + mLabelParams = pLabelParams; + mSeparatorParams = pSeparatorParams; + mConverterParams = pConverterParams; + mLineReaderParams = pLineReaderParams; + ReadCsv(); + } + + /** + * @brief Read Document data from stream. + * @param pStream specifies a binary input stream to read CSV + * data from. + * @param pLabelParams specifies which row and column should be + * treated as labels. + * @param pSeparatorParams specifies which field and row separators + * should be used. + * @param pConverterParams specifies how invalid numbers (including + * empty strings) should be handled. + * @param pLineReaderParams specifies how special line formats should be + * treated. + */ + void Load(std::istream& pStream, + const LabelParams& pLabelParams = LabelParams(), + const SeparatorParams& pSeparatorParams = SeparatorParams(), + const ConverterParams& pConverterParams = ConverterParams(), + const LineReaderParams& pLineReaderParams = LineReaderParams()) { + mPath = ""; + mLabelParams = pLabelParams; + mSeparatorParams = pSeparatorParams; + mConverterParams = pConverterParams; + mLineReaderParams = pLineReaderParams; + ReadCsv(pStream); + } + + /** + * @brief Write Document data to file. + * @param pPath optionally specifies the path where the + * CSV-file will be created (if not specified, the original path provided when + * creating or loading the Document data will be used). + */ + void Save(const std::string& pPath = std::string()) { + if (!pPath.empty()) { + mPath = pPath; } + WriteCsv(); + } - /** - * @brief Write Document data to file. - * @param pPath optionally specifies the path where the CSV-file will be created - * (if not specified, the original path provided when creating or - * loading the Document data will be used). - */ - void Save(const std::string& pPath = std::string()) - { - if (!pPath.empty()) - { - mPath = pPath; - } - WriteCsv(); - } + /** + * @brief Write Document data to stream. + * @param pStream specifies a binary output stream to write + * the data to. + */ + void Save(std::ostream& pStream) { WriteCsv(pStream); } - /** - * @brief Write Document data to stream. - * @param pStream specifies a binary output stream to write the data to. - */ - void Save(std::ostream& pStream) - { - WriteCsv(pStream); - } - - /** - * @brief Clears loaded Document data. - * - */ - void Clear() - { - mData.clear(); - mColumnNames.clear(); - mRowNames.clear(); + /** + * @brief Clears loaded Document data. + * + */ + void Clear() { + mData.clear(); + mColumnNames.clear(); + mRowNames.clear(); #ifdef HAS_CODECVT - mIsUtf16 = false; - mIsLE = false; + mIsUtf16 = false; + mIsLE = false; #endif - } + } - /** - * @brief Get column index by name. - * @param pColumnName column label name. - * @returns zero-based column index. - */ - ssize_t GetColumnIdx(const std::string& pColumnName) const - { - if (mLabelParams.mColumnNameIdx >= 0) - { - if (mColumnNames.find(pColumnName) != mColumnNames.end()) - { - return static_cast(mColumnNames.at(pColumnName)) - (mLabelParams.mRowNameIdx + 1); - } + /** + * @brief Get column index by name. + * @param pColumnName column label name. + * @returns zero-based column index. + */ + ssize_t GetColumnIdx(const std::string& pColumnName) const { + if (mLabelParams.mColumnNameIdx >= 0) { + if (mColumnNames.find(pColumnName) != mColumnNames.end()) { + return static_cast(mColumnNames.at(pColumnName)) - + (mLabelParams.mRowNameIdx + 1); } - return -1; } + return -1; + } - /** - * @brief Get column by index. - * @param pColumnIdx zero-based column index. - * @returns vector of column data. - */ - template - std::vector GetColumn(const size_t pColumnIdx) const - { - const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); - std::vector column; - Converter converter(mConverterParams); - for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) - { - if (std::distance(mData.begin(), itRow) > mLabelParams.mColumnNameIdx) - { - if (dataColumnIdx < itRow->size()) - { - T val; - converter.ToVal(itRow->at(dataColumnIdx), val); - column.push_back(val); - } - else - { - const std::string errStr = "requested column index " + - std::to_string(pColumnIdx) + " >= " + - std::to_string(itRow->size() - GetDataColumnIndex(0)) + - " (number of columns on row index " + - std::to_string(std::distance(mData.begin(), itRow) - - (mLabelParams.mColumnNameIdx + 1)) + ")"; - throw std::out_of_range(errStr); - } - } - } - return column; - } - - /** - * @brief Get column by index. - * @param pColumnIdx zero-based column index. - * @param pToVal conversion function. - * @returns vector of column data. - */ - template - std::vector GetColumn(const size_t pColumnIdx, ConvFunc pToVal) const - { - const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); - std::vector column; - for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) - { - if (std::distance(mData.begin(), itRow) > mLabelParams.mColumnNameIdx) - { + /** + * @brief Get column by index. + * @param pColumnIdx zero-based column index. + * @returns vector of column data. + */ + template + std::vector GetColumn(const size_t pColumnIdx) const { + const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); + std::vector column; + Converter converter(mConverterParams); + for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) { + if (std::distance(mData.begin(), itRow) > mLabelParams.mColumnNameIdx) { + if (dataColumnIdx < itRow->size()) { T val; - pToVal(itRow->at(dataColumnIdx), val); + converter.ToVal(itRow->at(dataColumnIdx), val); column.push_back(val); + } else { + const std::string errStr = + "requested column index " + std::to_string(pColumnIdx) + + " >= " + std::to_string(itRow->size() - GetDataColumnIndex(0)) + + " (number of columns on row index " + + std::to_string(std::distance(mData.begin(), itRow) - + (mLabelParams.mColumnNameIdx + 1)) + + ")"; + throw std::out_of_range(errStr); } } - return column; + } + return column; + } + + /** + * @brief Get column by index. + * @param pColumnIdx zero-based column index. + * @param pToVal conversion function. + * @returns vector of column data. + */ + template + std::vector GetColumn(const size_t pColumnIdx, ConvFunc pToVal) const { + const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); + std::vector column; + for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) { + if (std::distance(mData.begin(), itRow) > mLabelParams.mColumnNameIdx) { + T val; + pToVal(itRow->at(dataColumnIdx), val); + column.push_back(val); + } + } + return column; + } + + /** + * @brief Get column by name. + * @param pColumnName column label name. + * @returns vector of column data. + */ + template + std::vector GetColumn(const std::string& pColumnName) const { + const ssize_t columnIdx = GetColumnIdx(pColumnName); + if (columnIdx < 0) { + throw std::out_of_range("column not found: " + pColumnName); + } + return GetColumn(static_cast(columnIdx)); + } + + /** + * @brief Get column by name. + * @param pColumnName column label name. + * @param pToVal conversion function. + * @returns vector of column data. + */ + template + std::vector GetColumn(const std::string& pColumnName, + ConvFunc pToVal) const { + const ssize_t columnIdx = GetColumnIdx(pColumnName); + if (columnIdx < 0) { + throw std::out_of_range("column not found: " + pColumnName); + } + return GetColumn(static_cast(columnIdx), pToVal); + } + + /** + * @brief Set column by index. + * @param pColumnIdx zero-based column index. + * @param pColumn vector of column data. + */ + template + void SetColumn(const size_t pColumnIdx, const std::vector& pColumn) { + const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); + + while (GetDataRowIndex(pColumn.size()) > GetDataRowCount()) { + std::vector row; + row.resize(GetDataColumnCount()); + mData.push_back(row); } - /** - * @brief Get column by name. - * @param pColumnName column label name. - * @returns vector of column data. - */ - template - std::vector GetColumn(const std::string& pColumnName) const - { - const ssize_t columnIdx = GetColumnIdx(pColumnName); - if (columnIdx < 0) - { - throw std::out_of_range("column not found: " + pColumnName); + if ((dataColumnIdx + 1) > GetDataColumnCount()) { + for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) { + itRow->resize(GetDataColumnIndex(dataColumnIdx + 1)); } - return GetColumn(static_cast(columnIdx)); } - /** - * @brief Get column by name. - * @param pColumnName column label name. - * @param pToVal conversion function. - * @returns vector of column data. - */ - template - std::vector GetColumn(const std::string& pColumnName, ConvFunc pToVal) const - { - const ssize_t columnIdx = GetColumnIdx(pColumnName); - if (columnIdx < 0) - { - throw std::out_of_range("column not found: " + pColumnName); - } - return GetColumn(static_cast(columnIdx), pToVal); + Converter converter(mConverterParams); + for (auto itRow = pColumn.begin(); itRow != pColumn.end(); ++itRow) { + std::string str; + converter.ToStr(*itRow, str); + mData + .at(static_cast(std::distance(pColumn.begin(), itRow) + + mLabelParams.mColumnNameIdx + 1)) + .at(dataColumnIdx) = str; + } + } + + /** + * @brief Set column by name. + * @param pColumnName column label name. + * @param pColumn vector of column data. + */ + template + void SetColumn(const std::string& pColumnName, + const std::vector& pColumn) { + const ssize_t columnIdx = GetColumnIdx(pColumnName); + if (columnIdx < 0) { + throw std::out_of_range("column not found: " + pColumnName); + } + SetColumn(static_cast(columnIdx), pColumn); + } + + /** + * @brief Remove column by index. + * @param pColumnIdx zero-based column index. + */ + void RemoveColumn(const size_t pColumnIdx) { + const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); + for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) { + itRow->erase(itRow->begin() + static_cast(dataColumnIdx)); } - /** - * @brief Set column by index. - * @param pColumnIdx zero-based column index. - * @param pColumn vector of column data. - */ - template - void SetColumn(const size_t pColumnIdx, const std::vector& pColumn) - { - const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); + UpdateColumnNames(); + } - while (GetDataRowIndex(pColumn.size()) > GetDataRowCount()) - { - std::vector row; - row.resize(GetDataColumnCount()); - mData.push_back(row); - } + /** + * @brief Remove column by name. + * @param pColumnName column label name. + */ + void RemoveColumn(const std::string& pColumnName) { + ssize_t columnIdx = GetColumnIdx(pColumnName); + if (columnIdx < 0) { + throw std::out_of_range("column not found: " + pColumnName); + } - if ((dataColumnIdx + 1) > GetDataColumnCount()) - { - for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) - { - itRow->resize(GetDataColumnIndex(dataColumnIdx + 1)); - } - } + RemoveColumn(static_cast(columnIdx)); + } + /** + * @brief Insert column at specified index. + * @param pColumnIdx zero-based column index. + * @param pColumn vector of column data (optional argument). + * @param pColumnName column label name (optional argument). + */ + template + void InsertColumn(const size_t pColumnIdx, + const std::vector& pColumn = std::vector(), + const std::string& pColumnName = std::string()) { + const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); + + std::vector column; + if (pColumn.empty()) { + column.resize(GetDataRowCount()); + } else { + column.resize(GetDataRowIndex(pColumn.size())); Converter converter(mConverterParams); - for (auto itRow = pColumn.begin(); itRow != pColumn.end(); ++itRow) - { + for (auto itRow = pColumn.begin(); itRow != pColumn.end(); ++itRow) { std::string str; converter.ToStr(*itRow, str); - mData.at(static_cast(std::distance(pColumn.begin(), itRow) + mLabelParams.mColumnNameIdx + 1)).at(dataColumnIdx) = str; + const size_t rowIdx = + static_cast(std::distance(pColumn.begin(), itRow) + + (mLabelParams.mColumnNameIdx + 1)); + column.at(rowIdx) = str; } } - /** - * @brief Set column by name. - * @param pColumnName column label name. - * @param pColumn vector of column data. - */ - template - void SetColumn(const std::string& pColumnName, const std::vector& pColumn) - { - const ssize_t columnIdx = GetColumnIdx(pColumnName); - if (columnIdx < 0) - { - throw std::out_of_range("column not found: " + pColumnName); - } - SetColumn(static_cast(columnIdx), pColumn); + while (column.size() > GetDataRowCount()) { + std::vector row; + const size_t columnCount = + std::max(static_cast(mLabelParams.mColumnNameIdx + 1), + GetDataColumnCount()); + row.resize(columnCount); + mData.push_back(row); } - /** - * @brief Remove column by index. - * @param pColumnIdx zero-based column index. - */ - void RemoveColumn(const size_t pColumnIdx) - { - const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); - for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) - { - itRow->erase(itRow->begin() + static_cast(dataColumnIdx)); - } - - UpdateColumnNames(); + for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) { + const size_t rowIdx = + static_cast(std::distance(mData.begin(), itRow)); + itRow->insert(itRow->begin() + static_cast(dataColumnIdx), + column.at(rowIdx)); } - /** - * @brief Remove column by name. - * @param pColumnName column label name. - */ - void RemoveColumn(const std::string& pColumnName) - { - ssize_t columnIdx = GetColumnIdx(pColumnName); - if (columnIdx < 0) - { - throw std::out_of_range("column not found: " + pColumnName); - } - - RemoveColumn(static_cast(columnIdx)); + if (!pColumnName.empty()) { + SetColumnName(pColumnIdx, pColumnName); } - /** - * @brief Insert column at specified index. - * @param pColumnIdx zero-based column index. - * @param pColumn vector of column data (optional argument). - * @param pColumnName column label name (optional argument). - */ - template - void InsertColumn(const size_t pColumnIdx, const std::vector& pColumn = std::vector(), - const std::string& pColumnName = std::string()) - { - const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); + UpdateColumnNames(); + } - std::vector column; - if (pColumn.empty()) - { - column.resize(GetDataRowCount()); - } - else - { - column.resize(GetDataRowIndex(pColumn.size())); - Converter converter(mConverterParams); - for (auto itRow = pColumn.begin(); itRow != pColumn.end(); ++itRow) - { - std::string str; - converter.ToStr(*itRow, str); - const size_t rowIdx = static_cast(std::distance(pColumn.begin(), itRow) + (mLabelParams.mColumnNameIdx + 1)); - column.at(rowIdx) = str; - } - } + /** + * @brief Get number of data columns (excluding label columns). + * @returns column count. + */ + size_t GetColumnCount() const { + const ssize_t count = + static_cast((mData.size() > 0) ? mData.at(0).size() : 0) - + (mLabelParams.mRowNameIdx + 1); + return (count >= 0) ? static_cast(count) : 0; + } - while (column.size() > GetDataRowCount()) - { - std::vector row; - const size_t columnCount = std::max(static_cast(mLabelParams.mColumnNameIdx + 1), - GetDataColumnCount()); - row.resize(columnCount); - mData.push_back(row); + /** + * @brief Get row index by name. + * @param pRowName row label name. + * @returns zero-based row index. + */ + ssize_t GetRowIdx(const std::string& pRowName) const { + if (mLabelParams.mRowNameIdx >= 0) { + if (mRowNames.find(pRowName) != mRowNames.end()) { + return static_cast(mRowNames.at(pRowName)) - + (mLabelParams.mColumnNameIdx + 1); } + } + return -1; + } - for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) - { - const size_t rowIdx = static_cast(std::distance(mData.begin(), itRow)); - itRow->insert(itRow->begin() + static_cast(dataColumnIdx), column.at(rowIdx)); + /** + * @brief Get row by index. + * @param pRowIdx zero-based row index. + * @returns vector of row data. + */ + template + std::vector GetRow(const size_t pRowIdx) const { + const size_t dataRowIdx = GetDataRowIndex(pRowIdx); + std::vector row; + Converter converter(mConverterParams); + for (auto itCol = mData.at(dataRowIdx).begin(); + itCol != mData.at(dataRowIdx).end(); ++itCol) { + if (std::distance(mData.at(dataRowIdx).begin(), itCol) > + mLabelParams.mRowNameIdx) { + T val; + converter.ToVal(*itCol, val); + row.push_back(val); } + } + return row; + } - if (!pColumnName.empty()) - { - SetColumnName(pColumnIdx, pColumnName); + /** + * @brief Get row by index. + * @param pRowIdx zero-based row index. + * @param pToVal conversion function. + * @returns vector of row data. + */ + template + std::vector GetRow(const size_t pRowIdx, ConvFunc pToVal) const { + const size_t dataRowIdx = GetDataRowIndex(pRowIdx); + std::vector row; + Converter converter(mConverterParams); + for (auto itCol = mData.at(dataRowIdx).begin(); + itCol != mData.at(dataRowIdx).end(); ++itCol) { + if (std::distance(mData.at(dataRowIdx).begin(), itCol) > + mLabelParams.mRowNameIdx) { + T val; + pToVal(*itCol, val); + row.push_back(val); } + } + return row; + } - UpdateColumnNames(); + /** + * @brief Get row by name. + * @param pRowName row label name. + * @returns vector of row data. + */ + template + std::vector GetRow(const std::string& pRowName) const { + ssize_t rowIdx = GetRowIdx(pRowName); + if (rowIdx < 0) { + throw std::out_of_range("row not found: " + pRowName); + } + return GetRow(static_cast(rowIdx)); + } + + /** + * @brief Get row by name. + * @param pRowName row label name. + * @param pToVal conversion function. + * @returns vector of row data. + */ + template + std::vector GetRow(const std::string& pRowName, ConvFunc pToVal) const { + ssize_t rowIdx = GetRowIdx(pRowName); + if (rowIdx < 0) { + throw std::out_of_range("row not found: " + pRowName); + } + return GetRow(static_cast(rowIdx), pToVal); + } + + /** + * @brief Set row by index. + * @param pRowIdx zero-based row index. + * @param pRow vector of row data. + */ + template + void SetRow(const size_t pRowIdx, const std::vector& pRow) { + const size_t dataRowIdx = GetDataRowIndex(pRowIdx); + + while ((dataRowIdx + 1) > GetDataRowCount()) { + std::vector row; + row.resize(GetDataColumnCount()); + mData.push_back(row); } - /** - * @brief Get number of data columns (excluding label columns). - * @returns column count. - */ - size_t GetColumnCount() const - { - const ssize_t count = static_cast((mData.size() > 0) ? mData.at(0).size() : 0) - - (mLabelParams.mRowNameIdx + 1); - return (count >= 0) ? static_cast(count) : 0; - } - - /** - * @brief Get row index by name. - * @param pRowName row label name. - * @returns zero-based row index. - */ - ssize_t GetRowIdx(const std::string& pRowName) const - { - if (mLabelParams.mRowNameIdx >= 0) - { - if (mRowNames.find(pRowName) != mRowNames.end()) - { - return static_cast(mRowNames.at(pRowName)) - (mLabelParams.mColumnNameIdx + 1); - } + if (pRow.size() > GetDataColumnCount()) { + for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) { + itRow->resize(GetDataColumnIndex(pRow.size())); } - return -1; } - /** - * @brief Get row by index. - * @param pRowIdx zero-based row index. - * @returns vector of row data. - */ - template - std::vector GetRow(const size_t pRowIdx) const - { - const size_t dataRowIdx = GetDataRowIndex(pRowIdx); - std::vector row; + Converter converter(mConverterParams); + for (auto itCol = pRow.begin(); itCol != pRow.end(); ++itCol) { + std::string str; + converter.ToStr(*itCol, str); + mData.at(dataRowIdx) + .at(static_cast(std::distance(pRow.begin(), itCol) + + mLabelParams.mRowNameIdx + 1)) = str; + } + } + + /** + * @brief Set row by name. + * @param pRowName row label name. + * @param pRow vector of row data. + */ + template + void SetRow(const std::string& pRowName, const std::vector& pRow) { + ssize_t rowIdx = GetRowIdx(pRowName); + if (rowIdx < 0) { + throw std::out_of_range("row not found: " + pRowName); + } + return SetRow(static_cast(rowIdx), pRow); + } + + /** + * @brief Remove row by index. + * @param pRowIdx zero-based row index. + */ + void RemoveRow(const size_t pRowIdx) { + const size_t dataRowIdx = GetDataRowIndex(pRowIdx); + mData.erase(mData.begin() + static_cast(dataRowIdx)); + UpdateRowNames(); + } + + /** + * @brief Remove row by name. + * @param pRowName row label name. + */ + void RemoveRow(const std::string& pRowName) { + ssize_t rowIdx = GetRowIdx(pRowName); + if (rowIdx < 0) { + throw std::out_of_range("row not found: " + pRowName); + } + + RemoveRow(static_cast(rowIdx)); + } + + /** + * @brief Insert row at specified index. + * @param pRowIdx zero-based row index. + * @param pRow vector of row data (optional argument). + * @param pRowName row label name (optional argument). + */ + template + void InsertRow(const size_t pRowIdx, + const std::vector& pRow = std::vector(), + const std::string& pRowName = std::string()) { + const size_t rowIdx = GetDataRowIndex(pRowIdx); + + std::vector row; + if (pRow.empty()) { + row.resize(GetDataColumnCount()); + } else { + row.resize(GetDataColumnIndex(pRow.size())); Converter converter(mConverterParams); - for (auto itCol = mData.at(dataRowIdx).begin(); itCol != mData.at(dataRowIdx).end(); ++itCol) - { - if (std::distance(mData.at(dataRowIdx).begin(), itCol) > mLabelParams.mRowNameIdx) - { - T val; - converter.ToVal(*itCol, val); - row.push_back(val); - } - } - return row; - } - - /** - * @brief Get row by index. - * @param pRowIdx zero-based row index. - * @param pToVal conversion function. - * @returns vector of row data. - */ - template - std::vector GetRow(const size_t pRowIdx, ConvFunc pToVal) const - { - const size_t dataRowIdx = GetDataRowIndex(pRowIdx); - std::vector row; - Converter converter(mConverterParams); - for (auto itCol = mData.at(dataRowIdx).begin(); itCol != mData.at(dataRowIdx).end(); ++itCol) - { - if (std::distance(mData.at(dataRowIdx).begin(), itCol) > mLabelParams.mRowNameIdx) - { - T val; - pToVal(*itCol, val); - row.push_back(val); - } - } - return row; - } - - /** - * @brief Get row by name. - * @param pRowName row label name. - * @returns vector of row data. - */ - template - std::vector GetRow(const std::string& pRowName) const - { - ssize_t rowIdx = GetRowIdx(pRowName); - if (rowIdx < 0) - { - throw std::out_of_range("row not found: " + pRowName); - } - return GetRow(static_cast(rowIdx)); - } - - /** - * @brief Get row by name. - * @param pRowName row label name. - * @param pToVal conversion function. - * @returns vector of row data. - */ - template - std::vector GetRow(const std::string& pRowName, ConvFunc pToVal) const - { - ssize_t rowIdx = GetRowIdx(pRowName); - if (rowIdx < 0) - { - throw std::out_of_range("row not found: " + pRowName); - } - return GetRow(static_cast(rowIdx), pToVal); - } - - /** - * @brief Set row by index. - * @param pRowIdx zero-based row index. - * @param pRow vector of row data. - */ - template - void SetRow(const size_t pRowIdx, const std::vector& pRow) - { - const size_t dataRowIdx = GetDataRowIndex(pRowIdx); - - while ((dataRowIdx + 1) > GetDataRowCount()) - { - std::vector row; - row.resize(GetDataColumnCount()); - mData.push_back(row); - } - - if (pRow.size() > GetDataColumnCount()) - { - for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) - { - itRow->resize(GetDataColumnIndex(pRow.size())); - } - } - - Converter converter(mConverterParams); - for (auto itCol = pRow.begin(); itCol != pRow.end(); ++itCol) - { + for (auto itCol = pRow.begin(); itCol != pRow.end(); ++itCol) { std::string str; converter.ToStr(*itCol, str); - mData.at(dataRowIdx).at(static_cast(std::distance(pRow.begin(), itCol) + mLabelParams.mRowNameIdx + 1)) = str; + row.at(static_cast(std::distance(pRow.begin(), itCol) + + mLabelParams.mRowNameIdx + 1)) = str; } } - /** - * @brief Set row by name. - * @param pRowName row label name. - * @param pRow vector of row data. - */ - template - void SetRow(const std::string& pRowName, const std::vector& pRow) - { - ssize_t rowIdx = GetRowIdx(pRowName); - if (rowIdx < 0) - { - throw std::out_of_range("row not found: " + pRowName); - } - return SetRow(static_cast(rowIdx), pRow); + while (rowIdx > GetDataRowCount()) { + std::vector tempRow; + tempRow.resize(GetDataColumnCount()); + mData.push_back(tempRow); } - /** - * @brief Remove row by index. - * @param pRowIdx zero-based row index. - */ - void RemoveRow(const size_t pRowIdx) - { - const size_t dataRowIdx = GetDataRowIndex(pRowIdx); - mData.erase(mData.begin() + static_cast(dataRowIdx)); - UpdateRowNames(); + mData.insert(mData.begin() + static_cast(rowIdx), row); + + if (!pRowName.empty()) { + SetRowName(pRowIdx, pRowName); } - /** - * @brief Remove row by name. - * @param pRowName row label name. - */ - void RemoveRow(const std::string& pRowName) - { - ssize_t rowIdx = GetRowIdx(pRowName); - if (rowIdx < 0) - { - throw std::out_of_range("row not found: " + pRowName); - } + UpdateRowNames(); + } - RemoveRow(static_cast(rowIdx)); + /** + * @brief Get number of data rows (excluding label rows). + * @returns row count. + */ + size_t GetRowCount() const { + const ssize_t count = + static_cast(mData.size()) - (mLabelParams.mColumnNameIdx + 1); + return (count >= 0) ? static_cast(count) : 0; + } + + /** + * @brief Get cell by index. + * @param pColumnIdx zero-based column index. + * @param pRowIdx zero-based row index. + * @returns cell data. + */ + template + T GetCell(const size_t pColumnIdx, const size_t pRowIdx) const { + const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); + const size_t dataRowIdx = GetDataRowIndex(pRowIdx); + + T val; + Converter converter(mConverterParams); + converter.ToVal(mData.at(dataRowIdx).at(dataColumnIdx), val); + return val; + } + + /** + * @brief Get cell by index. + * @param pColumnIdx zero-based column index. + * @param pRowIdx zero-based row index. + * @param pToVal conversion function. + * @returns cell data. + */ + template + T GetCell(const size_t pColumnIdx, const size_t pRowIdx, + ConvFunc pToVal) const { + const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); + const size_t dataRowIdx = GetDataRowIndex(pRowIdx); + + T val; + pToVal(mData.at(dataRowIdx).at(dataColumnIdx), val); + return val; + } + + /** + * @brief Get cell by name. + * @param pColumnName column label name. + * @param pRowName row label name. + * @returns cell data. + */ + template + T GetCell(const std::string& pColumnName, const std::string& pRowName) const { + const ssize_t columnIdx = GetColumnIdx(pColumnName); + if (columnIdx < 0) { + throw std::out_of_range("column not found: " + pColumnName); } - /** - * @brief Insert row at specified index. - * @param pRowIdx zero-based row index. - * @param pRow vector of row data (optional argument). - * @param pRowName row label name (optional argument). - */ - template - void InsertRow(const size_t pRowIdx, const std::vector& pRow = std::vector(), - const std::string& pRowName = std::string()) - { - const size_t rowIdx = GetDataRowIndex(pRowIdx); + const ssize_t rowIdx = GetRowIdx(pRowName); + if (rowIdx < 0) { + throw std::out_of_range("row not found: " + pRowName); + } + return GetCell(static_cast(columnIdx), + static_cast(rowIdx)); + } + + /** + * @brief Get cell by name. + * @param pColumnName column label name. + * @param pRowName row label name. + * @param pToVal conversion function. + * @returns cell data. + */ + template + T GetCell(const std::string& pColumnName, const std::string& pRowName, + ConvFunc pToVal) const { + const ssize_t columnIdx = GetColumnIdx(pColumnName); + if (columnIdx < 0) { + throw std::out_of_range("column not found: " + pColumnName); + } + + const ssize_t rowIdx = GetRowIdx(pRowName); + if (rowIdx < 0) { + throw std::out_of_range("row not found: " + pRowName); + } + + return GetCell(static_cast(columnIdx), + static_cast(rowIdx), pToVal); + } + + /** + * @brief Get cell by column name and row index. + * @param pColumnName column label name. + * @param pRowIdx zero-based row index. + * @returns cell data. + */ + template + T GetCell(const std::string& pColumnName, const size_t pRowIdx) const { + const ssize_t columnIdx = GetColumnIdx(pColumnName); + if (columnIdx < 0) { + throw std::out_of_range("column not found: " + pColumnName); + } + + return GetCell(static_cast(columnIdx), pRowIdx); + } + + /** + * @brief Get cell by column name and row index. + * @param pColumnName column label name. + * @param pRowIdx zero-based row index. + * @param pToVal conversion function. + * @returns cell data. + */ + template + T GetCell(const std::string& pColumnName, const size_t pRowIdx, + ConvFunc pToVal) const { + const ssize_t columnIdx = GetColumnIdx(pColumnName); + if (columnIdx < 0) { + throw std::out_of_range("column not found: " + pColumnName); + } + + return GetCell(static_cast(columnIdx), pRowIdx, pToVal); + } + + /** + * @brief Get cell by column index and row name. + * @param pColumnIdx zero-based column index. + * @param pRowName row label name. + * @returns cell data. + */ + template + T GetCell(const size_t pColumnIdx, const std::string& pRowName) const { + const ssize_t rowIdx = GetRowIdx(pRowName); + if (rowIdx < 0) { + throw std::out_of_range("row not found: " + pRowName); + } + + return GetCell(pColumnIdx, static_cast(rowIdx)); + } + + /** + * @brief Get cell by column index and row name. + * @param pColumnIdx zero-based column index. + * @param pRowName row label name. + * @param pToVal conversion function. + * @returns cell data. + */ + template + T GetCell(const size_t pColumnIdx, const std::string& pRowName, + ConvFunc pToVal) const { + const ssize_t rowIdx = GetRowIdx(pRowName); + if (rowIdx < 0) { + throw std::out_of_range("row not found: " + pRowName); + } + + return GetCell(pColumnIdx, static_cast(rowIdx), pToVal); + } + + /** + * @brief Set cell by index. + * @param pRowIdx zero-based row index. + * @param pColumnIdx zero-based column index. + * @param pCell cell data. + */ + template + void SetCell(const size_t pColumnIdx, const size_t pRowIdx, const T& pCell) { + const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); + const size_t dataRowIdx = GetDataRowIndex(pRowIdx); + + while ((dataRowIdx + 1) > GetDataRowCount()) { std::vector row; - if (pRow.empty()) - { - row.resize(GetDataColumnCount()); + row.resize(GetDataColumnCount()); + mData.push_back(row); + } + + if ((dataColumnIdx + 1) > GetDataColumnCount()) { + for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) { + itRow->resize(dataColumnIdx + 1); } - else - { - row.resize(GetDataColumnIndex(pRow.size())); - Converter converter(mConverterParams); - for (auto itCol = pRow.begin(); itCol != pRow.end(); ++itCol) - { - std::string str; - converter.ToStr(*itCol, str); - row.at(static_cast(std::distance(pRow.begin(), itCol) + mLabelParams.mRowNameIdx + 1)) = str; + } + + std::string str; + Converter converter(mConverterParams); + converter.ToStr(pCell, str); + mData.at(dataRowIdx).at(dataColumnIdx) = str; + } + + /** + * @brief Set cell by name. + * @param pColumnName column label name. + * @param pRowName row label name. + * @param pCell cell data. + */ + template + void SetCell(const std::string& pColumnName, const std::string& pRowName, + const T& pCell) { + const ssize_t columnIdx = GetColumnIdx(pColumnName); + if (columnIdx < 0) { + throw std::out_of_range("column not found: " + pColumnName); + } + + const ssize_t rowIdx = GetRowIdx(pRowName); + if (rowIdx < 0) { + throw std::out_of_range("row not found: " + pRowName); + } + + SetCell(static_cast(columnIdx), static_cast(rowIdx), + pCell); + } + + /** + * @brief Get column name + * @param pColumnIdx zero-based column index. + * @returns column name. + */ + std::string GetColumnName(const size_t pColumnIdx) { + const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); + if (mLabelParams.mColumnNameIdx < 0) { + throw std::out_of_range("column name row index < 0: " + + std::to_string(mLabelParams.mColumnNameIdx)); + } + + return mData.at(static_cast(mLabelParams.mColumnNameIdx)) + .at(dataColumnIdx); + } + + /** + * @brief Set column name + * @param pColumnIdx zero-based column index. + * @param pColumnName column name. + */ + void SetColumnName(size_t pColumnIdx, const std::string& pColumnName) { + if (mLabelParams.mColumnNameIdx < 0) { + throw std::out_of_range("column name row index < 0: " + + std::to_string(mLabelParams.mColumnNameIdx)); + } + + const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); + mColumnNames[pColumnName] = dataColumnIdx; + + // increase table size if necessary: + const size_t rowIdx = static_cast(mLabelParams.mColumnNameIdx); + if (rowIdx >= mData.size()) { + mData.resize(rowIdx + 1); + } + auto& row = mData[rowIdx]; + if (dataColumnIdx >= row.size()) { + row.resize(dataColumnIdx + 1); + } + + mData.at(static_cast(mLabelParams.mColumnNameIdx)) + .at(dataColumnIdx) = pColumnName; + } + + /** + * @brief Get column names + * @returns vector of column names. + */ + std::vector GetColumnNames() { + if (mLabelParams.mColumnNameIdx >= 0) { + return std::vector( + mData.at(static_cast(mLabelParams.mColumnNameIdx)).begin() + + (mLabelParams.mRowNameIdx + 1), + mData.at(static_cast(mLabelParams.mColumnNameIdx)).end()); + } + + return std::vector(); + } + + /** + * @brief Get row name + * @param pRowIdx zero-based column index. + * @returns row name. + */ + std::string GetRowName(const size_t pRowIdx) { + const size_t dataRowIdx = GetDataRowIndex(pRowIdx); + if (mLabelParams.mRowNameIdx < 0) { + throw std::out_of_range("row name column index < 0: " + + std::to_string(mLabelParams.mRowNameIdx)); + } + + return mData.at(dataRowIdx) + .at(static_cast(mLabelParams.mRowNameIdx)); + } + + /** + * @brief Set row name + * @param pRowIdx zero-based row index. + * @param pRowName row name. + */ + void SetRowName(size_t pRowIdx, const std::string& pRowName) { + const size_t dataRowIdx = GetDataRowIndex(pRowIdx); + mRowNames[pRowName] = dataRowIdx; + if (mLabelParams.mRowNameIdx < 0) { + throw std::out_of_range("row name column index < 0: " + + std::to_string(mLabelParams.mRowNameIdx)); + } + + // increase table size if necessary: + if (dataRowIdx >= mData.size()) { + mData.resize(dataRowIdx + 1); + } + auto& row = mData[dataRowIdx]; + if (mLabelParams.mRowNameIdx >= static_cast(row.size())) { + row.resize(static_cast(mLabelParams.mRowNameIdx) + 1); + } + + mData.at(dataRowIdx).at(static_cast(mLabelParams.mRowNameIdx)) = + pRowName; + } + + /** + * @brief Get row names + * @returns vector of row names. + */ + std::vector GetRowNames() { + std::vector rownames; + if (mLabelParams.mRowNameIdx >= 0) { + for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) { + if (std::distance(mData.begin(), itRow) > mLabelParams.mColumnNameIdx) { + rownames.push_back( + itRow->at(static_cast(mLabelParams.mRowNameIdx))); } } - - while (rowIdx > GetDataRowCount()) - { - std::vector tempRow; - tempRow.resize(GetDataColumnCount()); - mData.push_back(tempRow); - } - - mData.insert(mData.begin() + static_cast(rowIdx), row); - - if (!pRowName.empty()) - { - SetRowName(pRowIdx, pRowName); - } - - UpdateRowNames(); } + return rownames; + } - /** - * @brief Get number of data rows (excluding label rows). - * @returns row count. - */ - size_t GetRowCount() const - { - const ssize_t count = static_cast(mData.size()) - (mLabelParams.mColumnNameIdx + 1); - return (count >= 0) ? static_cast(count) : 0; - } + private: + void ReadCsv() { + std::ifstream stream; + stream.exceptions(std::ifstream::failbit | std::ifstream::badbit); + stream.open(mPath, std::ios::binary); + ReadCsv(stream); + } - /** - * @brief Get cell by index. - * @param pColumnIdx zero-based column index. - * @param pRowIdx zero-based row index. - * @returns cell data. - */ - template - T GetCell(const size_t pColumnIdx, const size_t pRowIdx) const - { - const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); - const size_t dataRowIdx = GetDataRowIndex(pRowIdx); + void ReadCsv(std::istream& pStream) { + Clear(); + pStream.seekg(0, std::ios::end); + std::streamsize length = pStream.tellg(); + pStream.seekg(0, std::ios::beg); - T val; - Converter converter(mConverterParams); - converter.ToVal(mData.at(dataRowIdx).at(dataColumnIdx), val); - return val; - } - - /** - * @brief Get cell by index. - * @param pColumnIdx zero-based column index. - * @param pRowIdx zero-based row index. - * @param pToVal conversion function. - * @returns cell data. - */ - template - T GetCell(const size_t pColumnIdx, const size_t pRowIdx, ConvFunc pToVal) const - { - const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); - const size_t dataRowIdx = GetDataRowIndex(pRowIdx); - - T val; - pToVal(mData.at(dataRowIdx).at(dataColumnIdx), val); - return val; - } - - /** - * @brief Get cell by name. - * @param pColumnName column label name. - * @param pRowName row label name. - * @returns cell data. - */ - template - T GetCell(const std::string& pColumnName, const std::string& pRowName) const - { - const ssize_t columnIdx = GetColumnIdx(pColumnName); - if (columnIdx < 0) - { - throw std::out_of_range("column not found: " + pColumnName); - } - - const ssize_t rowIdx = GetRowIdx(pRowName); - if (rowIdx < 0) - { - throw std::out_of_range("row not found: " + pRowName); - } - - return GetCell(static_cast(columnIdx), static_cast(rowIdx)); - } - - /** - * @brief Get cell by name. - * @param pColumnName column label name. - * @param pRowName row label name. - * @param pToVal conversion function. - * @returns cell data. - */ - template - T GetCell(const std::string& pColumnName, const std::string& pRowName, ConvFunc pToVal) const - { - const ssize_t columnIdx = GetColumnIdx(pColumnName); - if (columnIdx < 0) - { - throw std::out_of_range("column not found: " + pColumnName); - } - - const ssize_t rowIdx = GetRowIdx(pRowName); - if (rowIdx < 0) - { - throw std::out_of_range("row not found: " + pRowName); - } - - return GetCell(static_cast(columnIdx), static_cast(rowIdx), pToVal); - } - - /** - * @brief Get cell by column name and row index. - * @param pColumnName column label name. - * @param pRowIdx zero-based row index. - * @returns cell data. - */ - template - T GetCell(const std::string& pColumnName, const size_t pRowIdx) const - { - const ssize_t columnIdx = GetColumnIdx(pColumnName); - if (columnIdx < 0) - { - throw std::out_of_range("column not found: " + pColumnName); - } - - return GetCell(static_cast(columnIdx), pRowIdx); - } - - /** - * @brief Get cell by column name and row index. - * @param pColumnName column label name. - * @param pRowIdx zero-based row index. - * @param pToVal conversion function. - * @returns cell data. - */ - template - T GetCell(const std::string& pColumnName, const size_t pRowIdx, ConvFunc pToVal) const - { - const ssize_t columnIdx = GetColumnIdx(pColumnName); - if (columnIdx < 0) - { - throw std::out_of_range("column not found: " + pColumnName); - } - - return GetCell(static_cast(columnIdx), pRowIdx, pToVal); - } - - /** - * @brief Get cell by column index and row name. - * @param pColumnIdx zero-based column index. - * @param pRowName row label name. - * @returns cell data. - */ - template - T GetCell(const size_t pColumnIdx, const std::string& pRowName) const - { - const ssize_t rowIdx = GetRowIdx(pRowName); - if (rowIdx < 0) - { - throw std::out_of_range("row not found: " + pRowName); - } - - return GetCell(pColumnIdx, static_cast(rowIdx)); - } - - /** - * @brief Get cell by column index and row name. - * @param pColumnIdx zero-based column index. - * @param pRowName row label name. - * @param pToVal conversion function. - * @returns cell data. - */ - template - T GetCell(const size_t pColumnIdx, const std::string& pRowName, ConvFunc pToVal) const - { - const ssize_t rowIdx = GetRowIdx(pRowName); - if (rowIdx < 0) - { - throw std::out_of_range("row not found: " + pRowName); - } - - return GetCell(pColumnIdx, static_cast(rowIdx), pToVal); - } - - /** - * @brief Set cell by index. - * @param pRowIdx zero-based row index. - * @param pColumnIdx zero-based column index. - * @param pCell cell data. - */ - template - void SetCell(const size_t pColumnIdx, const size_t pRowIdx, const T& pCell) - { - const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); - const size_t dataRowIdx = GetDataRowIndex(pRowIdx); - - while ((dataRowIdx + 1) > GetDataRowCount()) - { - std::vector row; - row.resize(GetDataColumnCount()); - mData.push_back(row); - } - - if ((dataColumnIdx + 1) > GetDataColumnCount()) - { - for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) - { - itRow->resize(dataColumnIdx + 1); - } - } - - std::string str; - Converter converter(mConverterParams); - converter.ToStr(pCell, str); - mData.at(dataRowIdx).at(dataColumnIdx) = str; - } - - /** - * @brief Set cell by name. - * @param pColumnName column label name. - * @param pRowName row label name. - * @param pCell cell data. - */ - template - void SetCell(const std::string& pColumnName, const std::string& pRowName, const T& pCell) - { - const ssize_t columnIdx = GetColumnIdx(pColumnName); - if (columnIdx < 0) - { - throw std::out_of_range("column not found: " + pColumnName); - } - - const ssize_t rowIdx = GetRowIdx(pRowName); - if (rowIdx < 0) - { - throw std::out_of_range("row not found: " + pRowName); - } - - SetCell(static_cast(columnIdx), static_cast(rowIdx), pCell); - } - - /** - * @brief Get column name - * @param pColumnIdx zero-based column index. - * @returns column name. - */ - std::string GetColumnName(const size_t pColumnIdx) - { - const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); - if (mLabelParams.mColumnNameIdx < 0) - { - throw std::out_of_range("column name row index < 0: " + std::to_string(mLabelParams.mColumnNameIdx)); - } - - return mData.at(static_cast(mLabelParams.mColumnNameIdx)).at(dataColumnIdx); - } - - /** - * @brief Set column name - * @param pColumnIdx zero-based column index. - * @param pColumnName column name. - */ - void SetColumnName(size_t pColumnIdx, const std::string& pColumnName) - { - if (mLabelParams.mColumnNameIdx < 0) - { - throw std::out_of_range("column name row index < 0: " + std::to_string(mLabelParams.mColumnNameIdx)); - } - - const size_t dataColumnIdx = GetDataColumnIndex(pColumnIdx); - mColumnNames[pColumnName] = dataColumnIdx; - - // increase table size if necessary: - const size_t rowIdx = static_cast(mLabelParams.mColumnNameIdx); - if (rowIdx >= mData.size()) - { - mData.resize(rowIdx + 1); - } - auto& row = mData[rowIdx]; - if (dataColumnIdx >= row.size()) - { - row.resize(dataColumnIdx + 1); - } - - mData.at(static_cast(mLabelParams.mColumnNameIdx)).at(dataColumnIdx) = pColumnName; - } - - /** - * @brief Get column names - * @returns vector of column names. - */ - std::vector GetColumnNames() - { - if (mLabelParams.mColumnNameIdx >= 0) - { - return std::vector(mData.at(static_cast(mLabelParams.mColumnNameIdx)).begin() + - (mLabelParams.mRowNameIdx + 1), - mData.at(static_cast(mLabelParams.mColumnNameIdx)).end()); - } - - return std::vector(); - } - - /** - * @brief Get row name - * @param pRowIdx zero-based column index. - * @returns row name. - */ - std::string GetRowName(const size_t pRowIdx) - { - const size_t dataRowIdx = GetDataRowIndex(pRowIdx); - if (mLabelParams.mRowNameIdx < 0) - { - throw std::out_of_range("row name column index < 0: " + std::to_string(mLabelParams.mRowNameIdx)); - } - - return mData.at(dataRowIdx).at(static_cast(mLabelParams.mRowNameIdx)); - } - - /** - * @brief Set row name - * @param pRowIdx zero-based row index. - * @param pRowName row name. - */ - void SetRowName(size_t pRowIdx, const std::string& pRowName) - { - const size_t dataRowIdx = GetDataRowIndex(pRowIdx); - mRowNames[pRowName] = dataRowIdx; - if (mLabelParams.mRowNameIdx < 0) - { - throw std::out_of_range("row name column index < 0: " + std::to_string(mLabelParams.mRowNameIdx)); - } - - // increase table size if necessary: - if (dataRowIdx >= mData.size()) - { - mData.resize(dataRowIdx + 1); - } - auto& row = mData[dataRowIdx]; - if (mLabelParams.mRowNameIdx >= static_cast(row.size())) - { - row.resize(static_cast(mLabelParams.mRowNameIdx) + 1); - } - - mData.at(dataRowIdx).at(static_cast(mLabelParams.mRowNameIdx)) = pRowName; - } - - /** - * @brief Get row names - * @returns vector of row names. - */ - std::vector GetRowNames() - { - std::vector rownames; - if (mLabelParams.mRowNameIdx >= 0) - { - for (auto itRow = mData.begin(); itRow != mData.end(); ++itRow) - { - if (std::distance(mData.begin(), itRow) > mLabelParams.mColumnNameIdx) - { - rownames.push_back(itRow->at(static_cast(mLabelParams.mRowNameIdx))); - } - } - } - return rownames; - } - - private: - void ReadCsv() - { - std::ifstream stream; - stream.exceptions(std::ifstream::failbit | std::ifstream::badbit); - stream.open(mPath, std::ios::binary); - ReadCsv(stream); - } - - void ReadCsv(std::istream& pStream) - { - Clear(); - pStream.seekg(0, std::ios::end); - std::streamsize length = pStream.tellg(); +#ifdef HAS_CODECVT + std::vector bom2b(2, '\0'); + if (length >= 2) { + pStream.read(bom2b.data(), 2); pStream.seekg(0, std::ios::beg); - -#ifdef HAS_CODECVT - std::vector bom2b(2, '\0'); - if (length >= 2) - { - pStream.read(bom2b.data(), 2); - pStream.seekg(0, std::ios::beg); - } - - static const std::vector bomU16le = { '\xff', '\xfe' }; - static const std::vector bomU16be = { '\xfe', '\xff' }; - if ((bom2b == bomU16le) || (bom2b == bomU16be)) - { - mIsUtf16 = true; - mIsLE = (bom2b == bomU16le); - - std::wifstream wstream; - wstream.exceptions(std::wifstream::failbit | std::wifstream::badbit); - wstream.open(mPath, std::ios::binary); - if (mIsLE) - { - wstream.imbue(std::locale(wstream.getloc(), - new std::codecvt_utf16(std::consume_header | - std::little_endian)>)); - } - else - { - wstream.imbue(std::locale(wstream.getloc(), - new std::codecvt_utf16)); - } - std::wstringstream wss; - wss << wstream.rdbuf(); - std::string utf8 = ToString(wss.str()); - std::stringstream ss(utf8); - ParseCsv(ss, static_cast(utf8.size())); - } - else -#endif - { - // check for UTF-8 Byte order mark and skip it when found - if (length >= 3) - { - std::vector bom3b(3, '\0'); - pStream.read(bom3b.data(), 3); - static const std::vector bomU8 = { '\xef', '\xbb', '\xbf' }; - if (bom3b != bomU8) - { - // file does not start with a UTF-8 Byte order mark - pStream.seekg(0, std::ios::beg); - } - else - { - // file did start with a UTF-8 Byte order mark, simply skip it - length -= 3; - } - } - - ParseCsv(pStream, length); - } } - void ParseCsv(std::istream& pStream, std::streamsize p_FileLength) + static const std::vector bomU16le = {'\xff', '\xfe'}; + static const std::vector bomU16be = {'\xfe', '\xff'}; + if ((bom2b == bomU16le) || (bom2b == bomU16be)) { + mIsUtf16 = true; + mIsLE = (bom2b == bomU16le); + + std::wifstream wstream; + wstream.exceptions(std::wifstream::failbit | std::wifstream::badbit); + wstream.open(mPath, std::ios::binary); + if (mIsLE) { + wstream.imbue(std::locale( + wstream.getloc(), + new std::codecvt_utf16( + std::consume_header | std::little_endian)>)); + } else { + wstream.imbue(std::locale( + wstream.getloc(), + new std::codecvt_utf16)); + } + std::wstringstream wss; + wss << wstream.rdbuf(); + std::string utf8 = ToString(wss.str()); + std::stringstream ss(utf8); + ParseCsv(ss, static_cast(utf8.size())); + } else +#endif { - const std::streamsize bufLength = 64 * 1024; - std::vector buffer(bufLength); - std::vector row; - std::string cell; - bool quoted = false; - int cr = 0; - int lf = 0; - - while (p_FileLength > 0) - { - const std::streamsize toReadLength = std::min(p_FileLength, bufLength); - pStream.read(buffer.data(), toReadLength); - - // With user-specified istream opened in non-binary mode on windows, we may have a - // data length mismatch, so ensure we don't parse outside actual data length read. - const std::streamsize readLength = pStream.gcount(); - if (readLength <= 0) - { - break; + // check for UTF-8 Byte order mark and skip it when found + if (length >= 3) { + std::vector bom3b(3, '\0'); + pStream.read(bom3b.data(), 3); + static const std::vector bomU8 = {'\xef', '\xbb', '\xbf'}; + if (bom3b != bomU8) { + // file does not start with a UTF-8 Byte order mark + pStream.seekg(0, std::ios::beg); + } else { + // file did start with a UTF-8 Byte order mark, simply skip it + length -= 3; } + } - for (size_t i = 0; i < static_cast(readLength); ++i) - { - if (buffer[i] == '"') - { - if (cell.empty() || cell[0] == '"') - { - quoted = !quoted; - } + ParseCsv(pStream, length); + } + } + + void ParseCsv(std::istream& pStream, std::streamsize p_FileLength) { + const std::streamsize bufLength = 64 * 1024; + std::vector buffer(bufLength); + std::vector row; + std::string cell; + bool quoted = false; + int cr = 0; + int lf = 0; + + while (p_FileLength > 0) { + const std::streamsize toReadLength = + std::min(p_FileLength, bufLength); + pStream.read(buffer.data(), toReadLength); + + // With user-specified istream opened in non-binary mode on windows, we + // may have a data length mismatch, so ensure we don't parse outside + // actual data length read. + const std::streamsize readLength = pStream.gcount(); + if (readLength <= 0) { + break; + } + + for (size_t i = 0; i < static_cast(readLength); ++i) { + if (buffer[i] == '"') { + if (cell.empty() || cell[0] == '"') { + quoted = !quoted; + } + cell += buffer[i]; + } else if (buffer[i] == mSeparatorParams.mSeparator) { + if (!quoted) { + row.push_back(Unquote(Trim(cell))); + cell.clear(); + } else { cell += buffer[i]; } - else if (buffer[i] == mSeparatorParams.mSeparator) - { - if (!quoted) - { + } else if (buffer[i] == '\r') { + if (mSeparatorParams.mQuotedLinebreaks && quoted) { + cell += buffer[i]; + } else { + ++cr; + } + } else if (buffer[i] == '\n') { + if (mSeparatorParams.mQuotedLinebreaks && quoted) { + cell += buffer[i]; + } else { + ++lf; + if (mLineReaderParams.mSkipEmptyLines && row.empty() && + cell.empty()) { + // skip empty line + } else { row.push_back(Unquote(Trim(cell))); + + if (mLineReaderParams.mSkipCommentLines && !row.at(0).empty() && + (row.at(0)[0] == mLineReaderParams.mCommentPrefix)) { + // skip comment line + } else { + mData.push_back(row); + } + cell.clear(); - } - else - { - cell += buffer[i]; + row.clear(); + quoted = false; } } - else if (buffer[i] == '\r') - { - if (mSeparatorParams.mQuotedLinebreaks && quoted) - { - cell += buffer[i]; - } - else - { - ++cr; - } - } - else if (buffer[i] == '\n') - { - if (mSeparatorParams.mQuotedLinebreaks && quoted) - { - cell += buffer[i]; - } - else - { - ++lf; - if (mLineReaderParams.mSkipEmptyLines && row.empty() && cell.empty()) - { - // skip empty line - } - else - { - row.push_back(Unquote(Trim(cell))); - - if (mLineReaderParams.mSkipCommentLines && !row.at(0).empty() && - (row.at(0)[0] == mLineReaderParams.mCommentPrefix)) - { - // skip comment line - } - else - { - mData.push_back(row); - } - - cell.clear(); - row.clear(); - quoted = false; - } - } - } - else - { - cell += buffer[i]; - } + } else { + cell += buffer[i]; } - p_FileLength -= readLength; } - - // Handle last line without linebreak - if (!cell.empty() || !row.empty()) - { - row.push_back(Unquote(Trim(cell))); - cell.clear(); - mData.push_back(row); - row.clear(); - } - - // Assume CR/LF if at least half the linebreaks have CR - mSeparatorParams.mHasCR = (cr > (lf / 2)); - - // Set up column labels - UpdateColumnNames(); - - // Set up row labels - UpdateRowNames(); + p_FileLength -= readLength; } - void WriteCsv() const - { + // Handle last line without linebreak + if (!cell.empty() || !row.empty()) { + row.push_back(Unquote(Trim(cell))); + cell.clear(); + mData.push_back(row); + row.clear(); + } + + // Assume CR/LF if at least half the linebreaks have CR + mSeparatorParams.mHasCR = (cr > (lf / 2)); + + // Set up column labels + UpdateColumnNames(); + + // Set up row labels + UpdateRowNames(); + } + + void WriteCsv() const { #ifdef HAS_CODECVT - if (mIsUtf16) - { - std::stringstream ss; - WriteCsv(ss); - std::string utf8 = ss.str(); - std::wstring wstr = ToWString(utf8); + if (mIsUtf16) { + std::stringstream ss; + WriteCsv(ss); + std::string utf8 = ss.str(); + std::wstring wstr = ToWString(utf8); - std::wofstream wstream; - wstream.exceptions(std::wofstream::failbit | std::wofstream::badbit); - wstream.open(mPath, std::ios::binary | std::ios::trunc); + std::wofstream wstream; + wstream.exceptions(std::wofstream::failbit | std::wofstream::badbit); + wstream.open(mPath, std::ios::binary | std::ios::trunc); - if (mIsLE) - { - wstream.imbue(std::locale(wstream.getloc(), - new std::codecvt_utf16(std::little_endian)>)); - } - else - { - wstream.imbue(std::locale(wstream.getloc(), - new std::codecvt_utf16)); - } - - wstream << static_cast(0xfeff); - wstream << wstr; + if (mIsLE) { + wstream.imbue( + std::locale(wstream.getloc(), + new std::codecvt_utf16( + std::little_endian)>)); + } else { + wstream.imbue(std::locale(wstream.getloc(), + new std::codecvt_utf16)); } - else + + wstream << static_cast(0xfeff); + wstream << wstr; + } else #endif - { - std::ofstream stream; - stream.exceptions(std::ofstream::failbit | std::ofstream::badbit); - stream.open(mPath, std::ios::binary | std::ios::trunc); - WriteCsv(stream); - } - } - - void WriteCsv(std::ostream& pStream) const { - for (auto itr = mData.begin(); itr != mData.end(); ++itr) - { - for (auto itc = itr->begin(); itc != itr->end(); ++itc) - { - if (mSeparatorParams.mAutoQuote && - ((itc->find(mSeparatorParams.mSeparator) != std::string::npos) || - (itc->find(' ') != std::string::npos))) - { - // escape quotes in string - std::string str = *itc; - ReplaceString(str, "\"", "\"\""); + std::ofstream stream; + stream.exceptions(std::ofstream::failbit | std::ofstream::badbit); + stream.open(mPath, std::ios::binary | std::ios::trunc); + WriteCsv(stream); + } + } - pStream << "\"" << str << "\""; - } - else - { - pStream << *itc; - } + void WriteCsv(std::ostream& pStream) const { + for (auto itr = mData.begin(); itr != mData.end(); ++itr) { + for (auto itc = itr->begin(); itc != itr->end(); ++itc) { + if (mSeparatorParams.mAutoQuote && + ((itc->find(mSeparatorParams.mSeparator) != std::string::npos) || + (itc->find(' ') != std::string::npos))) { + // escape quotes in string + std::string str = *itc; + ReplaceString(str, "\"", "\"\""); - if (std::distance(itc, itr->end()) > 1) - { - pStream << mSeparatorParams.mSeparator; - } + pStream << "\"" << str << "\""; + } else { + pStream << *itc; } - pStream << (mSeparatorParams.mHasCR ? "\r\n" : "\n"); + + if (std::distance(itc, itr->end()) > 1) { + pStream << mSeparatorParams.mSeparator; + } + } + pStream << (mSeparatorParams.mHasCR ? "\r\n" : "\n"); + } + } + + size_t GetDataRowCount() const { return mData.size(); } + + size_t GetDataColumnCount() const { + return (mData.size() > 0) ? mData.at(0).size() : 0; + } + + inline size_t GetDataRowIndex(const size_t pRowIdx) const { + return pRowIdx + static_cast(mLabelParams.mColumnNameIdx + 1); + } + + inline size_t GetDataColumnIndex(const size_t pColumnIdx) const { + return pColumnIdx + static_cast(mLabelParams.mRowNameIdx + 1); + } + + std::string Trim(const std::string& pStr) { + if (mSeparatorParams.mTrim) { + std::string str = pStr; + + // ltrim + str.erase(str.begin(), std::find_if(str.begin(), str.end(), + [](int ch) { return !isspace(ch); })); + + // rtrim + str.erase(std::find_if(str.rbegin(), str.rend(), + [](int ch) { return !isspace(ch); }) + .base(), + str.end()); + + return str; + } else { + return pStr; + } + } + + std::string Unquote(const std::string& pStr) { + if (mSeparatorParams.mAutoQuote && (pStr.size() >= 2) && + (pStr.front() == '"') && (pStr.back() == '"')) { + // remove start/end quotes + std::string str = pStr.substr(1, pStr.size() - 2); + + // unescape quotes in string + ReplaceString(str, "\"\"", "\""); + + return str; + } else { + return pStr; + } + } + + void UpdateColumnNames() { + mColumnNames.clear(); + if ((mLabelParams.mColumnNameIdx >= 0) && + (static_cast(mData.size()) > mLabelParams.mColumnNameIdx)) { + size_t i = 0; + for (auto& columnName : + mData[static_cast(mLabelParams.mColumnNameIdx)]) { + mColumnNames[columnName] = i++; } } + } - size_t GetDataRowCount() const - { - return mData.size(); - } - - size_t GetDataColumnCount() const - { - return (mData.size() > 0) ? mData.at(0).size() : 0; - } - - inline size_t GetDataRowIndex(const size_t pRowIdx) const - { - return pRowIdx + static_cast(mLabelParams.mColumnNameIdx + 1); - } - - inline size_t GetDataColumnIndex(const size_t pColumnIdx) const - { - return pColumnIdx + static_cast(mLabelParams.mRowNameIdx + 1); - } - - std::string Trim(const std::string& pStr) - { - if (mSeparatorParams.mTrim) - { - std::string str = pStr; - - // ltrim - str.erase(str.begin(), std::find_if(str.begin(), str.end(), [](int ch) { return !isspace(ch); })); - - // rtrim - str.erase(std::find_if(str.rbegin(), str.rend(), [](int ch) { return !isspace(ch); }).base(), str.end()); - - return str; - } - else - { - return pStr; - } - } - - std::string Unquote(const std::string& pStr) - { - if (mSeparatorParams.mAutoQuote && (pStr.size() >= 2) && (pStr.front() == '"') && (pStr.back() == '"')) - { - // remove start/end quotes - std::string str = pStr.substr(1, pStr.size() - 2); - - // unescape quotes in string - ReplaceString(str, "\"\"", "\""); - - return str; - } - else - { - return pStr; - } - } - - void UpdateColumnNames() - { - mColumnNames.clear(); - if ((mLabelParams.mColumnNameIdx >= 0) && - (static_cast(mData.size()) > mLabelParams.mColumnNameIdx)) - { - size_t i = 0; - for (auto& columnName : mData[static_cast(mLabelParams.mColumnNameIdx)]) - { - mColumnNames[columnName] = i++; - } - } - } - - void UpdateRowNames() - { - mRowNames.clear(); - if ((mLabelParams.mRowNameIdx >= 0) && - (static_cast(mData.size()) > - (mLabelParams.mColumnNameIdx + 1))) - { - size_t i = 0; - for (auto& dataRow : mData) - { - if (static_cast(dataRow.size()) > mLabelParams.mRowNameIdx) - { - mRowNames[dataRow[static_cast(mLabelParams.mRowNameIdx)]] = i++; - } + void UpdateRowNames() { + mRowNames.clear(); + if ((mLabelParams.mRowNameIdx >= 0) && + (static_cast(mData.size()) > + (mLabelParams.mColumnNameIdx + 1))) { + size_t i = 0; + for (auto& dataRow : mData) { + if (static_cast(dataRow.size()) > mLabelParams.mRowNameIdx) { + mRowNames[dataRow[static_cast(mLabelParams.mRowNameIdx)]] = + i++; } } } + } #ifdef HAS_CODECVT #if defined(_MSC_VER) -#pragma warning (push) -#pragma warning (disable: 4996) +#pragma warning(push) +#pragma warning(disable : 4996) #endif - static std::string ToString(const std::wstring& pWStr) - { - return std::wstring_convert, wchar_t>{ }.to_bytes(pWStr); - } + static std::string ToString(const std::wstring& pWStr) { + return std::wstring_convert, wchar_t>{}.to_bytes( + pWStr); + } - static std::wstring ToWString(const std::string& pStr) - { - return std::wstring_convert, wchar_t>{ }.from_bytes(pStr); - } + static std::wstring ToWString(const std::string& pStr) { + return std::wstring_convert, wchar_t>{} + .from_bytes(pStr); + } #if defined(_MSC_VER) -#pragma warning (pop) +#pragma warning(pop) #endif #endif - static void ReplaceString(std::string& pStr, const std::string& pSearch, const std::string& pReplace) - { - size_t pos = 0; + static void ReplaceString(std::string& pStr, const std::string& pSearch, + const std::string& pReplace) { + size_t pos = 0; - while ((pos = pStr.find(pSearch, pos)) != std::string::npos) - { - pStr.replace(pos, pSearch.size(), pReplace); - pos += pReplace.size(); - } + while ((pos = pStr.find(pSearch, pos)) != std::string::npos) { + pStr.replace(pos, pSearch.size(), pReplace); + pos += pReplace.size(); } + } - private: - std::string mPath; - LabelParams mLabelParams; - SeparatorParams mSeparatorParams; - ConverterParams mConverterParams; - LineReaderParams mLineReaderParams; - std::vector> mData; - std::map mColumnNames; - std::map mRowNames; + private: + std::string mPath; + LabelParams mLabelParams; + SeparatorParams mSeparatorParams; + ConverterParams mConverterParams; + LineReaderParams mLineReaderParams; + std::vector> mData; + std::map mColumnNames; + std::map mRowNames; #ifdef HAS_CODECVT - bool mIsUtf16 = false; - bool mIsLE = false; + bool mIsUtf16 = false; + bool mIsLE = false; #endif - }; -} +}; +} // namespace rapidcsv diff --git a/libs/libpcf/src/io/read_csv_io_pin_table.cpp b/libs/libpcf/src/io/read_csv_io_pin_table.cpp index 4838c7c8b..18bc0499c 100644 --- a/libs/libpcf/src/io/read_csv_io_pin_table.cpp +++ b/libs/libpcf/src/io/read_csv_io_pin_table.cpp @@ -7,14 +7,12 @@ /* Headers from vtr util library */ #include "vtr_assert.h" -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from libopenfpga util library */ #include "openfpga_port_parser.h" - #include "rapidcsv.h" - #include "read_csv_io_pin_table.h" /* Begin namespace openfpga */ @@ -32,12 +30,13 @@ IoPinTable read_csv_io_pin_table(const char* fname) { rapidcsv::SeparatorParams(',')); /* TODO: Move this to constants */ - std::map side_str_map { {"TOP", TOP}, {"RIGHT", RIGHT}, {"LEFT", LEFT}, {"BOTTOM", BOTTOM} }; + std::map side_str_map{ + {"TOP", TOP}, {"RIGHT", RIGHT}, {"LEFT", LEFT}, {"BOTTOM", BOTTOM}}; int num_rows = doc.GetRowCount(); io_pin_table.reserve_pins(num_rows); - for (int irow = 1; irow < num_rows; irow++) { + for (int irow = 1; irow < num_rows; irow++) { std::vector row_vec = doc.GetRow(irow); IoPinTableId pin_id = io_pin_table.create_pin(); /* Fill pin-level information */ @@ -49,19 +48,25 @@ IoPinTable read_csv_io_pin_table(const char* fname) { std::string pin_side_str = row_vec.at(0); if (side_str_map.end() == side_str_map.find(pin_side_str)) { - VTR_LOG("Invalid side defintion (='%s')! Expect [TOP|RIGHT|LEFT|BOTTOM]\n", pin_side_str.c_str()); + VTR_LOG( + "Invalid side defintion (='%s')! Expect [TOP|RIGHT|LEFT|BOTTOM]\n", + pin_side_str.c_str()); exit(1); } else { io_pin_table.set_pin_side(pin_id, side_str_map[pin_side_str]); } - /*This is not general purpose: we should have an explicit attribute in the csv file to decalare direction */ - if (internal_pin_parser.port().get_name().find("A2F") != std::string::npos) { + /*This is not general purpose: we should have an explicit attribute in the + * csv file to decalare direction */ + if (internal_pin_parser.port().get_name().find("A2F") != + std::string::npos) { io_pin_table.set_pin_direction(pin_id, IoPinTable::INPUT); - } else if (internal_pin_parser.port().get_name().find("F2A") != std::string::npos) { + } else if (internal_pin_parser.port().get_name().find("F2A") != + std::string::npos) { io_pin_table.set_pin_direction(pin_id, IoPinTable::OUTPUT); } else { - VTR_LOG("Invalid direction defintion! Expect [A2F|F2A] in the pin name\n"); + VTR_LOG( + "Invalid direction defintion! Expect [A2F|F2A] in the pin name\n"); exit(1); } } @@ -70,6 +75,3 @@ IoPinTable read_csv_io_pin_table(const char* fname) { } } /* End namespace openfpga*/ - - - diff --git a/libs/libpcf/src/io/read_csv_io_pin_table.h b/libs/libpcf/src/io/read_csv_io_pin_table.h index 3da916b53..c82b5f9cf 100644 --- a/libs/libpcf/src/io/read_csv_io_pin_table.h +++ b/libs/libpcf/src/io/read_csv_io_pin_table.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "io_pin_table.h" /******************************************************************** diff --git a/libs/libpcf/src/io/read_xml_io_location_map.cpp b/libs/libpcf/src/io/read_xml_io_location_map.cpp index b6de60d76..689c3758f 100644 --- a/libs/libpcf/src/io/read_xml_io_location_map.cpp +++ b/libs/libpcf/src/io/read_xml_io_location_map.cpp @@ -18,9 +18,8 @@ /* Headers from libarchfpga */ #include "arch_error.h" -#include "read_xml_util.h" - #include "read_xml_io_location_map.h" +#include "read_xml_util.h" /* Begin namespace openfpga */ namespace openfpga { @@ -28,11 +27,11 @@ namespace openfpga { /******************************************************************** * Parse XML codes of a to an object of PinConstraint *******************************************************************/ -static -void read_xml_one_io_location(pugi::xml_node& xml_io, - const pugiutil::loc_data& loc_data, - IoLocationMap& io_location_map) { - openfpga::PortParser port_parser(get_attribute(xml_io, "pad", loc_data).as_string()); +static void read_xml_one_io_location(pugi::xml_node& xml_io, + const pugiutil::loc_data& loc_data, + IoLocationMap& io_location_map) { + openfpga::PortParser port_parser( + get_attribute(xml_io, "pad", loc_data).as_string()); int x_coord = get_attribute(xml_io, "x", loc_data).as_int(); int y_coord = get_attribute(xml_io, "y", loc_data).as_int(); @@ -41,7 +40,8 @@ void read_xml_one_io_location(pugi::xml_node& xml_io, /* Sanity checks */ if (x_coord < 0 || y_coord < 0 || z_coord < 0) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_io), - "Invalid coordinate (x, y, z) = (%d, %d, %d)! Expect zero or a positive integer!\n", + "Invalid coordinate (x, y, z) = (%d, %d, %d)! Expect zero " + "or a positive integer!\n", x_coord, y_coord, z_coord); } if (port_parser.port().get_width() != 1) { @@ -49,14 +49,15 @@ void read_xml_one_io_location(pugi::xml_node& xml_io, "I/O (%s) does not have a port size of 1!\n", get_attribute(xml_io, "pad", loc_data).as_string()); } - io_location_map.set_io_index(size_t(x_coord), size_t(y_coord), size_t(z_coord), port_parser.port().get_name(), port_parser.port().get_lsb()); + io_location_map.set_io_index(size_t(x_coord), size_t(y_coord), + size_t(z_coord), port_parser.port().get_name(), + port_parser.port().get_lsb()); } /******************************************************************** * Parse XML codes about to an object of PinConstraints *******************************************************************/ IoLocationMap read_xml_io_location_map(const char* fname) { - vtr::ScopedStartFinishTimer timer("Read I/O Location Map"); IoLocationMap io_location_map; @@ -70,7 +71,8 @@ IoLocationMap read_xml_io_location_map(const char* fname) { pugi::xml_node xml_root = get_single_child(doc, "io_coordinates", loc_data); - /*size_t num_children = std::distance(xml_root.children().begin(), xml_root.children().end()); + /*size_t num_children = std::distance(xml_root.children().begin(), + * xml_root.children().end()); * TODO: Reserve memory space for efficiency */ for (pugi::xml_node xml_io : xml_root.children()) { @@ -79,15 +81,12 @@ IoLocationMap read_xml_io_location_map(const char* fname) { bad_tag(xml_io, loc_data, xml_root, {"io"}); } read_xml_one_io_location(xml_io, loc_data, io_location_map); - } + } } catch (pugiutil::XmlError& e) { - archfpga_throw(fname, e.line(), - "%s", e.what()); + archfpga_throw(fname, e.line(), "%s", e.what()); } - return io_location_map; + return io_location_map; } } /* End namespace openfpga*/ - - diff --git a/libs/libpcf/src/io/read_xml_pin_constraints.cpp b/libs/libpcf/src/io/read_xml_pin_constraints.cpp index 98527cb32..b034aa3dd 100644 --- a/libs/libpcf/src/io/read_xml_pin_constraints.cpp +++ b/libs/libpcf/src/io/read_xml_pin_constraints.cpp @@ -18,36 +18,41 @@ /* Headers from libarchfpga */ #include "arch_error.h" -#include "read_xml_util.h" - #include "read_xml_pin_constraints.h" +#include "read_xml_util.h" /******************************************************************** * Parse XML codes of a to an object of PinConstraint *******************************************************************/ -static -void read_xml_pin_constraint(pugi::xml_node& xml_pin_constraint, - const pugiutil::loc_data& loc_data, - PinConstraints& pin_constraints) { +static void read_xml_pin_constraint(pugi::xml_node& xml_pin_constraint, + const pugiutil::loc_data& loc_data, + PinConstraints& pin_constraints) { + openfpga::PortParser port_parser( + get_attribute(xml_pin_constraint, "pin", loc_data).as_string()); - openfpga::PortParser port_parser(get_attribute(xml_pin_constraint, "pin", loc_data).as_string()); - - std::string net_name = get_attribute(xml_pin_constraint, "net", loc_data).as_string(); + std::string net_name = + get_attribute(xml_pin_constraint, "net", loc_data).as_string(); /* Create a new pin constraint in the storage */ - PinConstraintId pin_constraint_id = pin_constraints.create_pin_constraint(port_parser.port(), net_name); + PinConstraintId pin_constraint_id = + pin_constraints.create_pin_constraint(port_parser.port(), net_name); if (false == pin_constraints.valid_pin_constraint_id(pin_constraint_id)) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin_constraint), "Fail to create pin constraint!\n"); } - + /* Set default value if defined */ - std::string default_value = get_attribute(xml_pin_constraint, "default_value", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(); + std::string default_value = + get_attribute(xml_pin_constraint, "default_value", loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_string(); pin_constraints.set_net_default_value(pin_constraint_id, default_value); - if (!default_value.empty() && !pin_constraints.valid_net_default_value(pin_constraint_id)) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin_constraint), - "Invalid default value for pin constraints. Expect [0|1]!\n"); + if (!default_value.empty() && + !pin_constraints.valid_net_default_value(pin_constraint_id)) { + archfpga_throw( + loc_data.filename_c_str(), loc_data.line(xml_pin_constraint), + "Invalid default value for pin constraints. Expect [0|1]!\n"); } } @@ -55,7 +60,6 @@ void read_xml_pin_constraint(pugi::xml_node& xml_pin_constraint, * Parse XML codes about to an object of PinConstraints *******************************************************************/ PinConstraints read_xml_pin_constraints(const char* pin_constraint_fname) { - vtr::ScopedStartFinishTimer timer("Read Pin Constraints"); PinConstraints pin_constraints; @@ -67,9 +71,11 @@ PinConstraints read_xml_pin_constraints(const char* pin_constraint_fname) { try { loc_data = pugiutil::load_xml(doc, pin_constraint_fname); - pugi::xml_node xml_root = get_single_child(doc, "pin_constraints", loc_data); + pugi::xml_node xml_root = + get_single_child(doc, "pin_constraints", loc_data); - size_t num_pin_constraints = std::distance(xml_root.children().begin(), xml_root.children().end()); + size_t num_pin_constraints = + std::distance(xml_root.children().begin(), xml_root.children().end()); /* Reserve memory space for the region */ pin_constraints.reserve_pin_constraints(num_pin_constraints); @@ -79,12 +85,10 @@ PinConstraints read_xml_pin_constraints(const char* pin_constraint_fname) { bad_tag(xml_pin_constraint, loc_data, xml_root, {"set_io"}); } read_xml_pin_constraint(xml_pin_constraint, loc_data, pin_constraints); - } + } } catch (pugiutil::XmlError& e) { - archfpga_throw(pin_constraint_fname, e.line(), - "%s", e.what()); + archfpga_throw(pin_constraint_fname, e.line(), "%s", e.what()); } - return pin_constraints; + return pin_constraints; } - diff --git a/libs/libpcf/src/io/read_xml_pin_constraints.h b/libs/libpcf/src/io/read_xml_pin_constraints.h index 45065be26..96f61571d 100644 --- a/libs/libpcf/src/io/read_xml_pin_constraints.h +++ b/libs/libpcf/src/io/read_xml_pin_constraints.h @@ -4,9 +4,9 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "pugixml_util.hpp" -#include "pugixml.hpp" #include "pin_constraints.h" +#include "pugixml.hpp" +#include "pugixml_util.hpp" /******************************************************************** * Function declaration diff --git a/libs/libpcf/src/io/read_xml_repack_design_constraints.cpp b/libs/libpcf/src/io/read_xml_repack_design_constraints.cpp index dbf773748..008aac3ca 100644 --- a/libs/libpcf/src/io/read_xml_repack_design_constraints.cpp +++ b/libs/libpcf/src/io/read_xml_repack_design_constraints.cpp @@ -18,43 +18,46 @@ /* Headers from libarchfpga */ #include "arch_error.h" -#include "read_xml_util.h" - #include "read_xml_repack_design_constraints.h" +#include "read_xml_util.h" /******************************************************************** * Parse XML codes of a to an object of FabricKey *******************************************************************/ -static -void read_xml_pin_constraint(pugi::xml_node& xml_pin_constraint, - const pugiutil::loc_data& loc_data, - RepackDesignConstraints& repack_design_constraints) { - +static void read_xml_pin_constraint( + pugi::xml_node& xml_pin_constraint, const pugiutil::loc_data& loc_data, + RepackDesignConstraints& repack_design_constraints) { /* Create a new design constraint in the storage */ - RepackDesignConstraintId design_constraint_id = repack_design_constraints.create_design_constraint(RepackDesignConstraints::PIN_ASSIGNMENT); + RepackDesignConstraintId design_constraint_id = + repack_design_constraints.create_design_constraint( + RepackDesignConstraints::PIN_ASSIGNMENT); - if (false == repack_design_constraints.valid_design_constraint_id(design_constraint_id)) { + if (false == repack_design_constraints.valid_design_constraint_id( + design_constraint_id)) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin_constraint), "Fail to create design constraint!\n"); } - repack_design_constraints.set_pb_type(design_constraint_id, - get_attribute(xml_pin_constraint, "pb_type", loc_data).as_string()); + repack_design_constraints.set_pb_type( + design_constraint_id, + get_attribute(xml_pin_constraint, "pb_type", loc_data).as_string()); - openfpga::PortParser port_parser(get_attribute(xml_pin_constraint, "pin", loc_data).as_string()); + openfpga::PortParser port_parser( + get_attribute(xml_pin_constraint, "pin", loc_data).as_string()); - repack_design_constraints.set_pin(design_constraint_id, - port_parser.port()); + repack_design_constraints.set_pin(design_constraint_id, port_parser.port()); - repack_design_constraints.set_net(design_constraint_id, - get_attribute(xml_pin_constraint, "net", loc_data).as_string()); + repack_design_constraints.set_net( + design_constraint_id, + get_attribute(xml_pin_constraint, "net", loc_data).as_string()); } /******************************************************************** - * Parse XML codes about to an object of RepackDesignConstraints + * Parse XML codes about to an object of + *RepackDesignConstraints *******************************************************************/ -RepackDesignConstraints read_xml_repack_design_constraints(const char* design_constraint_fname) { - +RepackDesignConstraints read_xml_repack_design_constraints( + const char* design_constraint_fname) { vtr::ScopedStartFinishTimer timer("Read Repack Design Constraints"); RepackDesignConstraints repack_design_constraints; @@ -66,24 +69,26 @@ RepackDesignConstraints read_xml_repack_design_constraints(const char* design_co try { loc_data = pugiutil::load_xml(doc, design_constraint_fname); - pugi::xml_node xml_root = get_single_child(doc, "repack_design_constraints", loc_data); + pugi::xml_node xml_root = + get_single_child(doc, "repack_design_constraints", loc_data); - size_t num_design_constraints = std::distance(xml_root.children().begin(), xml_root.children().end()); + size_t num_design_constraints = + std::distance(xml_root.children().begin(), xml_root.children().end()); /* Reserve memory space for the region */ - repack_design_constraints.reserve_design_constraints(num_design_constraints); + repack_design_constraints.reserve_design_constraints( + num_design_constraints); for (pugi::xml_node xml_design_constraint : xml_root.children()) { /* Error out if the XML child has an invalid name! */ if (xml_design_constraint.name() != std::string("pin_constraint")) { bad_tag(xml_design_constraint, loc_data, xml_root, {"pin_constraint"}); } - read_xml_pin_constraint(xml_design_constraint, loc_data, repack_design_constraints); - } + read_xml_pin_constraint(xml_design_constraint, loc_data, + repack_design_constraints); + } } catch (pugiutil::XmlError& e) { - archfpga_throw(design_constraint_fname, e.line(), - "%s", e.what()); + archfpga_throw(design_constraint_fname, e.line(), "%s", e.what()); } - return repack_design_constraints; + return repack_design_constraints; } - diff --git a/libs/libpcf/src/io/read_xml_repack_design_constraints.h b/libs/libpcf/src/io/read_xml_repack_design_constraints.h index c2d3917b2..e7ac4bc2c 100644 --- a/libs/libpcf/src/io/read_xml_repack_design_constraints.h +++ b/libs/libpcf/src/io/read_xml_repack_design_constraints.h @@ -4,13 +4,14 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "pugixml_util.hpp" #include "pugixml.hpp" +#include "pugixml_util.hpp" #include "repack_design_constraints.h" /******************************************************************** * Function declaration *******************************************************************/ -RepackDesignConstraints read_xml_repack_design_constraints(const char* design_constraint_fname); +RepackDesignConstraints read_xml_repack_design_constraints( + const char* design_constraint_fname); #endif diff --git a/libs/libpcf/src/io/write_csv_io_pin_table.cpp b/libs/libpcf/src/io/write_csv_io_pin_table.cpp index e3edfdfe4..48b74d324 100644 --- a/libs/libpcf/src/io/write_csv_io_pin_table.cpp +++ b/libs/libpcf/src/io/write_csv_io_pin_table.cpp @@ -7,28 +7,26 @@ /* Headers from vtr util library */ #include "vtr_assert.h" -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from libopenfpga util library */ #include "openfpga_port_parser.h" /* Headers from arch openfpga library */ -#include "write_xml_utils.h" - #include "write_csv_io_pin_table.h" +#include "write_xml_utils.h" /* Begin namespace openfpga */ namespace openfpga { /******************************************************************** * Write I/O pin table to a csv file - * + * * Return 0 if successful * Return 1 if there are more serious errors * Return 2 if fail when creating files *******************************************************************/ -int write_csv_io_pin_table(const char* fname, - const IoPinTable& io_pin_table) { +int write_csv_io_pin_table(const char* fname, const IoPinTable& io_pin_table) { vtr::ScopedStartFinishTimer timer("Write I/O Pin Table"); /* Create a file handler */ @@ -37,10 +35,12 @@ int write_csv_io_pin_table(const char* fname, fp.open(std::string(fname), std::fstream::out | std::fstream::trunc); /* TODO: Move this to constants header file */ - std::array IO_DIRECTION_STRING = {"input", "output"}; + std::array IO_DIRECTION_STRING = { + "input", "output"}; /* Print head row */ - std::vector head_row_str({"orientation", "port_name", "mapped_pin", "direction"}); + std::vector head_row_str( + {"orientation", "port_name", "mapped_pin", "direction"}); for (size_t icol = 0; icol < head_row_str.size(); icol++) { fp << head_row_str[icol]; if (icol < head_row_str.size() - 1) { @@ -53,9 +53,12 @@ int write_csv_io_pin_table(const char* fname, for (const IoPinTableId& pin_id : io_pin_table.pins()) { std::vector data_row_str; data_row_str.push_back(SIDE_STRING[io_pin_table.pin_side(pin_id)]); - data_row_str.push_back(generate_xml_port_name(io_pin_table.internal_pin(pin_id))); - data_row_str.push_back(generate_xml_port_name(io_pin_table.external_pin(pin_id))); - data_row_str.push_back(IO_DIRECTION_STRING[io_pin_table.pin_direction(pin_id)]); + data_row_str.push_back( + generate_xml_port_name(io_pin_table.internal_pin(pin_id))); + data_row_str.push_back( + generate_xml_port_name(io_pin_table.external_pin(pin_id))); + data_row_str.push_back( + IO_DIRECTION_STRING[io_pin_table.pin_direction(pin_id)]); for (size_t icol = 0; icol < head_row_str.size(); icol++) { fp << data_row_str[icol]; if (icol < data_row_str.size() - 1) { diff --git a/libs/libpcf/src/io/write_csv_io_pin_table.h b/libs/libpcf/src/io/write_csv_io_pin_table.h index 0367326b2..91ad8034d 100644 --- a/libs/libpcf/src/io/write_csv_io_pin_table.h +++ b/libs/libpcf/src/io/write_csv_io_pin_table.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "io_pin_table.h" /******************************************************************** @@ -13,8 +14,7 @@ /* Begin namespace openfpga */ namespace openfpga { -int write_csv_io_pin_table(const char* fname, - const IoPinTable& io_pin_table); +int write_csv_io_pin_table(const char* fname, const IoPinTable& io_pin_table); } /* End namespace openfpga*/ diff --git a/libs/libpcf/src/io/write_xml_pin_constraints.cpp b/libs/libpcf/src/io/write_xml_pin_constraints.cpp index ef728be95..bd96f29e9 100644 --- a/libs/libpcf/src/io/write_xml_pin_constraints.cpp +++ b/libs/libpcf/src/io/write_xml_pin_constraints.cpp @@ -1,9 +1,10 @@ /******************************************************************** - * This file includes functions that outputs a pin constraint object to XML format + * This file includes functions that outputs a pin constraint object to XML + *format *******************************************************************/ /* Headers from system goes first */ -#include #include +#include /* Headers from vtr util library */ #include "vtr_assert.h" @@ -14,7 +15,7 @@ #include "openfpga_digest.h" /* Headers from arch openfpga library */ -#include "write_xml_utils.h" +#include "write_xml_utils.h" /* Headers from pin constraint library */ #include "write_xml_pin_constraints.h" @@ -23,13 +24,12 @@ * A writer to output a pin constraint to XML format * * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture + * Return 1 if there are more serious bugs in the architecture * Return 2 if fail when creating files *******************************************************************/ -static -int write_xml_pin_constraint(std::fstream& fp, - const PinConstraints& pin_constraints, - const PinConstraintId& pin_constraint) { +static int write_xml_pin_constraint(std::fstream& fp, + const PinConstraints& pin_constraints, + const PinConstraintId& pin_constraint) { /* Validate the file stream */ if (false == openfpga::valid_file_stream(fp)) { return 2; @@ -42,11 +42,16 @@ int write_xml_pin_constraint(std::fstream& fp, return 1; } - write_xml_attribute(fp, "pin", generate_xml_port_name(pin_constraints.pin(pin_constraint)).c_str()); + write_xml_attribute( + fp, "pin", + generate_xml_port_name(pin_constraints.pin(pin_constraint)).c_str()); write_xml_attribute(fp, "net", pin_constraints.net(pin_constraint).c_str()); - write_xml_attribute(fp, "default_value", pin_constraints.net_default_value_to_string(pin_constraint).c_str()); + write_xml_attribute( + fp, "default_value", + pin_constraints.net_default_value_to_string(pin_constraint).c_str()); - fp << "/>" << "\n"; + fp << "/>" + << "\n"; return 0; } @@ -55,12 +60,11 @@ int write_xml_pin_constraint(std::fstream& fp, * A writer to output a repack pin constraint object to XML format * * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture + * Return 1 if there are more serious bugs in the architecture * Return 2 if fail when creating files *******************************************************************/ int write_xml_pin_constraints(const char* fname, const PinConstraints& pin_constraints) { - vtr::ScopedStartFinishTimer timer("Write Pin Constraints"); /* Create a file handler */ @@ -70,15 +74,17 @@ int write_xml_pin_constraints(const char* fname, /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - + /* Write the root node */ - fp << "" << "\n"; + fp << "" + << "\n"; int err_code = 0; - /* Write region by region */ - for (const PinConstraintId& pin_constraint : pin_constraints.pin_constraints()) { - /* Write constraint by constraint */ + /* Write region by region */ + for (const PinConstraintId& pin_constraint : + pin_constraints.pin_constraints()) { + /* Write constraint by constraint */ err_code = write_xml_pin_constraint(fp, pin_constraints, pin_constraint); if (0 != err_code) { return err_code; @@ -86,7 +92,8 @@ int write_xml_pin_constraints(const char* fname, } /* Finish writing the root node */ - fp << "" << "\n"; + fp << "" + << "\n"; /* Close the file stream */ fp.close(); diff --git a/libs/libpcf/src/io/write_xml_pin_constraints.h b/libs/libpcf/src/io/write_xml_pin_constraints.h index c68b072b9..cd9d02e52 100644 --- a/libs/libpcf/src/io/write_xml_pin_constraints.h +++ b/libs/libpcf/src/io/write_xml_pin_constraints.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "pin_constraints.h" /******************************************************************** diff --git a/libs/libpcf/src/io/write_xml_repack_design_constraints.cpp b/libs/libpcf/src/io/write_xml_repack_design_constraints.cpp index ec8f662fb..307b05b24 100644 --- a/libs/libpcf/src/io/write_xml_repack_design_constraints.cpp +++ b/libs/libpcf/src/io/write_xml_repack_design_constraints.cpp @@ -1,9 +1,10 @@ /******************************************************************** - * This file includes functions that outputs a repack design constraint object to XML format + * This file includes functions that outputs a repack design constraint object + *to XML format *******************************************************************/ /* Headers from system goes first */ -#include #include +#include /* Headers from vtr util library */ #include "vtr_assert.h" @@ -14,7 +15,7 @@ #include "openfpga_digest.h" /* Headers from arch openfpga library */ -#include "write_xml_utils.h" +#include "write_xml_utils.h" /* Headers from fabrickey library */ #include "write_xml_repack_design_constraints.h" @@ -23,13 +24,12 @@ * A writer to output a pin constraint to XML format * * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture + * Return 1 if there are more serious bugs in the architecture * Return 2 if fail when creating files *******************************************************************/ -static -int write_xml_pin_constraint(std::fstream& fp, - const RepackDesignConstraints& repack_design_constraints, - const RepackDesignConstraintId& design_constraint) { +static int write_xml_pin_constraint( + std::fstream& fp, const RepackDesignConstraints& repack_design_constraints, + const RepackDesignConstraintId& design_constraint) { /* Validate the file stream */ if (false == openfpga::valid_file_stream(fp)) { return 2; @@ -38,15 +38,23 @@ int write_xml_pin_constraint(std::fstream& fp, openfpga::write_tab_to_file(fp, 1); fp << "" << "\n"; + fp << "/>" + << "\n"; return 0; } @@ -55,12 +63,11 @@ int write_xml_pin_constraint(std::fstream& fp, * A writer to output a repack design constraint object to XML format * * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture + * Return 1 if there are more serious bugs in the architecture * Return 2 if fail when creating files *******************************************************************/ -int write_xml_repack_design_constraints(const char* fname, - const RepackDesignConstraints& repack_design_constraints) { - +int write_xml_repack_design_constraints( + const char* fname, const RepackDesignConstraints& repack_design_constraints) { vtr::ScopedStartFinishTimer timer("Write Repack Design Constraints"); /* Create a file handler */ @@ -70,17 +77,21 @@ int write_xml_repack_design_constraints(const char* fname, /* Validate the file stream */ openfpga::check_file_stream(fname, fp); - + /* Write the root node */ - fp << "" << "\n"; + fp << "" + << "\n"; int err_code = 0; - /* Write region by region */ - for (const RepackDesignConstraintId& design_constraint : repack_design_constraints.design_constraints()) { - /* Write constraint by constraint */ - if (RepackDesignConstraints::PIN_ASSIGNMENT == repack_design_constraints.type(design_constraint)) { - err_code = write_xml_pin_constraint(fp, repack_design_constraints, design_constraint); + /* Write region by region */ + for (const RepackDesignConstraintId& design_constraint : + repack_design_constraints.design_constraints()) { + /* Write constraint by constraint */ + if (RepackDesignConstraints::PIN_ASSIGNMENT == + repack_design_constraints.type(design_constraint)) { + err_code = write_xml_pin_constraint(fp, repack_design_constraints, + design_constraint); if (0 != err_code) { return err_code; } @@ -88,7 +99,8 @@ int write_xml_repack_design_constraints(const char* fname, } /* Finish writing the root node */ - fp << "" << "\n"; + fp << "" + << "\n"; /* Close the file stream */ fp.close(); diff --git a/libs/libpcf/src/io/write_xml_repack_design_constraints.h b/libs/libpcf/src/io/write_xml_repack_design_constraints.h index 441799451..fd18604a9 100644 --- a/libs/libpcf/src/io/write_xml_repack_design_constraints.h +++ b/libs/libpcf/src/io/write_xml_repack_design_constraints.h @@ -5,12 +5,13 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "repack_design_constraints.h" /******************************************************************** * Function declaration *******************************************************************/ -int write_xml_repack_design_constraints(const char* fname, - const RepackDesignConstraints& repack_design_constraints); +int write_xml_repack_design_constraints( + const char* fname, const RepackDesignConstraints& repack_design_constraints); #endif diff --git a/libs/libpcf/test/test_blif_head_reader.cpp b/libs/libpcf/test/test_blif_head_reader.cpp index 4a08f5c2c..d3e4cd0c9 100644 --- a/libs/libpcf/test/test_blif_head_reader.cpp +++ b/libs/libpcf/test/test_blif_head_reader.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * Unit test functions to validate the correctness of + * Unit test functions to validate the correctness of * 1. parser of data structures * 2. writer of data structures *******************************************************************/ @@ -17,12 +17,10 @@ int main(int argc, const char** argv) { /* Parse the blif */ blifparse::BlifHeadReader callback; blifparse::blif_parse_filename(argv[1], callback); - VTR_LOG("Read the blif from a file: %s.\n", - argv[1]); + VTR_LOG("Read the blif from a file: %s.\n", argv[1]); if (callback.had_error()) { - VTR_LOG("Read the blif ends with errors\n", - argv[1]); + VTR_LOG("Read the blif ends with errors\n", argv[1]); return 1; } @@ -38,5 +36,3 @@ int main(int argc, const char** argv) { return 0; } - - diff --git a/libs/libpcf/test/test_csv_io_pin_table.cpp b/libs/libpcf/test/test_csv_io_pin_table.cpp index ce6c31f67..22084d6b9 100644 --- a/libs/libpcf/test/test_csv_io_pin_table.cpp +++ b/libs/libpcf/test/test_csv_io_pin_table.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * Unit test functions to validate the correctness of + * Unit test functions to validate the correctness of * 1. parser of data structures * 2. writer of data structures *******************************************************************/ @@ -17,17 +17,13 @@ int main(int argc, const char** argv) { /* Parse the fabric key from an XML file */ openfpga::IoPinTable io_pin_table = openfpga::read_csv_io_pin_table(argv[1]); - VTR_LOG("Read the I/O pin table from a csv file: %s.\n", - argv[1]); + VTR_LOG("Read the I/O pin table from a csv file: %s.\n", argv[1]); /* Output to an XML file * This is optional only used when there is a second argument */ - if (3 <= argc) { + if (3 <= argc) { write_csv_io_pin_table(argv[2], io_pin_table); - VTR_LOG("Echo the I/O pin table to a csv file: %s.\n", - argv[2]); + VTR_LOG("Echo the I/O pin table to a csv file: %s.\n", argv[2]); } } - - diff --git a/libs/libpcf/test/test_pcf.cpp b/libs/libpcf/test/test_pcf.cpp index fa71799ac..e5ae544c2 100644 --- a/libs/libpcf/test/test_pcf.cpp +++ b/libs/libpcf/test/test_pcf.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * Unit test functions to validate the correctness of + * Unit test functions to validate the correctness of * 1. parser of data structures * 2. writer of data structures *******************************************************************/ @@ -18,17 +18,13 @@ int main(int argc, const char** argv) { /* Parse the fabric key from an XML file */ openfpga::PcfData pcf_data; openfpga::read_pcf(argv[1], pcf_data); - VTR_LOG("Read the design constraints from a pcf file: %s.\n", - argv[1]); + VTR_LOG("Read the design constraints from a pcf file: %s.\n", argv[1]); /* Output to an XML file * This is optional only used when there is a second argument */ - if (3 <= argc) { + if (3 <= argc) { write_pcf(argv[2], pcf_data); - VTR_LOG("Echo the design constraints to a pcf file: %s.\n", - argv[2]); + VTR_LOG("Echo the design constraints to a pcf file: %s.\n", argv[2]); } } - - diff --git a/libs/libpcf/test/test_pcf2place.cpp b/libs/libpcf/test/test_pcf2place.cpp index 35a3b528f..05b9614d2 100644 --- a/libs/libpcf/test/test_pcf2place.cpp +++ b/libs/libpcf/test/test_pcf2place.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * Unit test functions to validate the correctness of + * Unit test functions to validate the correctness of * 1. parser of data structures * 2. writer of data structures *******************************************************************/ @@ -8,12 +8,12 @@ #include "vtr_log.h" /* Headers from fabric key */ -#include "pcf_reader.h" #include "blif_head_reader.h" -#include "read_csv_io_pin_table.h" -#include "read_xml_io_location_map.h" #include "io_net_place.h" #include "pcf2place.h" +#include "pcf_reader.h" +#include "read_csv_io_pin_table.h" +#include "read_xml_io_location_map.h" int main(int argc, const char** argv) { /* Ensure we have the following arguments: @@ -28,30 +28,28 @@ int main(int argc, const char** argv) { /* Parse the input files */ openfpga::PcfData pcf_data; openfpga::read_pcf(argv[1], pcf_data); - VTR_LOG("Read the design constraints from a pcf file: %s.\n", - argv[1]); + VTR_LOG("Read the design constraints from a pcf file: %s.\n", argv[1]); blifparse::BlifHeadReader callback; blifparse::blif_parse_filename(argv[2], callback); - VTR_LOG("Read the blif from a file: %s.\n", - argv[2]); + VTR_LOG("Read the blif from a file: %s.\n", argv[2]); if (callback.had_error()) { - VTR_LOG("Read the blif ends with errors\n", - argv[2]); + VTR_LOG("Read the blif ends with errors\n", argv[2]); return 1; } - openfpga::IoLocationMap io_location_map = openfpga::read_xml_io_location_map(argv[3]); - VTR_LOG("Read the I/O location map from an XML file: %s.\n", - argv[3]); + openfpga::IoLocationMap io_location_map = + openfpga::read_xml_io_location_map(argv[3]); + VTR_LOG("Read the I/O location map from an XML file: %s.\n", argv[3]); openfpga::IoPinTable io_pin_table = openfpga::read_csv_io_pin_table(argv[4]); - VTR_LOG("Read the I/O pin table from a csv file: %s.\n", - argv[4]); + VTR_LOG("Read the I/O pin table from a csv file: %s.\n", argv[4]); /* Convert */ openfpga::IoNetPlace io_net_place; - int status = pcf2place(pcf_data, callback.input_pins(), callback.output_pins(), io_pin_table, io_location_map, io_net_place); + int status = + pcf2place(pcf_data, callback.input_pins(), callback.output_pins(), + io_pin_table, io_location_map, io_net_place); if (status) { return status; } @@ -61,5 +59,3 @@ int main(int argc, const char** argv) { return status; } - - diff --git a/libs/libpcf/test/test_repack_design_constraints.cpp b/libs/libpcf/test/test_repack_design_constraints.cpp index 78a1314ef..a080d7c35 100644 --- a/libs/libpcf/test/test_repack_design_constraints.cpp +++ b/libs/libpcf/test/test_repack_design_constraints.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * Unit test functions to validate the correctness of + * Unit test functions to validate the correctness of * 1. parser of data structures * 2. writer of data structures *******************************************************************/ @@ -15,20 +15,18 @@ int main(int argc, const char** argv) { /* Ensure we have only one or two argument */ VTR_ASSERT((2 == argc) || (3 == argc)); - /* Parse the fabric key from an XML file */ - RepackDesignConstraints design_constraints = read_xml_repack_design_constraints(argv[1]); + RepackDesignConstraints design_constraints = + read_xml_repack_design_constraints(argv[1]); VTR_LOG("Read the repack design constraints from an XML file: %s.\n", argv[1]); /* Output the circuit library to an XML file * This is optional only used when there is a second argument */ - if (3 <= argc) { + if (3 <= argc) { write_xml_repack_design_constraints(argv[2], design_constraints); VTR_LOG("Echo the repack design constraints to an XML file: %s.\n", argv[2]); } } - - diff --git a/libs/libpcf/test/test_xml_io_location_map.cpp b/libs/libpcf/test/test_xml_io_location_map.cpp index f77964ab1..83ef9c35c 100644 --- a/libs/libpcf/test/test_xml_io_location_map.cpp +++ b/libs/libpcf/test/test_xml_io_location_map.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * Unit test functions to validate the correctness of + * Unit test functions to validate the correctness of * 1. parser of data structures * 2. writer of data structures *******************************************************************/ @@ -16,18 +16,15 @@ int main(int argc, const char** argv) { VTR_ASSERT((2 == argc) || (3 == argc)); /* Parse the fabric key from an XML file */ - openfpga::IoLocationMap io_location_map = openfpga::read_xml_io_location_map(argv[1]); - VTR_LOG("Read the I/O location map from an XML file: %s.\n", - argv[1]); + openfpga::IoLocationMap io_location_map = + openfpga::read_xml_io_location_map(argv[1]); + VTR_LOG("Read the I/O location map from an XML file: %s.\n", argv[1]); /* Output to an XML file * This is optional only used when there is a second argument */ - if (3 <= argc) { + if (3 <= argc) { io_location_map.write_to_xml_file(std::string(argv[2]), true, true); - VTR_LOG("Echo the I/O location map to an XML file: %s.\n", - argv[2]); + VTR_LOG("Echo the I/O location map to an XML file: %s.\n", argv[2]); } } - - diff --git a/libs/libpcf/test/test_xml_pcf.cpp b/libs/libpcf/test/test_xml_pcf.cpp index da91ddbcc..a992883e3 100644 --- a/libs/libpcf/test/test_xml_pcf.cpp +++ b/libs/libpcf/test/test_xml_pcf.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * Unit test functions to validate the correctness of + * Unit test functions to validate the correctness of * 1. parser of data structures * 2. writer of data structures *******************************************************************/ @@ -17,17 +17,13 @@ int main(int argc, const char** argv) { /* Parse the fabric key from an XML file */ PinConstraints pin_constraints = read_xml_pin_constraints(argv[1]); - VTR_LOG("Read the pin constraints from an XML file: %s.\n", - argv[1]); + VTR_LOG("Read the pin constraints from an XML file: %s.\n", argv[1]); /* Output pin constraints to an XML file * This is optional only used when there is a second argument */ - if (3 <= argc) { + if (3 <= argc) { write_xml_pin_constraints(argv[2], pin_constraints); - VTR_LOG("Echo the pin constraints to an XML file: %s.\n", - argv[2]); + VTR_LOG("Echo the pin constraints to an XML file: %s.\n", argv[2]); } } - - diff --git a/openfpga/src/annotation/annotate_bitstream_setting.cpp b/openfpga/src/annotation/annotate_bitstream_setting.cpp index a51e73fde..266202505 100644 --- a/openfpga/src/annotation/annotate_bitstream_setting.cpp +++ b/openfpga/src/annotation/annotate_bitstream_setting.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * This file includes functions that are used to annotate pb_type + * This file includes functions that are used to annotate pb_type * from VPR to OpenFPGA *******************************************************************/ #include @@ -13,10 +13,9 @@ #include "vtr_log.h" /* Headers from openfpgautil library */ -#include "openfpga_tokenizer.h" - -#include "pb_type_utils.h" #include "annotate_bitstream_setting.h" +#include "openfpga_tokenizer.h" +#include "pb_type_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -26,72 +25,102 @@ namespace openfpga { * - Find the pb_type and link to the bitstream source * - Find the pb_type and link to the bitstream content *******************************************************************/ -static -int annotate_bitstream_pb_type_setting(const BitstreamSetting& bitstream_setting, - const DeviceContext& vpr_device_ctx, - VprBitstreamAnnotation& vpr_bitstream_annotation) { - - for (const auto& bitstream_pb_type_setting_id : bitstream_setting.pb_type_settings()) { +static int annotate_bitstream_pb_type_setting( + const BitstreamSetting& bitstream_setting, + const DeviceContext& vpr_device_ctx, + VprBitstreamAnnotation& vpr_bitstream_annotation) { + for (const auto& bitstream_pb_type_setting_id : + bitstream_setting.pb_type_settings()) { /* Get the full name of pb_type */ std::vector target_pb_type_names; std::vector target_pb_mode_names; - target_pb_type_names = bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id); - target_pb_type_names.push_back(bitstream_setting.pb_type_name(bitstream_pb_type_setting_id)); - target_pb_mode_names = bitstream_setting.parent_mode_names(bitstream_pb_type_setting_id); + target_pb_type_names = + bitstream_setting.parent_pb_type_names(bitstream_pb_type_setting_id); + target_pb_type_names.push_back( + bitstream_setting.pb_type_name(bitstream_pb_type_setting_id)); + target_pb_mode_names = + bitstream_setting.parent_mode_names(bitstream_pb_type_setting_id); - /* Pb type information are located at the logic_block_types in the device context of VPR - * We iterate over the vectors and find the pb_type matches the parent_pb_type_name + /* Pb type information are located at the logic_block_types in the device + * context of VPR We iterate over the vectors and find the pb_type matches + * the parent_pb_type_name */ bool link_success = false; - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } - /* Check the name of the top-level pb_type, if it does not match, we can bypass */ + /* Check the name of the top-level pb_type, if it does not match, we can + * bypass */ if (target_pb_type_names[0] != std::string(lb_type.pb_type->name)) { continue; } - /* Match the name in the top-level, we go further to search the pb_type in the graph */ - t_pb_type* target_pb_type = try_find_pb_type_with_given_path(lb_type.pb_type, target_pb_type_names, - target_pb_mode_names); + /* Match the name in the top-level, we go further to search the pb_type in + * the graph */ + t_pb_type* target_pb_type = try_find_pb_type_with_given_path( + lb_type.pb_type, target_pb_type_names, target_pb_mode_names); if (nullptr == target_pb_type) { continue; } /* Found one, build annotation */ - if (std::string("eblif") != bitstream_setting.pb_type_bitstream_source(bitstream_pb_type_setting_id)) { + if (std::string("eblif") != bitstream_setting.pb_type_bitstream_source( + bitstream_pb_type_setting_id)) { /* Invalid source, error out! */ - VTR_LOG_ERROR("Invalid bitstream source '%s' for pb_type '%s' which is defined in bitstream setting\n", - bitstream_setting.pb_type_bitstream_source(bitstream_pb_type_setting_id).c_str(), - target_pb_type_names[0].c_str()); + VTR_LOG_ERROR( + "Invalid bitstream source '%s' for pb_type '%s' which is defined in " + "bitstream setting\n", + bitstream_setting + .pb_type_bitstream_source(bitstream_pb_type_setting_id) + .c_str(), + target_pb_type_names[0].c_str()); return CMD_EXEC_FATAL_ERROR; } /* Depending on the bitstream type, annotate through different entrances - * - For regular bitstream, set bitstream content, flags etc. - * - For mode-select bitstream, set mode-select bitstream content, flags etc. + * - For regular bitstream, set bitstream content, flags etc. + * - For mode-select bitstream, set mode-select bitstream content, flags + * etc. */ - if (false == bitstream_setting.is_mode_select_bitstream(bitstream_pb_type_setting_id)) { - vpr_bitstream_annotation.set_pb_type_bitstream_source(target_pb_type, VprBitstreamAnnotation::e_bitstream_source_type::BITSTREAM_SOURCE_EBLIF); - vpr_bitstream_annotation.set_pb_type_bitstream_content(target_pb_type, bitstream_setting.pb_type_bitstream_content(bitstream_pb_type_setting_id)); - vpr_bitstream_annotation.set_pb_type_bitstream_offset(target_pb_type, bitstream_setting.bitstream_offset(bitstream_pb_type_setting_id)); + if (false == bitstream_setting.is_mode_select_bitstream( + bitstream_pb_type_setting_id)) { + vpr_bitstream_annotation.set_pb_type_bitstream_source( + target_pb_type, VprBitstreamAnnotation::e_bitstream_source_type:: + BITSTREAM_SOURCE_EBLIF); + vpr_bitstream_annotation.set_pb_type_bitstream_content( + target_pb_type, bitstream_setting.pb_type_bitstream_content( + bitstream_pb_type_setting_id)); + vpr_bitstream_annotation.set_pb_type_bitstream_offset( + target_pb_type, + bitstream_setting.bitstream_offset(bitstream_pb_type_setting_id)); } else { - VTR_ASSERT_SAFE(false == bitstream_setting.is_mode_select_bitstream(bitstream_pb_type_setting_id)); - vpr_bitstream_annotation.set_pb_type_mode_select_bitstream_source(target_pb_type, VprBitstreamAnnotation::e_bitstream_source_type::BITSTREAM_SOURCE_EBLIF); - vpr_bitstream_annotation.set_pb_type_mode_select_bitstream_content(target_pb_type, bitstream_setting.pb_type_bitstream_content(bitstream_pb_type_setting_id)); - vpr_bitstream_annotation.set_pb_type_mode_select_bitstream_offset(target_pb_type, bitstream_setting.bitstream_offset(bitstream_pb_type_setting_id)); + VTR_ASSERT_SAFE(false == bitstream_setting.is_mode_select_bitstream( + bitstream_pb_type_setting_id)); + vpr_bitstream_annotation.set_pb_type_mode_select_bitstream_source( + target_pb_type, VprBitstreamAnnotation::e_bitstream_source_type:: + BITSTREAM_SOURCE_EBLIF); + vpr_bitstream_annotation.set_pb_type_mode_select_bitstream_content( + target_pb_type, bitstream_setting.pb_type_bitstream_content( + bitstream_pb_type_setting_id)); + vpr_bitstream_annotation.set_pb_type_mode_select_bitstream_offset( + target_pb_type, + bitstream_setting.bitstream_offset(bitstream_pb_type_setting_id)); } link_success = true; } - /* If fail to link bitstream setting to architecture, error out immediately */ + /* If fail to link bitstream setting to architecture, error out immediately + */ if (false == link_success) { - VTR_LOG_ERROR("Fail to find a pb_type '%s' which is defined in bitstream setting from VPR architecture description\n", - target_pb_type_names[0].c_str()); + VTR_LOG_ERROR( + "Fail to find a pb_type '%s' which is defined in bitstream setting " + "from VPR architecture description\n", + target_pb_type_names[0].c_str()); return CMD_EXEC_FATAL_ERROR; } } @@ -103,73 +132,87 @@ int annotate_bitstream_pb_type_setting(const BitstreamSetting& bitstream_setting * Annotate bitstream setting based on VPR device information * - Find the interconnect and link to the default path id *******************************************************************/ -static -int annotate_bitstream_interconnect_setting(const BitstreamSetting& bitstream_setting, - const DeviceContext& vpr_device_ctx, - const VprDeviceAnnotation& vpr_device_annotation, - VprBitstreamAnnotation& vpr_bitstream_annotation) { - - for (const auto& bitstream_interc_setting_id : bitstream_setting.interconnect_settings()) { +static int annotate_bitstream_interconnect_setting( + const BitstreamSetting& bitstream_setting, + const DeviceContext& vpr_device_ctx, + const VprDeviceAnnotation& vpr_device_annotation, + VprBitstreamAnnotation& vpr_bitstream_annotation) { + for (const auto& bitstream_interc_setting_id : + bitstream_setting.interconnect_settings()) { /* Get the full name of pb_type */ std::vector target_pb_type_names; std::vector target_pb_mode_names; - target_pb_type_names = bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id); - target_pb_mode_names = bitstream_setting.parent_mode_names(bitstream_interc_setting_id); - /* Kick out the last mode so that we can use an existing function search the pb_type in graph */ + target_pb_type_names = + bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id); + target_pb_mode_names = + bitstream_setting.parent_mode_names(bitstream_interc_setting_id); + /* Kick out the last mode so that we can use an existing function search the + * pb_type in graph */ std::string expected_physical_mode_name = target_pb_mode_names.back(); target_pb_mode_names.pop_back(); - std::string interconnect_name = bitstream_setting.interconnect_name(bitstream_interc_setting_id); - std::string expected_input_path = bitstream_setting.default_path(bitstream_interc_setting_id); + std::string interconnect_name = + bitstream_setting.interconnect_name(bitstream_interc_setting_id); + std::string expected_input_path = + bitstream_setting.default_path(bitstream_interc_setting_id); - /* Pb type information are located at the logic_block_types in the device context of VPR - * We iterate over the vectors and find the pb_type matches the parent_pb_type_name + /* Pb type information are located at the logic_block_types in the device + * context of VPR We iterate over the vectors and find the pb_type matches + * the parent_pb_type_name */ bool link_success = false; - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } - /* Check the name of the top-level pb_type, if it does not match, we can bypass */ + /* Check the name of the top-level pb_type, if it does not match, we can + * bypass */ if (target_pb_type_names[0] != std::string(lb_type.pb_type->name)) { continue; } - /* Match the name in the top-level, we go further to search the pb_type in the graph */ - t_pb_type* target_pb_type = try_find_pb_type_with_given_path(lb_type.pb_type, target_pb_type_names, - target_pb_mode_names); + /* Match the name in the top-level, we go further to search the pb_type in + * the graph */ + t_pb_type* target_pb_type = try_find_pb_type_with_given_path( + lb_type.pb_type, target_pb_type_names, target_pb_mode_names); if (nullptr == target_pb_type) { continue; } /* Found one, build annotation */ - t_mode* physical_mode = vpr_device_annotation.physical_mode(target_pb_type); - + t_mode* physical_mode = + vpr_device_annotation.physical_mode(target_pb_type); + VTR_ASSERT(nullptr != physical_mode); - /* Ensure that the annotation is only applicable to physical mode */ + /* Ensure that the annotation is only applicable to physical mode */ if (std::string(physical_mode->name) != expected_physical_mode_name) { - VTR_LOG_ERROR("The physical mode '%s' under pb_type '%s' does not match in the bitstream setting '%s'!\n", - physical_mode->name, - target_pb_type->name, - expected_physical_mode_name.c_str()); - return CMD_EXEC_FATAL_ERROR; - } - - /* Find the interconnect name under the physical mode of a physical pb_type */ - t_interconnect* pb_interc = find_pb_mode_interconnect(physical_mode, interconnect_name.c_str()); - - if (nullptr == pb_interc) { - VTR_LOG_ERROR("Unable to find interconnect '%s' under physical mode '%s' of pb_type '%s'!\n", - interconnect_name.c_str(), - physical_mode->name, - target_pb_type->name); + VTR_LOG_ERROR( + "The physical mode '%s' under pb_type '%s' does not match in the " + "bitstream setting '%s'!\n", + physical_mode->name, target_pb_type->name, + expected_physical_mode_name.c_str()); return CMD_EXEC_FATAL_ERROR; } - /* Find the default path and spot the path id from the input string recorded */ - StringToken input_string_tokenizer(std::string(pb_interc->input_string)); + /* Find the interconnect name under the physical mode of a physical + * pb_type */ + t_interconnect* pb_interc = + find_pb_mode_interconnect(physical_mode, interconnect_name.c_str()); + + if (nullptr == pb_interc) { + VTR_LOG_ERROR( + "Unable to find interconnect '%s' under physical mode '%s' of " + "pb_type '%s'!\n", + interconnect_name.c_str(), physical_mode->name, target_pb_type->name); + return CMD_EXEC_FATAL_ERROR; + } + + /* Find the default path and spot the path id from the input string + * recorded */ + StringToken input_string_tokenizer(std::string(pb_interc->input_string)); std::vector input_paths = input_string_tokenizer.split(' '); size_t input_path_id = input_paths.size(); for (size_t ipath = 0; ipath < input_paths.size(); ++ipath) { @@ -180,23 +223,27 @@ int annotate_bitstream_interconnect_setting(const BitstreamSetting& bitstream_se } /* If the input_path id is invalid, error out! */ if (input_path_id == input_paths.size()) { - VTR_LOG_ERROR("Invalid default path '%s' for interconnect '%s' which inputs are '%s'\n", - expected_input_path.c_str(), - interconnect_name.c_str(), - pb_interc->input_string); + VTR_LOG_ERROR( + "Invalid default path '%s' for interconnect '%s' which inputs are " + "'%s'\n", + expected_input_path.c_str(), interconnect_name.c_str(), + pb_interc->input_string); return CMD_EXEC_FATAL_ERROR; } - vpr_bitstream_annotation.set_interconnect_default_path_id(pb_interc, input_path_id); + vpr_bitstream_annotation.set_interconnect_default_path_id(pb_interc, + input_path_id); link_success = true; } - /* If fail to link bitstream setting to architecture, error out immediately */ + /* If fail to link bitstream setting to architecture, error out immediately + */ if (false == link_success) { - VTR_LOG_ERROR("Fail to find an interconnect '%s' with default path '%s', which is defined in bitstream setting from VPR architecture description\n", - interconnect_name.c_str(), - expected_input_path.c_str()); + VTR_LOG_ERROR( + "Fail to find an interconnect '%s' with default path '%s', which is " + "defined in bitstream setting from VPR architecture description\n", + interconnect_name.c_str(), expected_input_path.c_str()); return CMD_EXEC_FATAL_ERROR; } } @@ -209,23 +256,22 @@ int annotate_bitstream_interconnect_setting(const BitstreamSetting& bitstream_se * - Fill pb_type -related mapping * - Fill interconnect -related mapping *******************************************************************/ -int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting, - const DeviceContext& vpr_device_ctx, - const VprDeviceAnnotation& vpr_device_annotation, - VprBitstreamAnnotation& vpr_bitstream_annotation) { - +int annotate_bitstream_setting( + const BitstreamSetting& bitstream_setting, + const DeviceContext& vpr_device_ctx, + const VprDeviceAnnotation& vpr_device_annotation, + VprBitstreamAnnotation& vpr_bitstream_annotation) { int status = CMD_EXEC_SUCCESS; - - status = annotate_bitstream_pb_type_setting(bitstream_setting, - vpr_device_ctx, + + status = annotate_bitstream_pb_type_setting(bitstream_setting, vpr_device_ctx, vpr_bitstream_annotation); if (status == CMD_EXEC_FATAL_ERROR) { return status; } - status = annotate_bitstream_interconnect_setting(bitstream_setting, - vpr_device_ctx, vpr_device_annotation, - vpr_bitstream_annotation); + status = annotate_bitstream_interconnect_setting( + bitstream_setting, vpr_device_ctx, vpr_device_annotation, + vpr_bitstream_annotation); return status; } diff --git a/openfpga/src/annotation/annotate_bitstream_setting.h b/openfpga/src/annotation/annotate_bitstream_setting.h index 45d6316dd..3adc17639 100644 --- a/openfpga/src/annotation/annotate_bitstream_setting.h +++ b/openfpga/src/annotation/annotate_bitstream_setting.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" #include "openfpga_context.h" +#include "vpr_context.h" /******************************************************************** * Function declaration @@ -14,10 +14,11 @@ /* begin namespace openfpga */ namespace openfpga { -int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting, - const DeviceContext& vpr_device_ctx, - const VprDeviceAnnotation& vpr_device_annotation, - VprBitstreamAnnotation& vpr_bitstream_annotation); +int annotate_bitstream_setting( + const BitstreamSetting& bitstream_setting, + const DeviceContext& vpr_device_ctx, + const VprDeviceAnnotation& vpr_device_annotation, + VprBitstreamAnnotation& vpr_bitstream_annotation); } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/annotate_clustering.cpp b/openfpga/src/annotation/annotate_clustering.cpp index 4d345e061..dbd0e120f 100644 --- a/openfpga/src/annotation/annotate_clustering.cpp +++ b/openfpga/src/annotation/annotate_clustering.cpp @@ -3,26 +3,29 @@ * from VPR to OpenFPGA *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_assert.h" -#include "vtr_log.h" -#include "vtr_geometry.h" +#include "annotate_clustering.h" #include "command_exit_codes.h" - -#include "annotate_clustering.h" +#include "vtr_assert.h" +#include "vtr_geometry.h" +#include "vtr_log.h" /* begin namespace openfpga */ namespace openfpga { -/* @brief Record the net remapping and local routing trace changes in annotation - * This is to ensure that the clustering annotation data structure is always up-to-date +/* @brief Record the net remapping and local routing trace changes in annotation + * This is to ensure that the clustering annotation data structure is always + * up-to-date */ -bool annotate_post_routing_cluster_sync_results(const DeviceContext& device_ctx, - const ClusteringContext& clustering_ctx, - VprClusteringAnnotation& clustering_annotation) { - VTR_LOG("Building annotation for post-routing and clustering synchornization results..."); +bool annotate_post_routing_cluster_sync_results( + const DeviceContext& device_ctx, const ClusteringContext& clustering_ctx, + VprClusteringAnnotation& clustering_annotation) { + VTR_LOG( + "Building annotation for post-routing and clustering synchornization " + "results..."); - for (const ClusterBlockId& cluster_blk_id : clustering_ctx.clb_nlist.blocks()) { + for (const ClusterBlockId& cluster_blk_id : + clustering_ctx.clb_nlist.blocks()) { /* Skip invalid ids */ if (!cluster_blk_id) { continue; @@ -30,15 +33,17 @@ bool annotate_post_routing_cluster_sync_results(const DeviceContext& device_ctx, auto logical_block = clustering_ctx.clb_nlist.block_type(cluster_blk_id); for (int ipin = 0; ipin < logical_block->pb_type->num_pins; ++ipin) { /* Update pin remapping from vtr data storage */ - auto blk_search_result = clustering_ctx.post_routing_clb_pin_nets.find(cluster_blk_id); + auto blk_search_result = + clustering_ctx.post_routing_clb_pin_nets.find(cluster_blk_id); if (blk_search_result != clustering_ctx.post_routing_clb_pin_nets.end()) { auto pin_search_result = blk_search_result->second.find(ipin); if (pin_search_result != blk_search_result->second.end()) { - clustering_annotation.rename_net(cluster_blk_id, ipin, pin_search_result->second); + clustering_annotation.rename_net(cluster_blk_id, ipin, + pin_search_result->second); } } } - } + } VTR_LOG("Done\n"); return CMD_EXEC_SUCCESS; diff --git a/openfpga/src/annotation/annotate_clustering.h b/openfpga/src/annotation/annotate_clustering.h index 3deb3ba91..2fb832f4b 100644 --- a/openfpga/src/annotation/annotate_clustering.h +++ b/openfpga/src/annotation/annotate_clustering.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" #include "vpr_clustering_annotation.h" +#include "vpr_context.h" /******************************************************************** * Function declaration @@ -14,9 +14,9 @@ /* begin namespace openfpga */ namespace openfpga { -bool annotate_post_routing_cluster_sync_results(const DeviceContext& device_ctx, - const ClusteringContext& clustering_ctx, - VprClusteringAnnotation& clustering_annotation); +bool annotate_post_routing_cluster_sync_results( + const DeviceContext& device_ctx, const ClusteringContext& clustering_ctx, + VprClusteringAnnotation& clustering_annotation); } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/annotate_pb_graph.cpp b/openfpga/src/annotation/annotate_pb_graph.cpp index bed7997cc..66028c633 100644 --- a/openfpga/src/annotation/annotate_pb_graph.cpp +++ b/openfpga/src/annotation/annotate_pb_graph.cpp @@ -3,15 +3,14 @@ * and pb_graph_pins from VPR to OpenFPGA *******************************************************************/ /* Headers from vtrutil library */ +#include "annotate_pb_graph.h" + +#include "check_pb_graph_annotation.h" +#include "pb_graph_utils.h" +#include "pb_type_utils.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "pb_type_utils.h" -#include "pb_graph_utils.h" - -#include "annotate_pb_graph.h" -#include "check_pb_graph_annotation.h" - /* begin namespace openfpga */ namespace openfpga { @@ -20,18 +19,17 @@ namespace openfpga { * starting from a top node. * It aims to annotate the physical type of each interconnect. * This is due to that the type of interconnect 'complete' may diverge - * in physical implmentation. - * - When there is only one input driving a 'complete' interconnection, + * in physical implmentation. + * - When there is only one input driving a 'complete' interconnection, * it will be implemented with wires - * - When there are multiple inputs driving a 'complete' interconnection, + * - When there are multiple inputs driving a 'complete' interconnection, * it will be implemented with routing multiplexers *******************************************************************/ -static -void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_node* pb_graph_node, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { - /* Skip the root node because we start from the inputs of child pb_graph node - * +static void rec_build_vpr_pb_graph_interconnect_physical_type_annotation( + t_pb_graph_node* pb_graph_node, VprDeviceAnnotation& vpr_device_annotation, + const bool& verbose_output) { + /* Skip the root node because we start from the inputs of child pb_graph node + * * pb_graph_node * +---------------------------------- * | child_pb_graph_node @@ -44,8 +42,10 @@ void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_nod * */ if (false == pb_graph_node->is_root()) { - /* We only care the physical modes! But we have to find it through the parent node */ - t_mode* child_physical_mode = vpr_device_annotation.physical_mode(pb_graph_node->parent_pb_graph_node->pb_type); + /* We only care the physical modes! But we have to find it through the + * parent node */ + t_mode* child_physical_mode = vpr_device_annotation.physical_mode( + pb_graph_node->parent_pb_graph_node->pb_type); VTR_ASSERT(nullptr != child_physical_mode); std::map interc_num_inputs; @@ -53,13 +53,17 @@ void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_nod /* Find all the interconnects sourced from the input and clock pins */ for (int iport = 0; iport < pb_graph_node->num_input_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) { - for (int iedge = 0; iedge < pb_graph_node->input_pins[iport][ipin].num_input_edges; ++iedge) { - t_interconnect* interc = pb_graph_node->input_pins[iport][ipin].input_edges[iedge]->interconnect; + for (int iedge = 0; + iedge < pb_graph_node->input_pins[iport][ipin].num_input_edges; + ++iedge) { + t_interconnect* interc = pb_graph_node->input_pins[iport][ipin] + .input_edges[iedge] + ->interconnect; /* Ensure that the interconnect is unique in the list */ if (0 < interc_num_inputs.count(interc)) { continue; } - /* Unique interconnect, initialize the counter to be zero */ + /* Unique interconnect, initialize the counter to be zero */ interc_num_inputs[interc] = 0; } } @@ -67,13 +71,17 @@ void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_nod for (int iport = 0; iport < pb_graph_node->num_clock_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_clock_pins[iport]; ++ipin) { - for (int iedge = 0; iedge < pb_graph_node->clock_pins[iport][ipin].num_input_edges; ++iedge) { - t_interconnect* interc = pb_graph_node->clock_pins[iport][ipin].input_edges[iedge]->interconnect; + for (int iedge = 0; + iedge < pb_graph_node->clock_pins[iport][ipin].num_input_edges; + ++iedge) { + t_interconnect* interc = pb_graph_node->clock_pins[iport][ipin] + .input_edges[iedge] + ->interconnect; /* Ensure that the interconnect is unique in the list */ if (0 < interc_num_inputs.count(interc)) { continue; } - /* Unique interconnect, initialize the counter to be zero */ + /* Unique interconnect, initialize the counter to be zero */ interc_num_inputs[interc] = 0; } } @@ -90,7 +98,10 @@ void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_nod for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) { /* For each interconnect, we count the total number of inputs */ for (const auto& pair : interc_num_inputs) { - interc_num_inputs[pair.first] += pb_graph_pin_inputs(&(pb_graph_node->input_pins[iport][ipin]), pair.first).size(); + interc_num_inputs[pair.first] += + pb_graph_pin_inputs(&(pb_graph_node->input_pins[iport][ipin]), + pair.first) + .size(); } } } @@ -99,33 +110,39 @@ void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_nod for (int ipin = 0; ipin < pb_graph_node->num_clock_pins[iport]; ++ipin) { /* For each interconnect, we count the total number of inputs */ for (const auto& pair : interc_num_inputs) { - interc_num_inputs[pair.first] += pb_graph_pin_inputs(&(pb_graph_node->clock_pins[iport][ipin]), pair.first).size(); + interc_num_inputs[pair.first] += + pb_graph_pin_inputs(&(pb_graph_node->clock_pins[iport][ipin]), + pair.first) + .size(); } } } - /* For each interconnect that has more than 1 input, we can infer the physical type */ + /* For each interconnect that has more than 1 input, we can infer the + * physical type */ for (const auto& pair : interc_num_inputs) { t_interconnect* interc = pair.first; size_t actual_interc_num_inputs = pair.second; - /* If the number inputs for an interconnect is zero, this is a 0-driver pin - * we just set 1 to use direct wires + /* If the number inputs for an interconnect is zero, this is a 0-driver + * pin we just set 1 to use direct wires */ if (0 == actual_interc_num_inputs) { actual_interc_num_inputs = 1; } - - e_interconnect interc_physical_type = pb_interconnect_physical_type(interc, actual_interc_num_inputs); - if (interc_physical_type == vpr_device_annotation.interconnect_physical_type(interc)) { + + e_interconnect interc_physical_type = + pb_interconnect_physical_type(interc, actual_interc_num_inputs); + if (interc_physical_type == + vpr_device_annotation.interconnect_physical_type(interc)) { /* Skip annotation if we have already done! */ continue; } VTR_LOGV(verbose_output, "Infer physical type '%s' of interconnect '%s' (was '%s')\n", - INTERCONNECT_TYPE_STRING[interc_physical_type], - interc->name, + INTERCONNECT_TYPE_STRING[interc_physical_type], interc->name, INTERCONNECT_TYPE_STRING[interc->type]); - vpr_device_annotation.add_interconnect_physical_type(interc, interc_physical_type); + vpr_device_annotation.add_interconnect_physical_type( + interc, interc_physical_type); } } @@ -135,11 +152,12 @@ void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_nod } /* Find the physical mode of current pb_graph node */ - t_mode* physical_mode = vpr_device_annotation.physical_mode(pb_graph_node->pb_type); + t_mode* physical_mode = + vpr_device_annotation.physical_mode(pb_graph_node->pb_type); VTR_ASSERT(nullptr != physical_mode); - /* Before going recursive, we should check the interconnect between output pins - * Note that this is NOT applicable to primitive pb_graph nodes!!! + /* Before going recursive, we should check the interconnect between output + * pins Note that this is NOT applicable to primitive pb_graph nodes!!! * * pb_graph_node * -------------------------------+ @@ -157,13 +175,17 @@ void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_nod /* Find all the interconnects sourced from the output pins */ for (int iport = 0; iport < pb_graph_node->num_output_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ++ipin) { - for (int iedge = 0; iedge < pb_graph_node->output_pins[iport][ipin].num_input_edges; ++iedge) { - t_interconnect* interc = pb_graph_node->output_pins[iport][ipin].input_edges[iedge]->interconnect; + for (int iedge = 0; + iedge < pb_graph_node->output_pins[iport][ipin].num_input_edges; + ++iedge) { + t_interconnect* interc = pb_graph_node->output_pins[iport][ipin] + .input_edges[iedge] + ->interconnect; /* Ensure that the interconnect is unique in the list */ if (0 < interc_num_inputs.count(interc)) { continue; } - /* Unique interconnect, initialize the counter to be zero */ + /* Unique interconnect, initialize the counter to be zero */ interc_num_inputs[interc] = 0; } } @@ -180,86 +202,100 @@ void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_nod for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ++ipin) { /* For each interconnect, we count the total number of inputs */ for (const auto& pair : interc_num_inputs) { - interc_num_inputs[pair.first] += pb_graph_pin_inputs(&(pb_graph_node->output_pins[iport][ipin]), pair.first).size(); + interc_num_inputs[pair.first] += + pb_graph_pin_inputs(&(pb_graph_node->output_pins[iport][ipin]), + pair.first) + .size(); } } } - /* For each interconnect that has more than 1 input, we can infer the physical type */ + /* For each interconnect that has more than 1 input, we can infer the + * physical type */ for (const auto& pair : interc_num_inputs) { t_interconnect* interc = pair.first; size_t actual_interc_num_inputs = pair.second; - /* If the number inputs for an interconnect is zero, this is a 0-driver pin - * we just set 1 to use direct wires + /* If the number inputs for an interconnect is zero, this is a 0-driver + * pin we just set 1 to use direct wires */ if (0 == actual_interc_num_inputs) { actual_interc_num_inputs = 1; } - - e_interconnect interc_physical_type = pb_interconnect_physical_type(interc, actual_interc_num_inputs); - if (interc_physical_type == vpr_device_annotation.interconnect_physical_type(interc)) { + + e_interconnect interc_physical_type = + pb_interconnect_physical_type(interc, actual_interc_num_inputs); + if (interc_physical_type == + vpr_device_annotation.interconnect_physical_type(interc)) { /* Skip annotation if we have already done! */ continue; } VTR_LOGV(verbose_output, "Infer physical type '%s' of interconnect '%s' (was '%s')\n", - INTERCONNECT_TYPE_STRING[interc_physical_type], - interc->name, + INTERCONNECT_TYPE_STRING[interc_physical_type], interc->name, INTERCONNECT_TYPE_STRING[interc->type]); - vpr_device_annotation.add_interconnect_physical_type(interc, interc_physical_type); + vpr_device_annotation.add_interconnect_physical_type( + interc, interc_physical_type); } } /* Recursively visit all the child pb_graph_nodes */ for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) { /* Each child may exist multiple times in the hierarchy*/ - for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; ++jpb) { - rec_build_vpr_pb_graph_interconnect_physical_type_annotation(&(pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), - vpr_device_annotation, - verbose_output); + for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; + ++jpb) { + rec_build_vpr_pb_graph_interconnect_physical_type_annotation( + &(pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), + vpr_device_annotation, verbose_output); } } } /******************************************************************** * This function aims to annotate the physical type for each interconnect - * inside the pb_graph + * inside the pb_graph * * Note: * - This function should be executed AFTER functions - * build_vpr_physical_pb_mode_explicit_annotation() - * build_vpr_physical_pb_mode_implicit_annotation() + * build_vpr_physical_pb_mode_explicit_annotation() + * build_vpr_physical_pb_mode_implicit_annotation() *******************************************************************/ -void annotate_pb_graph_interconnect_physical_type(const DeviceContext& vpr_device_ctx, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { +void annotate_pb_graph_interconnect_physical_type( + const DeviceContext& vpr_device_ctx, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_graph head */ if (nullptr == lb_type.pb_graph_head) { continue; } - rec_build_vpr_pb_graph_interconnect_physical_type_annotation(lb_type.pb_graph_head, vpr_device_annotation, verbose_output); + rec_build_vpr_pb_graph_interconnect_physical_type_annotation( + lb_type.pb_graph_head, vpr_device_annotation, verbose_output); } } /******************************************************************** * This function will recursively walk through all the pb_graph nodes * starting from a top node. - * It aims to give an unique index to each pb_graph node + * It aims to give an unique index to each pb_graph node * * Therefore, the sequence in visiting the nodes is critical - * Here, we will follow the strategy where primitive nodes are visited first + * Here, we will follow the strategy where primitive nodes are visited first *******************************************************************/ -static -void rec_build_vpr_primitive_pb_graph_node_unique_index(t_pb_graph_node* pb_graph_node, - VprDeviceAnnotation& vpr_device_annotation) { +static void rec_build_vpr_primitive_pb_graph_node_unique_index( + t_pb_graph_node* pb_graph_node, VprDeviceAnnotation& vpr_device_annotation) { /* Go recursive first until we touch the primitive node */ if (false == is_primitive_pb_type(pb_graph_node->pb_type)) { for (int imode = 0; imode < pb_graph_node->pb_type->num_modes; ++imode) { - for (int ipb = 0; ipb < pb_graph_node->pb_type->modes[imode].num_pb_type_children; ++ipb) { + for (int ipb = 0; + ipb < pb_graph_node->pb_type->modes[imode].num_pb_type_children; + ++ipb) { /* Each child may exist multiple times in the hierarchy*/ - for (int jpb = 0; jpb < pb_graph_node->pb_type->modes[imode].pb_type_children[ipb].num_pb; ++jpb) { - rec_build_vpr_primitive_pb_graph_node_unique_index(&(pb_graph_node->child_pb_graph_nodes[imode][ipb][jpb]), - vpr_device_annotation); + for (int jpb = 0; + jpb < + pb_graph_node->pb_type->modes[imode].pb_type_children[ipb].num_pb; + ++jpb) { + rec_build_vpr_primitive_pb_graph_node_unique_index( + &(pb_graph_node->child_pb_graph_nodes[imode][ipb][jpb]), + vpr_device_annotation); } } } @@ -271,75 +307,82 @@ void rec_build_vpr_primitive_pb_graph_node_unique_index(t_pb_graph_node* pb_grap } /******************************************************************** - * This function aims to assign an unique index to each + * This function aims to assign an unique index to each * primitive pb_graph_node by following a recursive way in walking * through the pb_graph * - * Note: - * - The unique index is different from the placement_index in VPR's + * Note: + * - The unique index is different from the placement_index in VPR's * pb_graph_node data structure. The placement index is only unique - * for a node under its parent node. If the parent node is duplicated + * for a node under its parent node. If the parent node is duplicated * across the graph, the placement index is not unique. * For example, a CLB contains 10 LEs and each of LE contains 2 LUTs * Inside each LE, the placement index of the LUTs are 0 and 1 respectively. - * But these indices are not unique in the graph, as there are 20 LUTs in total + * But these indices are not unique in the graph, as there are 20 LUTs in + *total *******************************************************************/ -static -void annotate_primitive_pb_graph_node_unique_index(const DeviceContext& vpr_device_ctx, - VprDeviceAnnotation& vpr_device_annotation) { - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { +static void annotate_primitive_pb_graph_node_unique_index( + const DeviceContext& vpr_device_ctx, + VprDeviceAnnotation& vpr_device_annotation) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_graph head */ if (nullptr == lb_type.pb_graph_head) { continue; } - rec_build_vpr_primitive_pb_graph_node_unique_index(lb_type.pb_graph_head, vpr_device_annotation); + rec_build_vpr_primitive_pb_graph_node_unique_index(lb_type.pb_graph_head, + vpr_device_annotation); } } /******************************************************************** * Evaluate if the two pb_graph pins are matched by - * - pb_type port annotation + * - pb_type port annotation * - LSB/MSB and pin offset *******************************************************************/ -static -bool try_match_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, - t_pb_graph_pin* physical_pb_graph_pin, - const VprDeviceAnnotation& vpr_device_annotation) { +static bool try_match_pb_graph_pin( + t_pb_graph_pin* operating_pb_graph_pin, t_pb_graph_pin* physical_pb_graph_pin, + const VprDeviceAnnotation& vpr_device_annotation) { /* If the parent ports of the two pins are not paired, fail */ - for (t_port* candidate_port : vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) { + for (t_port* candidate_port : + vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) { if (physical_pb_graph_pin->port != candidate_port) { /* Not the one we want, try the next candidate */ continue; } - /* Check the pin number of physical pb_graph_pin matches the pin number of - * operating pb_graph_pin plus a rotation offset with an initial offset, + /* Check the pin number of physical pb_graph_pin matches the pin number of + * operating pb_graph_pin plus a rotation offset with an initial offset, * which is to align the lsb between operating and physical ports * - * For example: - * We can align the operating_port[32] to physical_port[0] with an initial offset - * which is -32 + * For example: + * We can align the operating_port[32] to physical_port[0] with an initial + * offset which is -32 * - * operating port physical port - * LSB port_range.lsb() pin_number pin_number MSB - * | | init_offset | - * Operating port | | +------ + | - * | |<----acc_offset--->| - * Physical port | + + + + * operating port physical port + * LSB port_range.lsb() pin_number pin_number MSB + * | | init_offset | + * Operating port | | +------ + | | + * |<----acc_offset--->| Physical port | + + + * - * Note: + * Note: * - accumulated offset is NOT the pin rotate offset specified by users * It is an aggregation of the offset during pin pairing - * Each time, we manage to pair two pins, the accumulated offset will be incremented - * by the pin rotate offset value - * The accumulated offset will be reset to 0 when it exceeds the msb() of the physical port + * Each time, we manage to pair two pins, the accumulated offset will be + * incremented by the pin rotate offset value The accumulated offset will be + * reset to 0 when it exceeds the msb() of the physical port */ - int acc_offset = vpr_device_annotation.physical_pb_pin_offset(operating_pb_graph_pin->port, candidate_port) + vpr_device_annotation.physical_pb_port_offset(operating_pb_graph_pin->port, candidate_port); - int init_offset = vpr_device_annotation.physical_pb_pin_initial_offset(operating_pb_graph_pin->port, candidate_port); - const BasicPort& physical_port_range = vpr_device_annotation.physical_pb_port_range(operating_pb_graph_pin->port, candidate_port); - if (physical_pb_graph_pin->pin_number != operating_pb_graph_pin->pin_number - + (int)physical_port_range.get_lsb() - + init_offset - + acc_offset) { + int acc_offset = vpr_device_annotation.physical_pb_pin_offset( + operating_pb_graph_pin->port, candidate_port) + + vpr_device_annotation.physical_pb_port_offset( + operating_pb_graph_pin->port, candidate_port); + int init_offset = vpr_device_annotation.physical_pb_pin_initial_offset( + operating_pb_graph_pin->port, candidate_port); + const BasicPort& physical_port_range = + vpr_device_annotation.physical_pb_port_range(operating_pb_graph_pin->port, + candidate_port); + if (physical_pb_graph_pin->pin_number != + operating_pb_graph_pin->pin_number + + (int)physical_port_range.get_lsb() + init_offset + acc_offset) { /* Not the one we want, try the next candidate */ continue; } @@ -356,91 +399,112 @@ bool try_match_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, * A function to print message to log file/screen when physical pb_graph_pin * binding succeed *******************************************************************/ -static -void print_success_bind_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, - t_pb_graph_pin* physical_pb_graph_pin) { - VTR_LOG("Bind a pb_graph_node '%s[%d]' pin '%s[%d]' to a pb_graph_node '%s[%d]' pin '%s[%d]'!\n", - operating_pb_graph_pin->parent_node->pb_type->name, - operating_pb_graph_pin->parent_node->placement_index, - operating_pb_graph_pin->port->name, - operating_pb_graph_pin->pin_number, - physical_pb_graph_pin->parent_node->pb_type->name, - physical_pb_graph_pin->parent_node->placement_index, - physical_pb_graph_pin->port->name, - physical_pb_graph_pin->pin_number); +static void print_success_bind_pb_graph_pin( + t_pb_graph_pin* operating_pb_graph_pin, + t_pb_graph_pin* physical_pb_graph_pin) { + VTR_LOG( + "Bind a pb_graph_node '%s[%d]' pin '%s[%d]' to a pb_graph_node '%s[%d]' " + "pin '%s[%d]'!\n", + operating_pb_graph_pin->parent_node->pb_type->name, + operating_pb_graph_pin->parent_node->placement_index, + operating_pb_graph_pin->port->name, operating_pb_graph_pin->pin_number, + physical_pb_graph_pin->parent_node->pb_type->name, + physical_pb_graph_pin->parent_node->placement_index, + physical_pb_graph_pin->port->name, physical_pb_graph_pin->pin_number); } /******************************************************************** - * Bind a pb_graph_pin from an operating pb_graph_node to + * Bind a pb_graph_pin from an operating pb_graph_node to * a pb_graph_pin from a physical pb_graph_node * - the name matching rules are already defined in the vpr_device_annotation *******************************************************************/ -static -void annotate_physical_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, - t_pb_graph_node* physical_pb_graph_node, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { - /* Iterate over every port and pin of the operating pb_graph_node - * and find the physical pins +static void annotate_physical_pb_graph_pin( + t_pb_graph_pin* operating_pb_graph_pin, + t_pb_graph_node* physical_pb_graph_node, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { + /* Iterate over every port and pin of the operating pb_graph_node + * and find the physical pins */ - for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; ++ipin) { - if (false == try_match_pb_graph_pin(operating_pb_graph_pin, - &(physical_pb_graph_node->input_pins[iport][ipin]), - vpr_device_annotation)) { + for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; + ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; + ++ipin) { + if (false == try_match_pb_graph_pin( + operating_pb_graph_pin, + &(physical_pb_graph_node->input_pins[iport][ipin]), + vpr_device_annotation)) { continue; } - /* Reach here, it means the pins are matched by the annotation requirements - * We can pair the pin and return + /* Reach here, it means the pins are matched by the annotation + * requirements We can pair the pin and return */ - vpr_device_annotation.add_physical_pb_graph_pin(operating_pb_graph_pin, &(physical_pb_graph_node->input_pins[iport][ipin])); + vpr_device_annotation.add_physical_pb_graph_pin( + operating_pb_graph_pin, + &(physical_pb_graph_node->input_pins[iport][ipin])); if (true == verbose_output) { - print_success_bind_pb_graph_pin(operating_pb_graph_pin, vpr_device_annotation.physical_pb_graph_pin(operating_pb_graph_pin)); + print_success_bind_pb_graph_pin( + operating_pb_graph_pin, + vpr_device_annotation.physical_pb_graph_pin(operating_pb_graph_pin)); } return; } } - for (int iport = 0; iport < physical_pb_graph_node->num_output_ports; ++iport) { - for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; ++ipin) { - if (false == try_match_pb_graph_pin(operating_pb_graph_pin, - &(physical_pb_graph_node->output_pins[iport][ipin]), - vpr_device_annotation)) { + for (int iport = 0; iport < physical_pb_graph_node->num_output_ports; + ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; + ++ipin) { + if (false == try_match_pb_graph_pin( + operating_pb_graph_pin, + &(physical_pb_graph_node->output_pins[iport][ipin]), + vpr_device_annotation)) { continue; } - /* Reach here, it means the pins are matched by the annotation requirements - * We can pair the pin and return + /* Reach here, it means the pins are matched by the annotation + * requirements We can pair the pin and return */ - vpr_device_annotation.add_physical_pb_graph_pin(operating_pb_graph_pin, &(physical_pb_graph_node->output_pins[iport][ipin])); + vpr_device_annotation.add_physical_pb_graph_pin( + operating_pb_graph_pin, + &(physical_pb_graph_node->output_pins[iport][ipin])); if (true == verbose_output) { - print_success_bind_pb_graph_pin(operating_pb_graph_pin, vpr_device_annotation.physical_pb_graph_pin(operating_pb_graph_pin)); + print_success_bind_pb_graph_pin( + operating_pb_graph_pin, + vpr_device_annotation.physical_pb_graph_pin(operating_pb_graph_pin)); } return; } } - for (int iport = 0; iport < physical_pb_graph_node->num_clock_ports; ++iport) { - for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; ++ipin) { - if (false == try_match_pb_graph_pin(operating_pb_graph_pin, - &(physical_pb_graph_node->clock_pins[iport][ipin]), - vpr_device_annotation)) { + for (int iport = 0; iport < physical_pb_graph_node->num_clock_ports; + ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; + ++ipin) { + if (false == try_match_pb_graph_pin( + operating_pb_graph_pin, + &(physical_pb_graph_node->clock_pins[iport][ipin]), + vpr_device_annotation)) { continue; } - /* Reach here, it means the pins are matched by the annotation requirements - * We can pair the pin and return + /* Reach here, it means the pins are matched by the annotation + * requirements We can pair the pin and return */ - vpr_device_annotation.add_physical_pb_graph_pin(operating_pb_graph_pin, &(physical_pb_graph_node->clock_pins[iport][ipin])); + vpr_device_annotation.add_physical_pb_graph_pin( + operating_pb_graph_pin, + &(physical_pb_graph_node->clock_pins[iport][ipin])); if (true == verbose_output) { - print_success_bind_pb_graph_pin(operating_pb_graph_pin, vpr_device_annotation.physical_pb_graph_pin(operating_pb_graph_pin)); + print_success_bind_pb_graph_pin( + operating_pb_graph_pin, + vpr_device_annotation.physical_pb_graph_pin(operating_pb_graph_pin)); } return; } } /* If we reach here, it means that pin pairing fails, error out! */ - VTR_LOG_ERROR("Fail to match a physical pin for '%s' from pb_graph_node '%s'!\n", - operating_pb_graph_pin->to_string().c_str(), - physical_pb_graph_node->hierarchical_type_name().c_str()); + VTR_LOG_ERROR( + "Fail to match a physical pin for '%s' from pb_graph_node '%s'!\n", + operating_pb_graph_pin->to_string().c_str(), + physical_pb_graph_node->hierarchical_type_name().c_str()); } /******************************************************************** @@ -449,59 +513,73 @@ void annotate_physical_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, * available in vpr_device_annotation * It will add the pin bindings to the vpr_device_annotation *******************************************************************/ -static -void annotate_physical_pb_graph_node_pins(t_pb_graph_node* operating_pb_graph_node, - t_pb_graph_node* physical_pb_graph_node, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { - /* Iterate over every port and pin of the operating pb_graph_node - * and find the physical pins +static void annotate_physical_pb_graph_node_pins( + t_pb_graph_node* operating_pb_graph_node, + t_pb_graph_node* physical_pb_graph_node, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { + /* Iterate over every port and pin of the operating pb_graph_node + * and find the physical pins */ - for (int iport = 0; iport < operating_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < operating_pb_graph_node->num_input_pins[iport]; ++ipin) { - annotate_physical_pb_graph_pin(&(operating_pb_graph_node->input_pins[iport][ipin]), - physical_pb_graph_node, vpr_device_annotation, - verbose_output); + for (int iport = 0; iport < operating_pb_graph_node->num_input_ports; + ++iport) { + for (int ipin = 0; ipin < operating_pb_graph_node->num_input_pins[iport]; + ++ipin) { + annotate_physical_pb_graph_pin( + &(operating_pb_graph_node->input_pins[iport][ipin]), + physical_pb_graph_node, vpr_device_annotation, verbose_output); } /* Finish a port, accumulate the port-level offset affiliated to the port */ if (0 == operating_pb_graph_node->num_input_pins[iport]) { continue; } - t_pb_graph_pin* operating_pb_graph_pin = &(operating_pb_graph_node->input_pins[iport][0]); - for (t_port* candidate_port : vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) { - vpr_device_annotation.accumulate_physical_pb_port_rotate_offset(operating_pb_graph_pin->port, candidate_port); + t_pb_graph_pin* operating_pb_graph_pin = + &(operating_pb_graph_node->input_pins[iport][0]); + for (t_port* candidate_port : + vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) { + vpr_device_annotation.accumulate_physical_pb_port_rotate_offset( + operating_pb_graph_pin->port, candidate_port); } } - for (int iport = 0; iport < operating_pb_graph_node->num_output_ports; ++iport) { - for (int ipin = 0; ipin < operating_pb_graph_node->num_output_pins[iport]; ++ipin) { - annotate_physical_pb_graph_pin(&(operating_pb_graph_node->output_pins[iport][ipin]), - physical_pb_graph_node, vpr_device_annotation, - verbose_output); + for (int iport = 0; iport < operating_pb_graph_node->num_output_ports; + ++iport) { + for (int ipin = 0; ipin < operating_pb_graph_node->num_output_pins[iport]; + ++ipin) { + annotate_physical_pb_graph_pin( + &(operating_pb_graph_node->output_pins[iport][ipin]), + physical_pb_graph_node, vpr_device_annotation, verbose_output); } /* Finish a port, accumulate the port-level offset affiliated to the port */ if (0 == operating_pb_graph_node->num_output_pins[iport]) { continue; } - t_pb_graph_pin* operating_pb_graph_pin = &(operating_pb_graph_node->output_pins[iport][0]); - for (t_port* candidate_port : vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) { - vpr_device_annotation.accumulate_physical_pb_port_rotate_offset(operating_pb_graph_pin->port, candidate_port); + t_pb_graph_pin* operating_pb_graph_pin = + &(operating_pb_graph_node->output_pins[iport][0]); + for (t_port* candidate_port : + vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) { + vpr_device_annotation.accumulate_physical_pb_port_rotate_offset( + operating_pb_graph_pin->port, candidate_port); } } - for (int iport = 0; iport < operating_pb_graph_node->num_clock_ports; ++iport) { - for (int ipin = 0; ipin < operating_pb_graph_node->num_clock_pins[iport]; ++ipin) { - annotate_physical_pb_graph_pin(&(operating_pb_graph_node->clock_pins[iport][ipin]), - physical_pb_graph_node, vpr_device_annotation, - verbose_output); + for (int iport = 0; iport < operating_pb_graph_node->num_clock_ports; + ++iport) { + for (int ipin = 0; ipin < operating_pb_graph_node->num_clock_pins[iport]; + ++ipin) { + annotate_physical_pb_graph_pin( + &(operating_pb_graph_node->clock_pins[iport][ipin]), + physical_pb_graph_node, vpr_device_annotation, verbose_output); } /* Finish a port, accumulate the port-level offset affiliated to the port */ if (0 == operating_pb_graph_node->num_clock_pins[iport]) { continue; } - t_pb_graph_pin* operating_pb_graph_pin = &(operating_pb_graph_node->clock_pins[iport][0]); - for (t_port* candidate_port : vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) { - vpr_device_annotation.accumulate_physical_pb_port_rotate_offset(operating_pb_graph_pin->port, candidate_port); + t_pb_graph_pin* operating_pb_graph_pin = + &(operating_pb_graph_node->clock_pins[iport][0]); + for (t_port* candidate_port : + vpr_device_annotation.physical_pb_port(operating_pb_graph_pin->port)) { + vpr_device_annotation.accumulate_physical_pb_port_rotate_offset( + operating_pb_graph_pin->port, candidate_port); } } } @@ -509,24 +587,28 @@ void annotate_physical_pb_graph_node_pins(t_pb_graph_node* operating_pb_graph_no /******************************************************************** * This function will recursively walk through all the pb_graph nodes * starting from a top node. - * It aims to give an unique index to each pb_graph node + * It aims to give an unique index to each pb_graph node * * Therefore, the sequence in visiting the nodes is critical - * Here, we will follow the strategy where primitive nodes are visited first + * Here, we will follow the strategy where primitive nodes are visited first *******************************************************************/ -static -void rec_build_vpr_physical_pb_graph_node_annotation(t_pb_graph_node* pb_graph_node, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { +static void rec_build_vpr_physical_pb_graph_node_annotation( + t_pb_graph_node* pb_graph_node, VprDeviceAnnotation& vpr_device_annotation, + const bool& verbose_output) { /* Go recursive first until we touch the primitive node */ if (false == is_primitive_pb_type(pb_graph_node->pb_type)) { for (int imode = 0; imode < pb_graph_node->pb_type->num_modes; ++imode) { - for (int ipb = 0; ipb < pb_graph_node->pb_type->modes[imode].num_pb_type_children; ++ipb) { + for (int ipb = 0; + ipb < pb_graph_node->pb_type->modes[imode].num_pb_type_children; + ++ipb) { /* Each child may exist multiple times in the hierarchy*/ - for (int jpb = 0; jpb < pb_graph_node->pb_type->modes[imode].pb_type_children[ipb].num_pb; ++jpb) { - rec_build_vpr_physical_pb_graph_node_annotation(&(pb_graph_node->child_pb_graph_nodes[imode][ipb][jpb]), - vpr_device_annotation, - verbose_output); + for (int jpb = 0; + jpb < + pb_graph_node->pb_type->modes[imode].pb_type_children[ipb].num_pb; + ++jpb) { + rec_build_vpr_physical_pb_graph_node_annotation( + &(pb_graph_node->child_pb_graph_nodes[imode][ipb][jpb]), + vpr_device_annotation, verbose_output); } } } @@ -534,28 +616,34 @@ void rec_build_vpr_physical_pb_graph_node_annotation(t_pb_graph_node* pb_graph_n } /* To bind operating pb_graph_node to their physical pb_graph_node: - * - Get the physical pb_type that this type of pb_graph_node should be mapped to + * - Get the physical pb_type that this type of pb_graph_node should be + * mapped to * - Calculate the unique index of physical pb_graph_node to which * this pb_graph_node should be binded - * - Find the physical pb_graph_node with the given index - * To bind pins from operating pb_graph_node to their physical pb_graph_node pins + * - Find the physical pb_graph_node with the given index + * To bind pins from operating pb_graph_node to their physical pb_graph_node + * pins */ - t_pb_type* physical_pb_type = vpr_device_annotation.physical_pb_type(pb_graph_node->pb_type); + t_pb_type* physical_pb_type = + vpr_device_annotation.physical_pb_type(pb_graph_node->pb_type); VTR_ASSERT(nullptr != physical_pb_type); /* Index inference: - * physical_pb_graph_node_unique_index = operating_pb_graph_node_unique_index * factor + offset - * where factor and offset are provided by users + * physical_pb_graph_node_unique_index = operating_pb_graph_node_unique_index + * * factor + offset where factor and offset are provided by users */ PbGraphNodeId physical_pb_graph_node_id = PbGraphNodeId( - vpr_device_annotation.physical_pb_type_index_factor(pb_graph_node->pb_type) - * (size_t)vpr_device_annotation.pb_graph_node_unique_index(pb_graph_node) - + vpr_device_annotation.physical_pb_type_index_offset(pb_graph_node->pb_type) - ); + vpr_device_annotation.physical_pb_type_index_factor( + pb_graph_node->pb_type) * + (size_t)vpr_device_annotation.pb_graph_node_unique_index(pb_graph_node) + + vpr_device_annotation.physical_pb_type_index_offset( + pb_graph_node->pb_type)); - t_pb_graph_node* physical_pb_graph_node = vpr_device_annotation.pb_graph_node(physical_pb_type, physical_pb_graph_node_id); + t_pb_graph_node* physical_pb_graph_node = vpr_device_annotation.pb_graph_node( + physical_pb_type, physical_pb_graph_node_id); VTR_ASSERT(nullptr != physical_pb_graph_node); - vpr_device_annotation.add_physical_pb_graph_node(pb_graph_node, physical_pb_graph_node); + vpr_device_annotation.add_physical_pb_graph_node(pb_graph_node, + physical_pb_graph_node); VTR_LOGV(verbose_output, "Bind operating pb_graph_node '%s' to physical pb_graph_node '%s'\n", @@ -563,7 +651,8 @@ void rec_build_vpr_physical_pb_graph_node_annotation(t_pb_graph_node* pb_graph_n physical_pb_graph_node->hierarchical_type_name().c_str()); /* Try to bind each pins under this pb_graph_node to physical_pb_graph_node */ - annotate_physical_pb_graph_node_pins(pb_graph_node, physical_pb_graph_node, vpr_device_annotation, verbose_output); + annotate_physical_pb_graph_node_pins(pb_graph_node, physical_pb_graph_node, + vpr_device_annotation, verbose_output); } /******************************************************************** @@ -571,16 +660,17 @@ void rec_build_vpr_physical_pb_graph_node_annotation(t_pb_graph_node* pb_graph_n * - Bind operating pb_graph_node to their physical pb_graph_node * - Bind pins from operating pb_graph_node to their physical pb_graph_node pins *******************************************************************/ -static -void annotate_physical_pb_graph_node(const DeviceContext& vpr_device_ctx, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { +static void annotate_physical_pb_graph_node( + const DeviceContext& vpr_device_ctx, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_graph head */ if (nullptr == lb_type.pb_graph_head) { continue; } - rec_build_vpr_physical_pb_graph_node_annotation(lb_type.pb_graph_head, vpr_device_annotation, verbose_output); + rec_build_vpr_physical_pb_graph_node_annotation( + lb_type.pb_graph_head, vpr_device_annotation, verbose_output); } } @@ -590,23 +680,27 @@ void annotate_physical_pb_graph_node(const DeviceContext& vpr_device_ctx, * - Bind operating pb_graph_node to their physical pb_graph_node * - Bind pins from operating pb_graph_node to their physical pb_graph_node pins *******************************************************************/ -void annotate_pb_graph(const DeviceContext& vpr_device_ctx, +void annotate_pb_graph(const DeviceContext& vpr_device_ctx, VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { - VTR_LOG("Assigning unique indices for primitive pb_graph nodes..."); VTR_LOGV(verbose_output, "\n"); - annotate_primitive_pb_graph_node_unique_index(vpr_device_ctx, vpr_device_annotation); + annotate_primitive_pb_graph_node_unique_index(vpr_device_ctx, + vpr_device_annotation); VTR_LOG("Done\n"); - VTR_LOG("Binding operating pb_graph nodes/pins to physical pb_graph nodes/pins..."); + VTR_LOG( + "Binding operating pb_graph nodes/pins to physical pb_graph nodes/pins..."); VTR_LOGV(verbose_output, "\n"); - annotate_physical_pb_graph_node(vpr_device_ctx, vpr_device_annotation, verbose_output); + annotate_physical_pb_graph_node(vpr_device_ctx, vpr_device_annotation, + verbose_output); VTR_LOG("Done\n"); - /* Check each primitive pb_graph_node and pin has been binded to a physical node and pin */ - check_physical_pb_graph_node_annotation(vpr_device_ctx, const_cast(vpr_device_annotation)); + /* Check each primitive pb_graph_node and pin has been binded to a physical + * node and pin */ + check_physical_pb_graph_node_annotation( + vpr_device_ctx, + const_cast(vpr_device_annotation)); } } /* end namespace openfpga */ - diff --git a/openfpga/src/annotation/annotate_pb_graph.h b/openfpga/src/annotation/annotate_pb_graph.h index 5dd140da8..2e03f4ea8 100644 --- a/openfpga/src/annotation/annotate_pb_graph.h +++ b/openfpga/src/annotation/annotate_pb_graph.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" #include "openfpga_context.h" +#include "vpr_context.h" #include "vpr_device_annotation.h" /******************************************************************** @@ -15,11 +15,11 @@ /* begin namespace openfpga */ namespace openfpga { -void annotate_pb_graph_interconnect_physical_type(const DeviceContext& vpr_device_ctx, - VprDeviceAnnotation& vpr_pb_type_annotation, - const bool& verbose_output); +void annotate_pb_graph_interconnect_physical_type( + const DeviceContext& vpr_device_ctx, + VprDeviceAnnotation& vpr_pb_type_annotation, const bool& verbose_output); -void annotate_pb_graph(const DeviceContext& vpr_device_ctx, +void annotate_pb_graph(const DeviceContext& vpr_device_ctx, VprDeviceAnnotation& vpr_pb_type_annotation, const bool& verbose_output); diff --git a/openfpga/src/annotation/annotate_pb_types.cpp b/openfpga/src/annotation/annotate_pb_types.cpp index e4b5f972c..69e1ebc96 100644 --- a/openfpga/src/annotation/annotate_pb_types.cpp +++ b/openfpga/src/annotation/annotate_pb_types.cpp @@ -3,85 +3,93 @@ * in particular to annotate the physical mode and physical pb_type *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" -#include "vtr_assert.h" -#include "vtr_log.h" +#include "annotate_pb_types.h" -#include "vpr_device_annotation.h" -#include "pb_type_utils.h" #include "annotate_pb_graph.h" #include "check_pb_type_annotation.h" -#include "annotate_pb_types.h" +#include "pb_type_utils.h" +#include "vpr_device_annotation.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * This function will identify the physical mode for each multi-mode - * pb_type in VPR pb_type graph by following the explicit definition + * This function will identify the physical mode for each multi-mode + * pb_type in VPR pb_type graph by following the explicit definition * in OpenFPGA architecture XML *******************************************************************/ -static -void build_vpr_physical_pb_mode_explicit_annotation(const DeviceContext& vpr_device_ctx, - const Arch& openfpga_arch, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { +static void build_vpr_physical_pb_mode_explicit_annotation( + const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { /* Walk through the pb_type annotation stored in the openfpga arch */ - for (const PbTypeAnnotation& pb_type_annotation : openfpga_arch.pb_type_annotations) { - /* Since our target is to annotate the physical mode name, + for (const PbTypeAnnotation& pb_type_annotation : + openfpga_arch.pb_type_annotations) { + /* Since our target is to annotate the physical mode name, * we can skip those has not physical mode defined */ if (true == pb_type_annotation.physical_mode_name().empty()) { continue; - } + } /* Identify if the pb_type is operating or physical, - * For operating pb_type, get the full name of operating pb_type - * For physical pb_type, get the full name of physical pb_type + * For operating pb_type, get the full name of operating pb_type + * For physical pb_type, get the full name of physical pb_type */ std::vector target_pb_type_names; std::vector target_pb_mode_names; if (true == pb_type_annotation.is_operating_pb_type()) { - target_pb_type_names = pb_type_annotation.operating_parent_pb_type_names(); - target_pb_type_names.push_back(pb_type_annotation.operating_pb_type_name()); + target_pb_type_names = + pb_type_annotation.operating_parent_pb_type_names(); + target_pb_type_names.push_back( + pb_type_annotation.operating_pb_type_name()); target_pb_mode_names = pb_type_annotation.operating_parent_mode_names(); - } + } if (true == pb_type_annotation.is_physical_pb_type()) { target_pb_type_names = pb_type_annotation.physical_parent_pb_type_names(); - target_pb_type_names.push_back(pb_type_annotation.physical_pb_type_name()); + target_pb_type_names.push_back( + pb_type_annotation.physical_pb_type_name()); target_pb_mode_names = pb_type_annotation.physical_parent_mode_names(); - } + } /* We must have at least one pb_type in the list */ VTR_ASSERT_SAFE(0 < target_pb_type_names.size()); - /* Pb type information are located at the logic_block_types in the device context of VPR - * We iterate over the vectors and find the pb_type matches the parent_pb_type_name + /* Pb type information are located at the logic_block_types in the device + * context of VPR We iterate over the vectors and find the pb_type matches + * the parent_pb_type_name */ bool link_success = false; - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } - /* Check the name of the top-level pb_type, if it does not match, we can bypass */ + /* Check the name of the top-level pb_type, if it does not match, we can + * bypass */ if (target_pb_type_names[0] != std::string(lb_type.pb_type->name)) { continue; } - /* Match the name in the top-level, we go further to search the pb_type in the graph */ - t_pb_type* target_pb_type = try_find_pb_type_with_given_path(lb_type.pb_type, target_pb_type_names, - target_pb_mode_names); + /* Match the name in the top-level, we go further to search the pb_type in + * the graph */ + t_pb_type* target_pb_type = try_find_pb_type_with_given_path( + lb_type.pb_type, target_pb_type_names, target_pb_mode_names); if (nullptr == target_pb_type) { continue; } /* Found, we update the annotation by assigning the physical mode */ - t_mode* physical_mode = find_pb_type_mode(target_pb_type, pb_type_annotation.physical_mode_name().c_str()); - vpr_device_annotation.add_pb_type_physical_mode(target_pb_type, physical_mode); - + t_mode* physical_mode = find_pb_type_mode( + target_pb_type, pb_type_annotation.physical_mode_name().c_str()); + vpr_device_annotation.add_pb_type_physical_mode(target_pb_type, + physical_mode); + /* Give a message */ VTR_LOGV(verbose_output, "Annotate pb_type '%s' with physical mode '%s'\n", @@ -93,27 +101,27 @@ void build_vpr_physical_pb_mode_explicit_annotation(const DeviceContext& vpr_dev if (false == link_success) { /* Not found, error out! */ - VTR_LOG_ERROR("Unable to find the pb_type '%s' in VPR architecture definition!\n", - target_pb_type_names.back().c_str()); + VTR_LOG_ERROR( + "Unable to find the pb_type '%s' in VPR architecture definition!\n", + target_pb_type_names.back().c_str()); return; } - } + } } /******************************************************************** * This function will recursively visit all the pb_type from the top - * pb_type in the graph and - * infer the physical mode for each multi-mode + * pb_type in the graph and + * infer the physical mode for each multi-mode * pb_type in VPR pb_type graph without OpenFPGA architecture XML * * The following rule is applied: - * if there is only 1 mode under a pb_type, it will be the default + * if there is only 1 mode under a pb_type, it will be the default * physical mode for this pb_type *******************************************************************/ -static -void rec_infer_vpr_physical_pb_mode_annotation(t_pb_type* cur_pb_type, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { +static void rec_infer_vpr_physical_pb_mode_annotation( + t_pb_type* cur_pb_type, VprDeviceAnnotation& vpr_device_annotation, + const bool& verbose_output) { /* We do not check any primitive pb_type */ if (true == is_primitive_pb_type(cur_pb_type)) { return; @@ -123,14 +131,15 @@ void rec_infer_vpr_physical_pb_mode_annotation(t_pb_type* cur_pb_type, * - if there is only one mode, it will be the physical mode * we just need to make sure that we do not repeatedly annotate this * - if there are multiple modes, we should be able to find a physical mode - * and then go recursively + * and then go recursively */ t_mode* physical_mode = nullptr; if (1 == cur_pb_type->num_modes) { if (nullptr == vpr_device_annotation.physical_mode(cur_pb_type)) { /* Not assigned by explicit annotation, we should infer here */ - vpr_device_annotation.add_pb_type_physical_mode(cur_pb_type, &(cur_pb_type->modes[0])); + vpr_device_annotation.add_pb_type_physical_mode(cur_pb_type, + &(cur_pb_type->modes[0])); VTR_LOGV(verbose_output, "Implicitly infer physical mode '%s' for pb_type '%s'\n", cur_pb_type->modes[0].name, cur_pb_type->name); @@ -139,80 +148,85 @@ void rec_infer_vpr_physical_pb_mode_annotation(t_pb_type* cur_pb_type, VTR_ASSERT(1 < cur_pb_type->num_modes); if (nullptr == vpr_device_annotation.physical_mode(cur_pb_type)) { /* Not assigned by explicit annotation, we should infer here */ - vpr_device_annotation.add_pb_type_physical_mode(cur_pb_type, &(cur_pb_type->modes[0])); - VTR_LOG_ERROR("Unable to find a physical mode for a multi-mode pb_type '%s'!\n", - cur_pb_type->name); + vpr_device_annotation.add_pb_type_physical_mode(cur_pb_type, + &(cur_pb_type->modes[0])); + VTR_LOG_ERROR( + "Unable to find a physical mode for a multi-mode pb_type '%s'!\n", + cur_pb_type->name); VTR_LOG_ERROR("Please specify in the OpenFPGA architecture\n"); return; } } - /* Get the physical mode from annotation */ + /* Get the physical mode from annotation */ physical_mode = vpr_device_annotation.physical_mode(cur_pb_type); VTR_ASSERT(nullptr != physical_mode); /* Traverse the pb_type children under the physical mode */ - for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { - rec_infer_vpr_physical_pb_mode_annotation(&(physical_mode->pb_type_children[ichild]), - vpr_device_annotation, - verbose_output); + for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { + rec_infer_vpr_physical_pb_mode_annotation( + &(physical_mode->pb_type_children[ichild]), vpr_device_annotation, + verbose_output); } } /******************************************************************** - * This function will infer the physical mode for each multi-mode + * This function will infer the physical mode for each multi-mode * pb_type in VPR pb_type graph without OpenFPGA architecture XML * * The following rule is applied: - * if there is only 1 mode under a pb_type, it will be the default + * if there is only 1 mode under a pb_type, it will be the default * physical mode for this pb_type * - * Note: + * Note: * This function must be executed AFTER the function * build_vpr_physical_pb_mode_explicit_annotation() *******************************************************************/ -static -void build_vpr_physical_pb_mode_implicit_annotation(const DeviceContext& vpr_device_ctx, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { +static void build_vpr_physical_pb_mode_implicit_annotation( + const DeviceContext& vpr_device_ctx, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } - rec_infer_vpr_physical_pb_mode_annotation(lb_type.pb_type, vpr_device_annotation, verbose_output); + rec_infer_vpr_physical_pb_mode_annotation( + lb_type.pb_type, vpr_device_annotation, verbose_output); } } /******************************************************************** - * This function aims to make a pair of operating and physical + * This function aims to make a pair of operating and physical * pb_types: * - In addition to pairing the pb_types, it will pair the ports of the pb_types - * - For the ports which are explicited annotated as physical pin mapping - * in the pb_type annotation. - * We will check the port range and create a pair + * - For the ports which are explicited annotated as physical pin mapping + * in the pb_type annotation. + * We will check the port range and create a pair * - For the ports which are not specified in the pb_type annotation * we assume their physical ports share the same as the operating ports * We will try to find a port in the physical pb_type and check the port range - * If found, we will create a pair + * If found, we will create a pair * - All the pairs will be updated in vpr_device_annotation *******************************************************************/ -static -bool pair_operating_and_physical_pb_types(t_pb_type* operating_pb_type, - t_pb_type* physical_pb_type, - const PbTypeAnnotation& pb_type_annotation, - VprDeviceAnnotation& vpr_device_annotation) { +static bool pair_operating_and_physical_pb_types( + t_pb_type* operating_pb_type, t_pb_type* physical_pb_type, + const PbTypeAnnotation& pb_type_annotation, + VprDeviceAnnotation& vpr_device_annotation) { /* Reach here, we should have valid operating and physical pb_types */ VTR_ASSERT((nullptr != operating_pb_type) && (nullptr != physical_pb_type)); - - /* Iterate over the ports under the operating pb_type - * For each pin, we will try to find its physical port in the pb_type_annotation - * if not found, we assume that the physical port is the same as the operating pb_port + + /* Iterate over the ports under the operating pb_type + * For each pin, we will try to find its physical port in the + * pb_type_annotation if not found, we assume that the physical port is the + * same as the operating pb_port */ for (t_port* operating_pb_port : pb_type_ports(operating_pb_type)) { - std::map> expected_physical_pb_ports = pb_type_annotation.physical_pb_type_port(std::string(operating_pb_port->name)); - + std::map> expected_physical_pb_ports = + pb_type_annotation.physical_pb_type_port( + std::string(operating_pb_port->name)); + /* If not defined in the annotation, set the default pair: * rotate_offset is 0 by default! */ @@ -225,25 +239,35 @@ bool pair_operating_and_physical_pb_types(t_pb_type* operating_pb_type, for (const auto& expected_physical_pb_port : expected_physical_pb_ports) { /* Try to find the expected port in the physical pb_type */ - t_port* physical_pb_port = find_pb_type_port(physical_pb_type, expected_physical_pb_port.first.get_name()); + t_port* physical_pb_port = find_pb_type_port( + physical_pb_type, expected_physical_pb_port.first.get_name()); /* Not found, mapping fails */ if (nullptr == physical_pb_port) { return false; } /* If the port range does not match, mapping fails */ - if (false == BasicPort(physical_pb_port->name, physical_pb_port->num_pins).contained(expected_physical_pb_port.first)) { + if (false == BasicPort(physical_pb_port->name, physical_pb_port->num_pins) + .contained(expected_physical_pb_port.first)) { return false; } - /* Now, port mapping should succeed, we update the vpr_device_annotation + /* Now, port mapping should succeed, we update the vpr_device_annotation * - port binding * - port range * - port pin rotate offset */ - vpr_device_annotation.add_physical_pb_port(operating_pb_port, physical_pb_port); - vpr_device_annotation.add_physical_pb_port_range(operating_pb_port, physical_pb_port, expected_physical_pb_port.first); - vpr_device_annotation.add_physical_pb_pin_initial_offset(operating_pb_port, physical_pb_port, expected_physical_pb_port.second[0]); - vpr_device_annotation.add_physical_pb_pin_rotate_offset(operating_pb_port, physical_pb_port, expected_physical_pb_port.second[1]); - vpr_device_annotation.add_physical_pb_port_rotate_offset(operating_pb_port, physical_pb_port, expected_physical_pb_port.second[2]); + vpr_device_annotation.add_physical_pb_port(operating_pb_port, + physical_pb_port); + vpr_device_annotation.add_physical_pb_port_range( + operating_pb_port, physical_pb_port, expected_physical_pb_port.first); + vpr_device_annotation.add_physical_pb_pin_initial_offset( + operating_pb_port, physical_pb_port, + expected_physical_pb_port.second[0]); + vpr_device_annotation.add_physical_pb_pin_rotate_offset( + operating_pb_port, physical_pb_port, + expected_physical_pb_port.second[1]); + vpr_device_annotation.add_physical_pb_port_rotate_offset( + operating_pb_port, physical_pb_port, + expected_physical_pb_port.second[2]); } } @@ -252,30 +276,32 @@ bool pair_operating_and_physical_pb_types(t_pb_type* operating_pb_type, * - physical_pb_type_index_factor * - physical_pb_type_index_offset */ - vpr_device_annotation.add_physical_pb_type(operating_pb_type, physical_pb_type); - vpr_device_annotation.add_physical_pb_type_index_factor(operating_pb_type, pb_type_annotation.physical_pb_type_index_factor()); - vpr_device_annotation.add_physical_pb_type_index_offset(operating_pb_type, pb_type_annotation.physical_pb_type_index_offset()); + vpr_device_annotation.add_physical_pb_type(operating_pb_type, + physical_pb_type); + vpr_device_annotation.add_physical_pb_type_index_factor( + operating_pb_type, pb_type_annotation.physical_pb_type_index_factor()); + vpr_device_annotation.add_physical_pb_type_index_offset( + operating_pb_type, pb_type_annotation.physical_pb_type_index_offset()); return true; } /******************************************************************** - * This function will identify the physical pb_type for each operating - * pb_type in VPR pb_type graph by following the explicit definition + * This function will identify the physical pb_type for each operating + * pb_type in VPR pb_type graph by following the explicit definition * in OpenFPGA architecture XML * * Note: - * - This function should be executed only AFTER the physical mode + * - This function should be executed only AFTER the physical mode * annotation is completed *******************************************************************/ -static -void build_vpr_physical_pb_type_explicit_annotation(const DeviceContext& vpr_device_ctx, - const Arch& openfpga_arch, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { +static void build_vpr_physical_pb_type_explicit_annotation( + const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { /* Walk through the pb_type annotation stored in the openfpga arch */ - for (const PbTypeAnnotation& pb_type_annotation : openfpga_arch.pb_type_annotations) { - /* Since our target is to annotate the operating pb_type tp physical pb_type + for (const PbTypeAnnotation& pb_type_annotation : + openfpga_arch.pb_type_annotations) { + /* Since our target is to annotate the operating pb_type tp physical pb_type * we can skip those annotation only for physical pb_type */ if (true == pb_type_annotation.is_physical_pb_type()) { @@ -284,64 +310,74 @@ void build_vpr_physical_pb_type_explicit_annotation(const DeviceContext& vpr_dev VTR_ASSERT(true == pb_type_annotation.is_operating_pb_type()); - /* Collect the information about the full hierarchy of operating pb_type to be annotated */ + /* Collect the information about the full hierarchy of operating pb_type to + * be annotated */ std::vector target_op_pb_type_names; std::vector target_op_pb_mode_names; - target_op_pb_type_names = pb_type_annotation.operating_parent_pb_type_names(); - target_op_pb_type_names.push_back(pb_type_annotation.operating_pb_type_name()); + target_op_pb_type_names = + pb_type_annotation.operating_parent_pb_type_names(); + target_op_pb_type_names.push_back( + pb_type_annotation.operating_pb_type_name()); target_op_pb_mode_names = pb_type_annotation.operating_parent_mode_names(); - /* Collect the information about the full hierarchy of physical pb_type to be annotated */ + /* Collect the information about the full hierarchy of physical pb_type to + * be annotated */ std::vector target_phy_pb_type_names; std::vector target_phy_pb_mode_names; - target_phy_pb_type_names = pb_type_annotation.physical_parent_pb_type_names(); - target_phy_pb_type_names.push_back(pb_type_annotation.physical_pb_type_name()); + target_phy_pb_type_names = + pb_type_annotation.physical_parent_pb_type_names(); + target_phy_pb_type_names.push_back( + pb_type_annotation.physical_pb_type_name()); target_phy_pb_mode_names = pb_type_annotation.physical_parent_mode_names(); /* We must have at least one pb_type in the list */ VTR_ASSERT_SAFE(0 < target_op_pb_type_names.size()); VTR_ASSERT_SAFE(0 < target_phy_pb_type_names.size()); - /* Pb type information are located at the logic_block_types in the device context of VPR - * We iterate over the vectors and find the pb_type matches the parent_pb_type_name + /* Pb type information are located at the logic_block_types in the device + * context of VPR We iterate over the vectors and find the pb_type matches + * the parent_pb_type_name */ bool link_success = false; - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } - /* Check the name of the top-level pb_type, if it does not match, we can bypass */ + /* Check the name of the top-level pb_type, if it does not match, we can + * bypass */ if (target_op_pb_type_names[0] != std::string(lb_type.pb_type->name)) { continue; } - /* Match the name in the top-level, we go further to search the operating as well as - * physical pb_types in the graph */ - t_pb_type* target_op_pb_type = try_find_pb_type_with_given_path(lb_type.pb_type, target_op_pb_type_names, - target_op_pb_mode_names); + /* Match the name in the top-level, we go further to search the operating + * as well as physical pb_types in the graph */ + t_pb_type* target_op_pb_type = try_find_pb_type_with_given_path( + lb_type.pb_type, target_op_pb_type_names, target_op_pb_mode_names); if (nullptr == target_op_pb_type) { continue; } - t_pb_type* target_phy_pb_type = try_find_pb_type_with_given_path(lb_type.pb_type, target_phy_pb_type_names, - target_phy_pb_mode_names); + t_pb_type* target_phy_pb_type = try_find_pb_type_with_given_path( + lb_type.pb_type, target_phy_pb_type_names, target_phy_pb_mode_names); if (nullptr == target_phy_pb_type) { continue; } - /* Both operating and physical pb_type have been found, - * we update the annotation by assigning the physical mode + /* Both operating and physical pb_type have been found, + * we update the annotation by assigning the physical mode */ - if (true == pair_operating_and_physical_pb_types(target_op_pb_type, target_phy_pb_type, - pb_type_annotation, vpr_device_annotation)) { - + if (true == pair_operating_and_physical_pb_types( + target_op_pb_type, target_phy_pb_type, pb_type_annotation, + vpr_device_annotation)) { /* Give a message */ - VTR_LOGV(verbose_output, - "Annotate operating pb_type '%s' to its physical pb_type '%s'\n", - target_op_pb_type->name, target_phy_pb_type->name); + VTR_LOGV( + verbose_output, + "Annotate operating pb_type '%s' to its physical pb_type '%s'\n", + target_op_pb_type->name, target_phy_pb_type->name); link_success = true; break; @@ -350,50 +386,55 @@ void build_vpr_physical_pb_type_explicit_annotation(const DeviceContext& vpr_dev if (false == link_success) { /* Not found, error out! */ - VTR_LOG_ERROR("Unable to pair the operating pb_type '%s' to its physical pb_type '%s'!\n", - target_op_pb_type_names.back().c_str(), - target_phy_pb_type_names.back().c_str()); + VTR_LOG_ERROR( + "Unable to pair the operating pb_type '%s' to its physical pb_type " + "'%s'!\n", + target_op_pb_type_names.back().c_str(), + target_phy_pb_type_names.back().c_str()); } - } + } } /******************************************************************** * This function aims to pair a physical pb_type to itself *******************************************************************/ -static -bool self_pair_physical_pb_types(t_pb_type* physical_pb_type, - VprDeviceAnnotation& vpr_device_annotation) { +static bool self_pair_physical_pb_types( + t_pb_type* physical_pb_type, VprDeviceAnnotation& vpr_device_annotation) { /* Reach here, we should have valid physical pb_types */ VTR_ASSERT(nullptr != physical_pb_type); - - /* Iterate over the ports under the operating pb_type - * For each pin, we will try to find its physical port in the pb_type_annotation - * if not found, we assume that the physical port is the same as the operating pb_port + + /* Iterate over the ports under the operating pb_type + * For each pin, we will try to find its physical port in the + * pb_type_annotation if not found, we assume that the physical port is the + * same as the operating pb_port */ for (t_port* physical_pb_port : pb_type_ports(physical_pb_type)) { - BasicPort physical_port_range(physical_pb_port->name, physical_pb_port->num_pins); - vpr_device_annotation.add_physical_pb_port(physical_pb_port, physical_pb_port); - vpr_device_annotation.add_physical_pb_port_range(physical_pb_port, physical_pb_port, physical_port_range); + BasicPort physical_port_range(physical_pb_port->name, + physical_pb_port->num_pins); + vpr_device_annotation.add_physical_pb_port(physical_pb_port, + physical_pb_port); + vpr_device_annotation.add_physical_pb_port_range( + physical_pb_port, physical_pb_port, physical_port_range); } /* Now, pb_type mapping should succeed, we update the vpr_device_annotation */ - vpr_device_annotation.add_physical_pb_type(physical_pb_type, physical_pb_type); + vpr_device_annotation.add_physical_pb_type(physical_pb_type, + physical_pb_type); return true; } /******************************************************************** * This function will recursively visit all the pb_type from the top - * pb_type in the graph (only in the physical mode) and infer the - * physical pb_type - * This is mainly applied to single-mode pb_type graphs, where the + * pb_type in the graph (only in the physical mode) and infer the + * physical pb_type + * This is mainly applied to single-mode pb_type graphs, where the * physical pb_type should be pb_type itself * We can infer this and save the explicit annotation required by users *******************************************************************/ -static -void rec_infer_vpr_physical_pb_type_annotation(t_pb_type* cur_pb_type, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { +static void rec_infer_vpr_physical_pb_type_annotation( + t_pb_type* cur_pb_type, VprDeviceAnnotation& vpr_device_annotation, + const bool& verbose_output) { /* Physical pb_type is mainly for the primitive pb_type */ if (true == is_primitive_pb_type(cur_pb_type)) { /* If the physical pb_type has been mapped, we can skip it */ @@ -401,111 +442,118 @@ void rec_infer_vpr_physical_pb_type_annotation(t_pb_type* cur_pb_type, return; } /* Create the pair here */ - if (true == self_pair_physical_pb_types(cur_pb_type, vpr_device_annotation)) { + if (true == + self_pair_physical_pb_types(cur_pb_type, vpr_device_annotation)) { /* Give a message */ - VTR_LOGV(verbose_output, - "Implicitly infer the physical pb_type for pb_type '%s' itself\n", - cur_pb_type->name); + VTR_LOGV( + verbose_output, + "Implicitly infer the physical pb_type for pb_type '%s' itself\n", + cur_pb_type->name); } else { - VTR_LOG_ERROR("Unable to infer the physical pb_type for pb_type '%s' itself!\n", - cur_pb_type->name); + VTR_LOG_ERROR( + "Unable to infer the physical pb_type for pb_type '%s' itself!\n", + cur_pb_type->name); } return; } - /* Get the physical mode from annotation */ + /* Get the physical mode from annotation */ t_mode* physical_mode = vpr_device_annotation.physical_mode(cur_pb_type); VTR_ASSERT(nullptr != physical_mode); /* Traverse the pb_type children under the physical mode */ - for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { - rec_infer_vpr_physical_pb_type_annotation(&(physical_mode->pb_type_children[ichild]), - vpr_device_annotation, - verbose_output); + for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { + rec_infer_vpr_physical_pb_type_annotation( + &(physical_mode->pb_type_children[ichild]), vpr_device_annotation, + verbose_output); } } /******************************************************************** - * This function will infer the physical pb_type for each operating + * This function will infer the physical pb_type for each operating * pb_type in VPR pb_type graph which have not been explicitedly defined * in OpenFPGA architecture XML * * Note: - * - This function should be executed only AFTER the physical mode + * - This function should be executed only AFTER the physical mode * annotation is completed *******************************************************************/ -static -void build_vpr_physical_pb_type_implicit_annotation(const DeviceContext& vpr_device_ctx, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { +static void build_vpr_physical_pb_type_implicit_annotation( + const DeviceContext& vpr_device_ctx, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } - rec_infer_vpr_physical_pb_type_annotation(lb_type.pb_type, vpr_device_annotation, verbose_output); + rec_infer_vpr_physical_pb_type_annotation( + lb_type.pb_type, vpr_device_annotation, verbose_output); } } /******************************************************************** - * This function aims to link all the ports defined under a physical + * This function aims to link all the ports defined under a physical * pb_type to the ports of circuit model in the circuit library * The binding assumes that pb_type port should be defined with the same name * as the circuit port *******************************************************************/ -static -bool link_physical_pb_port_to_circuit_port(t_pb_type* physical_pb_type, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { +static bool link_physical_pb_port_to_circuit_port( + t_pb_type* physical_pb_type, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { bool link_success = true; /* Iterate over the pb_ports - * Note: - * - Not every port defined in the circuit model will appear under the pb_type - * Some circuit ports are just for physical implementation + * Note: + * - Not every port defined in the circuit model will appear under the + * pb_type Some circuit ports are just for physical implementation */ for (t_port* pb_port : pb_type_ports(physical_pb_type)) { - CircuitPortId circuit_port = circuit_lib.model_port(circuit_model, std::string(pb_port->name)); + CircuitPortId circuit_port = + circuit_lib.model_port(circuit_model, std::string(pb_port->name)); /* If we cannot find a port with the same name, error out */ if (CircuitPortId::INVALID() == circuit_port) { - VTR_LOG_ERROR("Pb type port '%s' is not found in any port of circuit model '%s'!\n", - pb_port->name, circuit_lib.model_name(circuit_model).c_str()); + VTR_LOG_ERROR( + "Pb type port '%s' is not found in any port of circuit model '%s'!\n", + pb_port->name, circuit_lib.model_name(circuit_model).c_str()); link_success = false; continue; } /* If the port width does not match, error out */ if ((size_t)(pb_port->num_pins) != circuit_lib.port_size(circuit_port)) { - VTR_LOG_ERROR("Pb type port '%s[%d:%d]' does not match the port '%s[%d:%d]' of circuit model '%s' in size!\n", - pb_port->name, - 0, pb_port->num_pins - 1, - circuit_lib.port_prefix(circuit_port).c_str(), - 0, circuit_lib.port_size(circuit_port) - 1, - circuit_lib.model_name(circuit_model).c_str()); + VTR_LOG_ERROR( + "Pb type port '%s[%d:%d]' does not match the port '%s[%d:%d]' of " + "circuit model '%s' in size!\n", + pb_port->name, 0, pb_port->num_pins - 1, + circuit_lib.port_prefix(circuit_port).c_str(), 0, + circuit_lib.port_size(circuit_port) - 1, + circuit_lib.model_name(circuit_model).c_str()); link_success = false; continue; } /* If the port type does not match, error out */ - if (ERR_PORT == circuit_port_require_pb_port_type(circuit_lib.port_type(circuit_port))) { - VTR_LOG_ERROR("Pb type port '%s' type does not match the port type '%s' of circuit model '%s'!\n", - pb_port->name, - circuit_lib.port_prefix(circuit_port).c_str(), - circuit_lib.model_name(circuit_model).c_str()); + if (ERR_PORT == circuit_port_require_pb_port_type( + circuit_lib.port_type(circuit_port))) { + VTR_LOG_ERROR( + "Pb type port '%s' type does not match the port type '%s' of circuit " + "model '%s'!\n", + pb_port->name, circuit_lib.port_prefix(circuit_port).c_str(), + circuit_lib.model_name(circuit_model).c_str()); link_success = false; continue; } - /* Reach here, it means that mapping should be ok, update the vpr_device_annotation */ + /* Reach here, it means that mapping should be ok, update the + * vpr_device_annotation */ vpr_device_annotation.add_pb_circuit_port(pb_port, circuit_port); VTR_LOGV(verbose_output, "Bind pb type '%s' port '%s' to circuit model '%s' port '%s'\n", - physical_pb_type->name, - pb_port->name, + physical_pb_type->name, pb_port->name, circuit_lib.model_name(circuit_model).c_str(), circuit_lib.port_prefix(circuit_port).c_str()); } @@ -517,133 +565,142 @@ bool link_physical_pb_port_to_circuit_port(t_pb_type* physical_pb_type, * This function aims to link a physical pb_type to a valid circuit model * in the circuit library *******************************************************************/ -static -bool link_physical_pb_type_to_circuit_model(t_pb_type* physical_pb_type, - const CircuitLibrary& circuit_lib, - const PbTypeAnnotation& pb_type_annotation, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { +static bool link_physical_pb_type_to_circuit_model( + t_pb_type* physical_pb_type, const CircuitLibrary& circuit_lib, + const PbTypeAnnotation& pb_type_annotation, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { /* Reach here, we should have valid operating and physical pb_types */ VTR_ASSERT(nullptr != physical_pb_type); /* This must be a physical pb_type according to our annotation! */ if (false == vpr_device_annotation.is_physical_pb_type(physical_pb_type)) { - VTR_LOG_ERROR("An operating pb_type '%s' is not allowed to be linked to any circuit model!\n", - physical_pb_type->name); + VTR_LOG_ERROR( + "An operating pb_type '%s' is not allowed to be linked to any circuit " + "model!\n", + physical_pb_type->name); return false; } - std::string pb_type_circuit_model_name = pb_type_annotation.circuit_model_name(); - CircuitModelId circuit_model_id = circuit_lib.model(pb_type_circuit_model_name); + std::string pb_type_circuit_model_name = + pb_type_annotation.circuit_model_name(); + CircuitModelId circuit_model_id = + circuit_lib.model(pb_type_circuit_model_name); if (CircuitModelId::INVALID() == circuit_model_id) { - VTR_LOG_ERROR("Unable to find a circuit model '%s' for physical pb_type '%s'!\n", - pb_type_circuit_model_name.c_str(), - physical_pb_type->name); + VTR_LOG_ERROR( + "Unable to find a circuit model '%s' for physical pb_type '%s'!\n", + pb_type_circuit_model_name.c_str(), physical_pb_type->name); return false; } /* Ensure that the pb_type ports can be matched in the circuit model ports */ - if (false == link_physical_pb_port_to_circuit_port(physical_pb_type, circuit_lib, circuit_model_id, - vpr_device_annotation, verbose_output)) { + if (false == link_physical_pb_port_to_circuit_port( + physical_pb_type, circuit_lib, circuit_model_id, + vpr_device_annotation, verbose_output)) { return false; } /* Now the circuit model is valid, update the vpr_device_annotation */ - vpr_device_annotation.add_pb_type_circuit_model(physical_pb_type, circuit_model_id); + vpr_device_annotation.add_pb_type_circuit_model(physical_pb_type, + circuit_model_id); return true; } /******************************************************************** - * This function aims to link an interconnect of a physical mode of + * This function aims to link an interconnect of a physical mode of * a pb_type to a valid circuit model in the circuit library *******************************************************************/ -static -bool link_physical_pb_interconnect_to_circuit_model(t_pb_type* physical_pb_type, - const std::string& interconnect_name, - const CircuitLibrary& circuit_lib, - const PbTypeAnnotation& pb_type_annotation, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { - /* The physical pb_type should NOT be a primitive, otherwise it should never contain any interconnect */ +static bool link_physical_pb_interconnect_to_circuit_model( + t_pb_type* physical_pb_type, const std::string& interconnect_name, + const CircuitLibrary& circuit_lib, const PbTypeAnnotation& pb_type_annotation, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { + /* The physical pb_type should NOT be a primitive, otherwise it should never + * contain any interconnect */ if (true == is_primitive_pb_type(physical_pb_type)) { - VTR_LOG_ERROR("Link interconnect to circuit model is not allowed for a primitive pb_type '%s'!\n", - physical_pb_type->name); + VTR_LOG_ERROR( + "Link interconnect to circuit model is not allowed for a primitive " + "pb_type '%s'!\n", + physical_pb_type->name); return false; } - /* Get the physical mode from annotation */ + /* Get the physical mode from annotation */ t_mode* physical_mode = vpr_device_annotation.physical_mode(physical_pb_type); VTR_ASSERT(nullptr != physical_mode); /* Find the interconnect name under the physical mode of a physical pb_type */ - t_interconnect* pb_interc = find_pb_mode_interconnect(physical_mode, interconnect_name.c_str()); + t_interconnect* pb_interc = + find_pb_mode_interconnect(physical_mode, interconnect_name.c_str()); if (nullptr == pb_interc) { - VTR_LOG_ERROR("Unable to find interconnect '%s' under physical mode '%s' of pb_type '%s'!\n", - interconnect_name.c_str(), - physical_mode->name, - physical_pb_type->name); + VTR_LOG_ERROR( + "Unable to find interconnect '%s' under physical mode '%s' of pb_type " + "'%s'!\n", + interconnect_name.c_str(), physical_mode->name, physical_pb_type->name); return false; } /* Try to find the circuit model name */ - std::string pb_type_circuit_model_name = pb_type_annotation.interconnect_circuit_model_name(interconnect_name); - CircuitModelId circuit_model_id = circuit_lib.model(pb_type_circuit_model_name); + std::string pb_type_circuit_model_name = + pb_type_annotation.interconnect_circuit_model_name(interconnect_name); + CircuitModelId circuit_model_id = + circuit_lib.model(pb_type_circuit_model_name); if (CircuitModelId::INVALID() == circuit_model_id) { - VTR_LOG_ERROR("Unable to find a circuit model '%s' for interconnect '%s' under physical mode '%s' of pb_type '%s'!\n", - pb_type_circuit_model_name.c_str(), - interconnect_name.c_str(), - physical_mode->name, - physical_pb_type->name); + VTR_LOG_ERROR( + "Unable to find a circuit model '%s' for interconnect '%s' under " + "physical mode '%s' of pb_type '%s'!\n", + pb_type_circuit_model_name.c_str(), interconnect_name.c_str(), + physical_mode->name, physical_pb_type->name); return false; } - - /* Double check the type of circuit model, it should be the same as required physical type */ - e_circuit_model_type required_circuit_model_type = pb_interconnect_require_circuit_model_type(vpr_device_annotation.interconnect_physical_type(pb_interc)); + + /* Double check the type of circuit model, it should be the same as required + * physical type */ + e_circuit_model_type required_circuit_model_type = + pb_interconnect_require_circuit_model_type( + vpr_device_annotation.interconnect_physical_type(pb_interc)); if (circuit_lib.model_type(circuit_model_id) != required_circuit_model_type) { - VTR_LOG_ERROR("Circuit model '%s' type '%s' does not match required type '%s' for interconnect '%s' under physical mode '%s' of pb_type '%s'!\n", - circuit_lib.model_name(circuit_model_id).c_str(), - CIRCUIT_MODEL_TYPE_STRING[circuit_lib.model_type(circuit_model_id)], - CIRCUIT_MODEL_TYPE_STRING[required_circuit_model_type], - pb_interc->name, - physical_mode->name, - physical_pb_type->name); + VTR_LOG_ERROR( + "Circuit model '%s' type '%s' does not match required type '%s' for " + "interconnect '%s' under physical mode '%s' of pb_type '%s'!\n", + circuit_lib.model_name(circuit_model_id).c_str(), + CIRCUIT_MODEL_TYPE_STRING[circuit_lib.model_type(circuit_model_id)], + CIRCUIT_MODEL_TYPE_STRING[required_circuit_model_type], pb_interc->name, + physical_mode->name, physical_pb_type->name); return false; } /* Now the circuit model is valid, update the vpr_device_annotation */ - vpr_device_annotation.add_interconnect_circuit_model(pb_interc, circuit_model_id); + vpr_device_annotation.add_interconnect_circuit_model(pb_interc, + circuit_model_id); VTR_LOGV(verbose_output, - "Bind pb_type '%s' physical mode '%s' interconnect '%s' to circuit model '%s'\n", - physical_pb_type->name, - physical_mode->name, - pb_interc->name, + "Bind pb_type '%s' physical mode '%s' interconnect '%s' to circuit " + "model '%s'\n", + physical_pb_type->name, physical_mode->name, pb_interc->name, circuit_lib.model_name(circuit_model_id).c_str()); return true; } /******************************************************************** - * This function will link - * - pb_type to circuit models in circuit library by following + * This function will link + * - pb_type to circuit models in circuit library by following * the explicit definition in OpenFPGA architecture XML * * Note: * - This function should be executed only AFTER the physical mode and * physical pb_type annotation is completed *******************************************************************/ -static -void link_vpr_pb_type_to_circuit_model_explicit_annotation(const DeviceContext& vpr_device_ctx, - const Arch& openfpga_arch, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { +static void link_vpr_pb_type_to_circuit_model_explicit_annotation( + const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { /* Walk through the pb_type annotation stored in the openfpga arch */ - for (const PbTypeAnnotation& pb_type_annotation : openfpga_arch.pb_type_annotations) { - /* Since our target is to annotate the circuti model for physical pb_type + for (const PbTypeAnnotation& pb_type_annotation : + openfpga_arch.pb_type_annotations) { + /* Since our target is to annotate the circuti model for physical pb_type * we can skip those annotation only for operating pb_type */ if (true == pb_type_annotation.is_operating_pb_type()) { @@ -656,48 +713,59 @@ void link_vpr_pb_type_to_circuit_model_explicit_annotation(const DeviceContext& VTR_ASSERT(true == pb_type_annotation.is_physical_pb_type()); - /* Collect the information about the full hierarchy of physical pb_type to be annotated */ + /* Collect the information about the full hierarchy of physical pb_type to + * be annotated */ std::vector target_phy_pb_type_names; std::vector target_phy_pb_mode_names; - target_phy_pb_type_names = pb_type_annotation.physical_parent_pb_type_names(); - target_phy_pb_type_names.push_back(pb_type_annotation.physical_pb_type_name()); + target_phy_pb_type_names = + pb_type_annotation.physical_parent_pb_type_names(); + target_phy_pb_type_names.push_back( + pb_type_annotation.physical_pb_type_name()); target_phy_pb_mode_names = pb_type_annotation.physical_parent_mode_names(); /* We must have at least one pb_type in the list */ VTR_ASSERT_SAFE(0 < target_phy_pb_type_names.size()); - /* Pb type information are located at the logic_block_types in the device context of VPR - * We iterate over the vectors and find the pb_type matches the parent_pb_type_name + /* Pb type information are located at the logic_block_types in the device + * context of VPR We iterate over the vectors and find the pb_type matches + * the parent_pb_type_name */ bool link_success = false; - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } - /* Check the name of the top-level pb_type, if it does not match, we can bypass */ + /* Check the name of the top-level pb_type, if it does not match, we can + * bypass */ if (target_phy_pb_type_names[0] != std::string(lb_type.pb_type->name)) { continue; } - /* Match the name in the top-level, we go further to search the operating as well as - * physical pb_types in the graph */ - t_pb_type* target_phy_pb_type = try_find_pb_type_with_given_path(lb_type.pb_type, target_phy_pb_type_names, - target_phy_pb_mode_names); + /* Match the name in the top-level, we go further to search the operating + * as well as physical pb_types in the graph */ + t_pb_type* target_phy_pb_type = try_find_pb_type_with_given_path( + lb_type.pb_type, target_phy_pb_type_names, target_phy_pb_mode_names); if (nullptr == target_phy_pb_type) { continue; } - /* Only try to bind pb_type to circuit model when it is defined by users */ - if (true == link_physical_pb_type_to_circuit_model(target_phy_pb_type, openfpga_arch.circuit_lib, - pb_type_annotation, vpr_device_annotation, - verbose_output)) { + /* Only try to bind pb_type to circuit model when it is defined by users + */ + if (true == link_physical_pb_type_to_circuit_model( + target_phy_pb_type, openfpga_arch.circuit_lib, + pb_type_annotation, vpr_device_annotation, + verbose_output)) { /* Give a message */ VTR_LOGV(verbose_output, "Bind physical pb_type '%s' to its circuit model '%s'\n", target_phy_pb_type->name, - openfpga_arch.circuit_lib.model_name(vpr_device_annotation.pb_type_circuit_model(target_phy_pb_type)).c_str()); + openfpga_arch.circuit_lib + .model_name(vpr_device_annotation.pb_type_circuit_model( + target_phy_pb_type)) + .c_str()); link_success = true; break; @@ -706,31 +774,31 @@ void link_vpr_pb_type_to_circuit_model_explicit_annotation(const DeviceContext& if (false == link_success) { /* Not found, error out! */ - VTR_LOG_ERROR("Unable to bind physical pb_type '%s' to circuit model '%s'!\n", - target_phy_pb_type_names.back().c_str(), - pb_type_annotation.circuit_model_name().c_str()); + VTR_LOG_ERROR( + "Unable to bind physical pb_type '%s' to circuit model '%s'!\n", + target_phy_pb_type_names.back().c_str(), + pb_type_annotation.circuit_model_name().c_str()); return; } - } + } } /******************************************************************** - * This function will link - * - interconnect of pb_type to circuit models in circuit library by following + * This function will link + * - interconnect of pb_type to circuit models in circuit library by following * the explicit definition in OpenFPGA architecture XML * * Note: * - This function should be executed only AFTER the physical mode and * physical pb_type annotation is completed *******************************************************************/ -static -void link_vpr_pb_interconnect_to_circuit_model_explicit_annotation(const DeviceContext& vpr_device_ctx, - const Arch& openfpga_arch, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { +static void link_vpr_pb_interconnect_to_circuit_model_explicit_annotation( + const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { /* Walk through the pb_type annotation stored in the openfpga arch */ - for (const PbTypeAnnotation& pb_type_annotation : openfpga_arch.pb_type_annotations) { - /* Since our target is to annotate the circuti model for physical pb_type + for (const PbTypeAnnotation& pb_type_annotation : + openfpga_arch.pb_type_annotations) { + /* Since our target is to annotate the circuti model for physical pb_type * we can skip those annotation only for operating pb_type */ if (true == pb_type_annotation.is_operating_pb_type()) { @@ -743,72 +811,84 @@ void link_vpr_pb_interconnect_to_circuit_model_explicit_annotation(const DeviceC VTR_ASSERT(true == pb_type_annotation.is_physical_pb_type()); - /* Collect the information about the full hierarchy of physical pb_type to be annotated */ + /* Collect the information about the full hierarchy of physical pb_type to + * be annotated */ std::vector target_phy_pb_type_names; std::vector target_phy_pb_mode_names; - target_phy_pb_type_names = pb_type_annotation.physical_parent_pb_type_names(); - target_phy_pb_type_names.push_back(pb_type_annotation.physical_pb_type_name()); + target_phy_pb_type_names = + pb_type_annotation.physical_parent_pb_type_names(); + target_phy_pb_type_names.push_back( + pb_type_annotation.physical_pb_type_name()); target_phy_pb_mode_names = pb_type_annotation.physical_parent_mode_names(); /* We must have at least one pb_type in the list */ VTR_ASSERT_SAFE(0 < target_phy_pb_type_names.size()); - /* Pb type information are located at the logic_block_types in the device context of VPR - * We iterate over the vectors and find the pb_type matches the parent_pb_type_name + /* Pb type information are located at the logic_block_types in the device + * context of VPR We iterate over the vectors and find the pb_type matches + * the parent_pb_type_name */ bool link_success = true; - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } - /* Check the name of the top-level pb_type, if it does not match, we can bypass */ + /* Check the name of the top-level pb_type, if it does not match, we can + * bypass */ if (target_phy_pb_type_names[0] != std::string(lb_type.pb_type->name)) { continue; } - /* Match the name in the top-level, we go further to search the operating as well as - * physical pb_types in the graph */ - t_pb_type* target_phy_pb_type = try_find_pb_type_with_given_path(lb_type.pb_type, target_phy_pb_type_names, - target_phy_pb_mode_names); + /* Match the name in the top-level, we go further to search the operating + * as well as physical pb_types in the graph */ + t_pb_type* target_phy_pb_type = try_find_pb_type_with_given_path( + lb_type.pb_type, target_phy_pb_type_names, target_phy_pb_mode_names); if (nullptr == target_phy_pb_type) { continue; } - /* Only try to bind interconnect to circuit model when it is defined by users */ - for (const std::string& interc_name : pb_type_annotation.interconnect_names()) { - if (false == link_physical_pb_interconnect_to_circuit_model(target_phy_pb_type, interc_name, openfpga_arch.circuit_lib, - pb_type_annotation, vpr_device_annotation, - verbose_output)) { - VTR_LOG_ERROR("Unable to bind pb_type '%s' interconnect '%s' to circuit model '%s'!\n", - target_phy_pb_type_names.back().c_str(), - interc_name.c_str(), - pb_type_annotation.circuit_model_name().c_str()); - link_success = false; - } + /* Only try to bind interconnect to circuit model when it is defined by + * users */ + for (const std::string& interc_name : + pb_type_annotation.interconnect_names()) { + if (false == link_physical_pb_interconnect_to_circuit_model( + target_phy_pb_type, interc_name, + openfpga_arch.circuit_lib, pb_type_annotation, + vpr_device_annotation, verbose_output)) { + VTR_LOG_ERROR( + "Unable to bind pb_type '%s' interconnect '%s' to circuit model " + "'%s'!\n", + target_phy_pb_type_names.back().c_str(), interc_name.c_str(), + pb_type_annotation.circuit_model_name().c_str()); + link_success = false; + } } } if (false == link_success) { /* Not found, error out! */ - VTR_LOG_ERROR("Unable to bind interconnects of physical pb_type '%s' to circuit model '%s'!\n", - target_phy_pb_type_names.back().c_str(), - pb_type_annotation.circuit_model_name().c_str()); + VTR_LOG_ERROR( + "Unable to bind interconnects of physical pb_type '%s' to circuit " + "model '%s'!\n", + target_phy_pb_type_names.back().c_str(), + pb_type_annotation.circuit_model_name().c_str()); return; } - } + } } /******************************************************************** * This function will recursively visit all the pb_type from the top - * pb_type in the graph and infer the circuit model for physical mode + * pb_type in the graph and infer the circuit model for physical mode * of pb_types in VPR pb_type graph without OpenFPGA architecture XML * * Because only the interconnect in physical modes need circuit model * annotation, we will skip all the operating modes here * - * Note: + * Note: * - This function will automatically infer the type of circuit model * that is required and find the default circuit model in the type * - Interconnect type to Circuit mode type assumption: @@ -817,76 +897,79 @@ void link_vpr_pb_interconnect_to_circuit_model_explicit_annotation(const DeviceC * - COMPLETE_INTERC (single input) -> CIRCUIT_MODEL_WIRE * - COMPLETE_INTERC (multiple input pins) -> CIRCUIT_MODEL_MUX *******************************************************************/ -static -void rec_infer_vpr_pb_interconnect_circuit_model_annotation(t_pb_type* cur_pb_type, - const CircuitLibrary& circuit_lib, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { +static void rec_infer_vpr_pb_interconnect_circuit_model_annotation( + t_pb_type* cur_pb_type, const CircuitLibrary& circuit_lib, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { /* We do not check any primitive pb_type */ if (true == is_primitive_pb_type(cur_pb_type)) { return; } - /* Get the physical mode from annotation */ + /* Get the physical mode from annotation */ t_mode* physical_mode = vpr_device_annotation.physical_mode(cur_pb_type); VTR_ASSERT(nullptr != physical_mode); - /* Annotate the circuit model for each interconnect under this physical mode */ + /* Annotate the circuit model for each interconnect under this physical mode + */ for (t_interconnect* pb_interc : pb_mode_interconnects(physical_mode)) { /* If the interconnect has been annotated, we skip it */ - if (CircuitModelId::INVALID() != vpr_device_annotation.interconnect_circuit_model(pb_interc)) { + if (CircuitModelId::INVALID() != + vpr_device_annotation.interconnect_circuit_model(pb_interc)) { continue; } /* Infer the circuit model type for a given interconnect */ - e_circuit_model_type circuit_model_type = pb_interconnect_require_circuit_model_type(vpr_device_annotation.interconnect_physical_type(pb_interc)); + e_circuit_model_type circuit_model_type = + pb_interconnect_require_circuit_model_type( + vpr_device_annotation.interconnect_physical_type(pb_interc)); /* Try to find a default circuit model from the circuit library */ - CircuitModelId default_circuit_model = circuit_lib.default_model(circuit_model_type); + CircuitModelId default_circuit_model = + circuit_lib.default_model(circuit_model_type); /* Update the annotation if the model id is valid */ if (CircuitModelId::INVALID() == default_circuit_model) { - VTR_LOG_ERROR("Unable to infer a circuit model for interconnect '%s' under physical mode '%s' of pb_type '%s'!\n", - pb_interc->name, - physical_mode->name, - cur_pb_type->name); + VTR_LOG_ERROR( + "Unable to infer a circuit model for interconnect '%s' under physical " + "mode '%s' of pb_type '%s'!\n", + pb_interc->name, physical_mode->name, cur_pb_type->name); } - vpr_device_annotation.add_interconnect_circuit_model(pb_interc, default_circuit_model); + vpr_device_annotation.add_interconnect_circuit_model(pb_interc, + default_circuit_model); VTR_LOGV(verbose_output, - "Implicitly infer a circuit model '%s' for interconnect '%s' under physical mode '%s' of pb_type '%s'\n", + "Implicitly infer a circuit model '%s' for interconnect '%s' " + "under physical mode '%s' of pb_type '%s'\n", circuit_lib.model_name(default_circuit_model).c_str(), - pb_interc->name, - physical_mode->name, - cur_pb_type->name); + pb_interc->name, physical_mode->name, cur_pb_type->name); } /* Traverse the pb_type children under the physical mode */ - for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { - rec_infer_vpr_pb_interconnect_circuit_model_annotation(&(physical_mode->pb_type_children[ichild]), - circuit_lib, vpr_device_annotation, - verbose_output); + for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { + rec_infer_vpr_pb_interconnect_circuit_model_annotation( + &(physical_mode->pb_type_children[ichild]), circuit_lib, + vpr_device_annotation, verbose_output); } } /******************************************************************** * This function will infer the circuit model for each interconnect - * under a physical mode of a pb_type in VPR pb_type graph without + * under a physical mode of a pb_type in VPR pb_type graph without * OpenFPGA architecture XML * - * Note: + * Note: * This function must be executed AFTER the function * build_vpr_physical_pb_mode_explicit_annotation() * build_vpr_physical_pb_mode_implicit_annotation() *******************************************************************/ -static -void link_vpr_pb_interconnect_to_circuit_model_implicit_annotation(const DeviceContext& vpr_device_ctx, - const CircuitLibrary& circuit_lib, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { +static void link_vpr_pb_interconnect_to_circuit_model_implicit_annotation( + const DeviceContext& vpr_device_ctx, const CircuitLibrary& circuit_lib, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } - rec_infer_vpr_pb_interconnect_circuit_model_annotation(lb_type.pb_type, circuit_lib, vpr_device_annotation, verbose_output); + rec_infer_vpr_pb_interconnect_circuit_model_annotation( + lb_type.pb_type, circuit_lib, vpr_device_annotation, verbose_output); } } @@ -894,40 +977,41 @@ void link_vpr_pb_interconnect_to_circuit_model_implicit_annotation(const DeviceC * This function will bind mode selection bits to a primitive pb_type * in the vpr_device_annotation *******************************************************************/ -static -bool link_primitive_pb_type_to_mode_bits(t_pb_type* primitive_pb_type, - const PbTypeAnnotation& pb_type_annotation, - VprDeviceAnnotation& vpr_device_annotation) { +static bool link_primitive_pb_type_to_mode_bits( + t_pb_type* primitive_pb_type, const PbTypeAnnotation& pb_type_annotation, + VprDeviceAnnotation& vpr_device_annotation) { /* Error out if this is not a primitive pb_type */ if (false == is_primitive_pb_type(primitive_pb_type)) { - VTR_LOG_ERROR("Mode selection is only applicable to primitive pb_type while pb_type '%s' is not primitve !\n", - primitive_pb_type->name); + VTR_LOG_ERROR( + "Mode selection is only applicable to primitive pb_type while pb_type " + "'%s' is not primitve !\n", + primitive_pb_type->name); return false; } /* Update the annotation */ - vpr_device_annotation.add_pb_type_mode_bits(primitive_pb_type, pb_type_annotation.mode_bits()); + vpr_device_annotation.add_pb_type_mode_bits(primitive_pb_type, + pb_type_annotation.mode_bits()); return true; } /******************************************************************** - * This function will link - * - pb_type to mode bits by following + * This function will link + * - pb_type to mode bits by following * the explicit definition in OpenFPGA architecture XML * * Note: - * - This function should be executed only AFTER + * - This function should be executed only AFTER * the physical mode and physical pb_type annotation is completed * the physical pb_type circuit model annotation is completed *******************************************************************/ -static -void link_vpr_pb_type_to_mode_bits_explicit_annotation(const DeviceContext& vpr_device_ctx, - const Arch& openfpga_arch, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { +static void link_vpr_pb_type_to_mode_bits_explicit_annotation( + const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { /* Walk through the pb_type annotation stored in the openfpga arch */ - for (const PbTypeAnnotation& pb_type_annotation : openfpga_arch.pb_type_annotations) { + for (const PbTypeAnnotation& pb_type_annotation : + openfpga_arch.pb_type_annotations) { if (true == pb_type_annotation.mode_bits().empty()) { continue; } @@ -938,55 +1022,63 @@ void link_vpr_pb_type_to_mode_bits_explicit_annotation(const DeviceContext& vpr_ mode_bits_str += std::to_string(bit); } - /* Collect the information about the full hierarchy of physical pb_type to be annotated */ + /* Collect the information about the full hierarchy of physical pb_type to + * be annotated */ std::vector target_pb_type_names; std::vector target_pb_mode_names; if (true == pb_type_annotation.is_operating_pb_type()) { - target_pb_type_names = pb_type_annotation.operating_parent_pb_type_names(); - target_pb_type_names.push_back(pb_type_annotation.operating_pb_type_name()); + target_pb_type_names = + pb_type_annotation.operating_parent_pb_type_names(); + target_pb_type_names.push_back( + pb_type_annotation.operating_pb_type_name()); target_pb_mode_names = pb_type_annotation.operating_parent_mode_names(); } if (true == pb_type_annotation.is_physical_pb_type()) { target_pb_type_names = pb_type_annotation.physical_parent_pb_type_names(); - target_pb_type_names.push_back(pb_type_annotation.physical_pb_type_name()); + target_pb_type_names.push_back( + pb_type_annotation.physical_pb_type_name()); target_pb_mode_names = pb_type_annotation.physical_parent_mode_names(); } /* We must have at least one pb_type in the list */ VTR_ASSERT_SAFE(0 < target_pb_type_names.size()); - /* Pb type information are located at the logic_block_types in the device context of VPR - * We iterate over the vectors and find the pb_type matches the parent_pb_type_name + /* Pb type information are located at the logic_block_types in the device + * context of VPR We iterate over the vectors and find the pb_type matches + * the parent_pb_type_name */ bool link_success = false; - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } - /* Check the name of the top-level pb_type, if it does not match, we can bypass */ + /* Check the name of the top-level pb_type, if it does not match, we can + * bypass */ if (target_pb_type_names[0] != std::string(lb_type.pb_type->name)) { continue; } - /* Match the name in the top-level, we go further to search the operating as well as - * physical pb_types in the graph */ - t_pb_type* target_pb_type = try_find_pb_type_with_given_path(lb_type.pb_type, target_pb_type_names, - target_pb_mode_names); + /* Match the name in the top-level, we go further to search the operating + * as well as physical pb_types in the graph */ + t_pb_type* target_pb_type = try_find_pb_type_with_given_path( + lb_type.pb_type, target_pb_type_names, target_pb_mode_names); if (nullptr == target_pb_type) { continue; } - /* Only try to bind pb_type to circuit model when it is defined by users */ + /* Only try to bind pb_type to circuit model when it is defined by users + */ if (true == link_primitive_pb_type_to_mode_bits(target_pb_type, - pb_type_annotation, vpr_device_annotation)) { + pb_type_annotation, + vpr_device_annotation)) { /* Give a message */ VTR_LOGV(verbose_output, "Bind physical pb_type '%s' to mode selection bits '%s'\n", - target_pb_type->name, - mode_bits_str.c_str()); + target_pb_type->name, mode_bits_str.c_str()); link_success = true; break; @@ -995,12 +1087,12 @@ void link_vpr_pb_type_to_mode_bits_explicit_annotation(const DeviceContext& vpr_ if (false == link_success) { /* Not found, error out! */ - VTR_LOG_ERROR("Unable to bind pb_type '%s' to mode_selection bits '%s'!\n", - target_pb_type_names.back().c_str(), - mode_bits_str.c_str()); + VTR_LOG_ERROR( + "Unable to bind pb_type '%s' to mode_selection bits '%s'!\n", + target_pb_type_names.back().c_str(), mode_bits_str.c_str()); return; } - } + } } /******************************************************************** @@ -1008,95 +1100,92 @@ void link_vpr_pb_type_to_mode_bits_explicit_annotation(const DeviceContext& vpr_ * - physical pb_type * - circuit models for pb_type, pb interconnect *******************************************************************/ -void annotate_pb_types(const DeviceContext& vpr_device_ctx, +void annotate_pb_types(const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { - /* Annotate physical mode to pb_type in the VPR pb_type graph */ VTR_LOG("\n"); VTR_LOG("Building annotation for physical modes in pb_type..."); VTR_LOGV(verbose_output, "\n"); - build_vpr_physical_pb_mode_explicit_annotation(vpr_device_ctx, openfpga_arch, - vpr_device_annotation, - verbose_output); + build_vpr_physical_pb_mode_explicit_annotation( + vpr_device_ctx, openfpga_arch, vpr_device_annotation, verbose_output); - build_vpr_physical_pb_mode_implicit_annotation(vpr_device_ctx, - vpr_device_annotation, - verbose_output); + build_vpr_physical_pb_mode_implicit_annotation( + vpr_device_ctx, vpr_device_annotation, verbose_output); VTR_LOG("Done\n"); - check_vpr_physical_pb_mode_annotation(vpr_device_ctx, - const_cast(vpr_device_annotation)); + check_vpr_physical_pb_mode_annotation( + vpr_device_ctx, + const_cast(vpr_device_annotation)); /* Annotate the physical type for each interconnect under physical modes - * Must run AFTER physical mode annotation is done and + * Must run AFTER physical mode annotation is done and * BEFORE inferring the circuit model for interconnect */ VTR_LOG("\n"); - VTR_LOG("Building annotation about physical types for pb_type interconnection..."); + VTR_LOG( + "Building annotation about physical types for pb_type interconnection..."); VTR_LOGV(verbose_output, "\n"); - annotate_pb_graph_interconnect_physical_type(vpr_device_ctx, - vpr_device_annotation, - verbose_output); + annotate_pb_graph_interconnect_physical_type( + vpr_device_ctx, vpr_device_annotation, verbose_output); VTR_LOG("Done\n"); - /* Annotate physical pb_types to operating pb_type in the VPR pb_type graph + /* Annotate physical pb_types to operating pb_type in the VPR pb_type graph * This function will also annotate - * - pb_type_index_factor + * - pb_type_index_factor * - pb_type_index_offset * - physical_pin_rotate_offset */ VTR_LOG("\n"); VTR_LOG("Building annotation between operating and physical pb_types..."); VTR_LOGV(verbose_output, "\n"); - build_vpr_physical_pb_type_explicit_annotation(vpr_device_ctx, openfpga_arch, - vpr_device_annotation, - verbose_output); + build_vpr_physical_pb_type_explicit_annotation( + vpr_device_ctx, openfpga_arch, vpr_device_annotation, verbose_output); - build_vpr_physical_pb_type_implicit_annotation(vpr_device_ctx, - vpr_device_annotation, - verbose_output); + build_vpr_physical_pb_type_implicit_annotation( + vpr_device_ctx, vpr_device_annotation, verbose_output); VTR_LOG("Done\n"); - check_vpr_physical_pb_type_annotation(vpr_device_ctx, - const_cast(vpr_device_annotation)); + check_vpr_physical_pb_type_annotation( + vpr_device_ctx, + const_cast(vpr_device_annotation)); - /* Link + /* Link * - physical pb_type to circuit model - * - interconnect of physical pb_type to circuit model + * - interconnect of physical pb_type to circuit model */ VTR_LOG("\n"); - VTR_LOG("Building annotation between physical pb_types and circuit models..."); + VTR_LOG( + "Building annotation between physical pb_types and circuit models..."); VTR_LOGV(verbose_output, "\n"); - link_vpr_pb_type_to_circuit_model_explicit_annotation(vpr_device_ctx, openfpga_arch, - vpr_device_annotation, - verbose_output); + link_vpr_pb_type_to_circuit_model_explicit_annotation( + vpr_device_ctx, openfpga_arch, vpr_device_annotation, verbose_output); - link_vpr_pb_interconnect_to_circuit_model_explicit_annotation(vpr_device_ctx, openfpga_arch, - vpr_device_annotation, - verbose_output); + link_vpr_pb_interconnect_to_circuit_model_explicit_annotation( + vpr_device_ctx, openfpga_arch, vpr_device_annotation, verbose_output); - link_vpr_pb_interconnect_to_circuit_model_implicit_annotation(vpr_device_ctx, openfpga_arch.circuit_lib, - vpr_device_annotation, - verbose_output); + link_vpr_pb_interconnect_to_circuit_model_implicit_annotation( + vpr_device_ctx, openfpga_arch.circuit_lib, vpr_device_annotation, + verbose_output); VTR_LOG("Done\n"); - check_vpr_pb_type_circuit_model_annotation(vpr_device_ctx, openfpga_arch.circuit_lib, - const_cast(vpr_device_annotation)); + check_vpr_pb_type_circuit_model_annotation( + vpr_device_ctx, openfpga_arch.circuit_lib, + const_cast(vpr_device_annotation)); /* Link physical pb_type to mode_bits */ VTR_LOG("\n"); - VTR_LOG("Building annotation between physical pb_types and mode selection bits..."); + VTR_LOG( + "Building annotation between physical pb_types and mode selection bits..."); VTR_LOGV(verbose_output, "\n"); - link_vpr_pb_type_to_mode_bits_explicit_annotation(vpr_device_ctx, openfpga_arch, - vpr_device_annotation, - verbose_output); + link_vpr_pb_type_to_mode_bits_explicit_annotation( + vpr_device_ctx, openfpga_arch, vpr_device_annotation, verbose_output); VTR_LOG("Done\n"); - check_vpr_pb_type_mode_bits_annotation(vpr_device_ctx, openfpga_arch.circuit_lib, - const_cast(vpr_device_annotation)); - -} + check_vpr_pb_type_mode_bits_annotation( + vpr_device_ctx, openfpga_arch.circuit_lib, + const_cast(vpr_device_annotation)); +} } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/annotate_pb_types.h b/openfpga/src/annotation/annotate_pb_types.h index d2c1b4cf5..a91ed3367 100644 --- a/openfpga/src/annotation/annotate_pb_types.h +++ b/openfpga/src/annotation/annotate_pb_types.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" #include "openfpga_context.h" +#include "vpr_context.h" #include "vpr_device_annotation.h" /******************************************************************** @@ -15,7 +15,7 @@ /* begin namespace openfpga */ namespace openfpga { -void annotate_pb_types(const DeviceContext& vpr_device_ctx, +void annotate_pb_types(const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output); diff --git a/openfpga/src/annotation/annotate_physical_tiles.cpp b/openfpga/src/annotation/annotate_physical_tiles.cpp index 27db35461..c61148406 100644 --- a/openfpga/src/annotation/annotate_physical_tiles.cpp +++ b/openfpga/src/annotation/annotate_physical_tiles.cpp @@ -3,48 +3,49 @@ * in particular to annotate the physical mode and physical pb_type *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" +#include "annotate_physical_tiles.h" + #include "vtr_assert.h" #include "vtr_log.h" - -#include "annotate_physical_tiles.h" +#include "vtr_time.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * Build the fast look-up for each physical tile between + * Build the fast look-up for each physical tile between * pin index and the physical port information, i.e., port name and port index *******************************************************************/ -void build_physical_tile_pin2port_info(const DeviceContext& vpr_device_ctx, - VprDeviceAnnotation& vpr_device_annotation) { +void build_physical_tile_pin2port_info( + const DeviceContext& vpr_device_ctx, + VprDeviceAnnotation& vpr_device_annotation) { + vtr::ScopedStartFinishTimer timer( + "Build fast look-up for physical tile pins"); - vtr::ScopedStartFinishTimer timer("Build fast look-up for physical tile pins"); - - for (const t_physical_tile_type& physical_tile : vpr_device_ctx.physical_tile_types) { + for (const t_physical_tile_type& physical_tile : + vpr_device_ctx.physical_tile_types) { int curr_pin_index = 0; /* Walk through each subtile, consider their capacity and num of pins */ - for (const t_sub_tile& sub_tile : physical_tile.sub_tiles) { - /* Walk through capacity */ - for (int subtile_index = sub_tile.capacity.low; subtile_index <= sub_tile.capacity.high; subtile_index++) { - vpr_device_annotation.add_physical_tile_z_to_start_pin_index(&physical_tile, - subtile_index, - curr_pin_index); - /* For each sub tile, the starting pin index is (num_pins_per_subtile * index) + abs_index */ + for (const t_sub_tile& sub_tile : physical_tile.sub_tiles) { + /* Walk through capacity */ + for (int subtile_index = sub_tile.capacity.low; + subtile_index <= sub_tile.capacity.high; subtile_index++) { + vpr_device_annotation.add_physical_tile_z_to_start_pin_index( + &physical_tile, subtile_index, curr_pin_index); + /* For each sub tile, the starting pin index is (num_pins_per_subtile * + * index) + abs_index */ for (const t_physical_tile_port& tile_port : sub_tile.ports) { for (int pin_index = 0; pin_index < tile_port.num_pins; ++pin_index) { - int absolute_pin_index = curr_pin_index + tile_port.absolute_first_pin_index + pin_index; + int absolute_pin_index = + curr_pin_index + tile_port.absolute_first_pin_index + pin_index; BasicPort tile_port_info(tile_port.name, pin_index, pin_index); - vpr_device_annotation.add_physical_tile_pin2port_info_pair(&physical_tile, - absolute_pin_index, - tile_port_info); - vpr_device_annotation.add_physical_tile_pin_subtile_index(&physical_tile, - absolute_pin_index, - subtile_index); - vpr_device_annotation.add_physical_tile_z_to_subtile_index(&physical_tile, - subtile_index, - &sub_tile - &(physical_tile.sub_tiles[0]) - ); + vpr_device_annotation.add_physical_tile_pin2port_info_pair( + &physical_tile, absolute_pin_index, tile_port_info); + vpr_device_annotation.add_physical_tile_pin_subtile_index( + &physical_tile, absolute_pin_index, subtile_index); + vpr_device_annotation.add_physical_tile_z_to_subtile_index( + &physical_tile, subtile_index, + &sub_tile - &(physical_tile.sub_tiles[0])); } } /* Count the number of pins for each sub tile */ diff --git a/openfpga/src/annotation/annotate_physical_tiles.h b/openfpga/src/annotation/annotate_physical_tiles.h index 726461359..01c340ce1 100644 --- a/openfpga/src/annotation/annotate_physical_tiles.h +++ b/openfpga/src/annotation/annotate_physical_tiles.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" #include "openfpga_context.h" +#include "vpr_context.h" #include "vpr_device_annotation.h" /******************************************************************** @@ -15,8 +15,9 @@ /* begin namespace openfpga */ namespace openfpga { -void build_physical_tile_pin2port_info(const DeviceContext& vpr_device_ctx, - VprDeviceAnnotation& vpr_device_annotation); +void build_physical_tile_pin2port_info( + const DeviceContext& vpr_device_ctx, + VprDeviceAnnotation& vpr_device_annotation); } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/annotate_placement.cpp b/openfpga/src/annotation/annotate_placement.cpp index 3f7179aaa..bf7d0b895 100644 --- a/openfpga/src/annotation/annotate_placement.cpp +++ b/openfpga/src/annotation/annotate_placement.cpp @@ -3,31 +3,33 @@ * and pb_graph_pins from VPR to OpenFPGA *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_assert.h" -#include "vtr_log.h" -#include "vtr_geometry.h" - #include "annotate_placement.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 + * 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 *******************************************************************/ -void annotate_mapped_blocks(const DeviceContext& device_ctx, - const ClusteringContext& cluster_ctx, - const PlacementContext& place_ctx, +void annotate_mapped_blocks(const DeviceContext& device_ctx, + const ClusteringContext& cluster_ctx, + const PlacementContext& place_ctx, VprPlacementAnnotation& place_annotation) { VTR_LOG("Building annotation for mapped blocks on grid locations..."); place_annotation.init_mapped_blocks(device_ctx.grid); for (const ClusterBlockId& blk_id : cluster_ctx.clb_nlist.blocks()) { - vtr::Point grid_coord(place_ctx.block_locs[blk_id].loc.x, place_ctx.block_locs[blk_id].loc.y); - place_annotation.add_mapped_block(grid_coord, place_ctx.block_locs[blk_id].loc.sub_tile, blk_id); - } + vtr::Point grid_coord(place_ctx.block_locs[blk_id].loc.x, + place_ctx.block_locs[blk_id].loc.y); + place_annotation.add_mapped_block( + grid_coord, place_ctx.block_locs[blk_id].loc.sub_tile, blk_id); + } VTR_LOG("Done\n"); } diff --git a/openfpga/src/annotation/annotate_placement.h b/openfpga/src/annotation/annotate_placement.h index fd47bb56d..a1095fb5c 100644 --- a/openfpga/src/annotation/annotate_placement.h +++ b/openfpga/src/annotation/annotate_placement.h @@ -14,9 +14,9 @@ /* begin namespace openfpga */ namespace openfpga { -void annotate_mapped_blocks(const DeviceContext& device_ctx, - const ClusteringContext& cluster_ctx, - const PlacementContext& place_ctx, +void annotate_mapped_blocks(const DeviceContext& device_ctx, + const ClusteringContext& cluster_ctx, + const PlacementContext& place_ctx, VprPlacementAnnotation& place_annotation); } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/annotate_rr_graph.cpp b/openfpga/src/annotation/annotate_rr_graph.cpp index 341fc1271..d88f2d692 100644 --- a/openfpga/src/annotation/annotate_rr_graph.cpp +++ b/openfpga/src/annotation/annotate_rr_graph.cpp @@ -3,52 +3,49 @@ * information, in particular the routing resource graph *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" #include "vtr_assert.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgautil library */ #include "openfpga_side_manager.h" /* Headers from vpr library */ +#include "annotate_rr_graph.h" +#include "openfpga_rr_graph_utils.h" #include "physical_types.h" #include "rr_graph_view_util.h" -#include "openfpga_rr_graph_utils.h" - -#include "annotate_rr_graph.h" /* begin namespace openfpga */ namespace openfpga { /* Build a RRChan Object with the given channel type and coorindators */ -static -RRChan build_one_rr_chan(const DeviceContext& vpr_device_ctx, - const t_rr_type& chan_type, - vtr::Point& chan_coord) { +static RRChan build_one_rr_chan(const DeviceContext& vpr_device_ctx, + const t_rr_type& chan_type, + vtr::Point& chan_coord) { std::vector chan_rr_nodes; /* Create a rr_chan object and check if it is unique in the graph */ RRChan rr_chan; /* Fill the information */ - rr_chan.set_type(chan_type); + rr_chan.set_type(chan_type); /* Collect rr_nodes for this channel */ - chan_rr_nodes = find_rr_graph_chan_nodes(vpr_device_ctx.rr_graph, - chan_coord.x(), chan_coord.y(), - chan_type); - /* Fill the rr_chan */ + chan_rr_nodes = find_rr_graph_chan_nodes( + vpr_device_ctx.rr_graph, chan_coord.x(), chan_coord.y(), chan_type); + /* Fill the rr_chan */ for (const RRNodeId& chan_rr_node : chan_rr_nodes) { - rr_chan.add_node(vpr_device_ctx.rr_graph, chan_rr_node, + rr_chan.add_node(vpr_device_ctx.rr_graph, chan_rr_node, vpr_device_ctx.rr_graph.node_segment(chan_rr_node)); } return rr_chan; } -/* Build a General Switch Block (GSB) +/* Build a General Switch Block (GSB) * which includes: * [I] A Switch Box subckt consists of following ports: - * 1. Channel Y [x][y] inputs + * 1. Channel Y [x][y] inputs * 2. Channel X [x+1][y] inputs * 3. Channel Y [x][y-1] outputs * 4. Channel X [x][y] outputs @@ -68,7 +65,7 @@ RRChan build_one_rr_chan(const DeviceContext& vpr_device_ctx, * | | | | * -------------- -------------- * ---------- - * ChanX & CBX | Switch | ChanX + * ChanX & CBX | Switch | ChanX * [x][y] | Box | [x+1][y] * | [x][y] | * ---------- @@ -78,33 +75,33 @@ RRChan build_one_rr_chan(const DeviceContext& vpr_device_ctx, * | [x][y] | [x][y] | [x+1][y] | * | | | | * -------------- -------------- - * For channels chanY with INC_DIRECTION on the top side, they should be marked as outputs - * For channels chanY with DEC_DIRECTION on the top side, they should be marked as inputs - * For channels chanY with INC_DIRECTION on the bottom side, they should be marked as inputs - * For channels chanY with DEC_DIRECTION on the bottom side, they should be marked as outputs - * For channels chanX with INC_DIRECTION on the left side, they should be marked as inputs - * For channels chanX with DEC_DIRECTION on the left side, they should be marked as outputs - * For channels chanX with INC_DIRECTION on the right side, they should be marked as outputs - * For channels chanX with DEC_DIRECTION on the right side, they should be marked as inputs + * For channels chanY with INC_DIRECTION on the top side, they should be marked + * as outputs For channels chanY with DEC_DIRECTION on the top side, they should + * be marked as inputs For channels chanY with INC_DIRECTION on the bottom side, + * they should be marked as inputs For channels chanY with DEC_DIRECTION on the + * bottom side, they should be marked as outputs For channels chanX with + * INC_DIRECTION on the left side, they should be marked as inputs For channels + * chanX with DEC_DIRECTION on the left side, they should be marked as outputs + * For channels chanX with INC_DIRECTION on the right side, they should be + * marked as outputs For channels chanX with DEC_DIRECTION on the right side, + * they should be marked as inputs * * [II] A X-direction Connection Block [x][y] - * The connection block shares the same routing channel[x][y] with the Switch Block - * We just need to fill the ipin nodes at TOP and BOTTOM sides - * as well as properly fill the ipin_grid_side information - * [III] A Y-direction Connection Block [x][y+1] - * The connection block shares the same routing channel[x][y+1] with the Switch Block - * We just need to fill the ipin nodes at LEFT and RIGHT sides - * as well as properly fill the ipin_grid_side information + * The connection block shares the same routing channel[x][y] with the Switch + * Block We just need to fill the ipin nodes at TOP and BOTTOM sides as well as + * properly fill the ipin_grid_side information [III] A Y-direction Connection + * Block [x][y+1] The connection block shares the same routing channel[x][y+1] + * with the Switch Block We just need to fill the ipin nodes at LEFT and RIGHT + * sides as well as properly fill the ipin_grid_side information */ -static -RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, - const vtr::Point& gsb_range, - const vtr::Point& gsb_coord) { +static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, + const vtr::Point& gsb_range, + const vtr::Point& gsb_coord) { /* Create an object to return */ RRGSB rr_gsb; - VTR_ASSERT(gsb_coord.x() <= gsb_range.x()); - VTR_ASSERT(gsb_coord.y() <= gsb_range.y()); + VTR_ASSERT(gsb_coord.x() <= gsb_range.x()); + VTR_ASSERT(gsb_coord.y() <= gsb_range.y()); /* Coordinator initialization */ rr_gsb.set_coordinate(gsb_coord.x(), gsb_coord.y()); @@ -117,124 +114,142 @@ RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { /* Local variables inside this for loop */ SideManager side_manager(side); - vtr::Point coordinate = rr_gsb.get_side_block_coordinate(side_manager.get_side()); + vtr::Point coordinate = + rr_gsb.get_side_block_coordinate(side_manager.get_side()); RRChan rr_chan; std::vector> temp_opin_rr_nodes(2); enum e_side opin_grid_side[2] = {NUM_SIDES, NUM_SIDES}; - enum PORTS chan_dir_to_port_dir_mapping[2] = {OUT_PORT, IN_PORT}; /* 0: INC_DIRECTION => ?; 1: DEC_DIRECTION => ? */ + enum PORTS chan_dir_to_port_dir_mapping[2] = { + OUT_PORT, IN_PORT}; /* 0: INC_DIRECTION => ?; 1: DEC_DIRECTION => ? */ switch (side) { - case TOP: /* TOP = 0 */ - /* For the border, we should take special care */ - if (gsb_coord.y() == gsb_range.y()) { - rr_gsb.clear_one_side(side_manager.get_side()); + case TOP: /* TOP = 0 */ + /* For the border, we should take special care */ + if (gsb_coord.y() == gsb_range.y()) { + rr_gsb.clear_one_side(side_manager.get_side()); + break; + } + /* Routing channels*/ + /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_rr_chan(vpr_device_ctx, CHANY, coordinate); + chan_dir_to_port_dir_mapping[0] = + OUT_PORT; /* INC_DIRECTION => OUT_PORT */ + chan_dir_to_port_dir_mapping[1] = + IN_PORT; /* DEC_DIRECTION => IN_PORT */ + + /* Build the Switch block: opin and opin_grid_side */ + /* Assign grid side of OPIN */ + /* Grid[x][y+1] RIGHT side outputs pins */ + opin_grid_side[0] = RIGHT; + /* Grid[x+1][y+1] left side outputs pins */ + opin_grid_side[1] = LEFT; + /* Include Grid[x][y+1] RIGHT side outputs pins */ + temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes( + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x(), + gsb_coord.y() + 1, OPIN, opin_grid_side[0]); + /* Include Grid[x+1][y+1] Left side output pins */ + temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes( + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x() + 1, + gsb_coord.y() + 1, OPIN, opin_grid_side[1]); + break; - } - /* Routing channels*/ - /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ - /* Create a rr_chan object and check if it is unique in the graph */ - rr_chan = build_one_rr_chan(vpr_device_ctx, CHANY, coordinate); - chan_dir_to_port_dir_mapping[0] = OUT_PORT; /* INC_DIRECTION => OUT_PORT */ - chan_dir_to_port_dir_mapping[1] = IN_PORT; /* DEC_DIRECTION => IN_PORT */ + case RIGHT: /* RIGHT = 1 */ + /* For the border, we should take special care */ + if (gsb_coord.x() == gsb_range.x()) { + rr_gsb.clear_one_side(side_manager.get_side()); + break; + } + /* Routing channels*/ + /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ + /* Collect rr_nodes for Tracks for top: chany[x][y+1] */ + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_rr_chan(vpr_device_ctx, CHANX, coordinate); + chan_dir_to_port_dir_mapping[0] = + OUT_PORT; /* INC_DIRECTION => OUT_PORT */ + chan_dir_to_port_dir_mapping[1] = + IN_PORT; /* DEC_DIRECTION => IN_PORT */ - /* Build the Switch block: opin and opin_grid_side */ - /* Assign grid side of OPIN */ - /* Grid[x][y+1] RIGHT side outputs pins */ - opin_grid_side[0] = RIGHT; - /* Grid[x+1][y+1] left side outputs pins */ - opin_grid_side[1] = LEFT; - /* Include Grid[x][y+1] RIGHT side outputs pins */ - temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid, - gsb_coord.x(), gsb_coord.y() + 1, OPIN, opin_grid_side[0]); - /* Include Grid[x+1][y+1] Left side output pins */ - temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid, - gsb_coord.x() + 1, gsb_coord.y() + 1, OPIN, opin_grid_side[1]); + /* Build the Switch block: opin and opin_grid_side */ + /* Assign grid side of OPIN */ + /* Grid[x+1][y+1] BOTTOM side outputs pins */ + opin_grid_side[0] = BOTTOM; + /* Grid[x+1][y] TOP side outputs pins */ + opin_grid_side[1] = TOP; - break; - case RIGHT: /* RIGHT = 1 */ - /* For the border, we should take special care */ - if (gsb_coord.x() == gsb_range.x()) { - rr_gsb.clear_one_side(side_manager.get_side()); + /* include Grid[x+1][y+1] Bottom side output pins */ + temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes( + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x() + 1, + gsb_coord.y() + 1, OPIN, opin_grid_side[0]); + /* include Grid[x+1][y] Top side output pins */ + temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes( + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x() + 1, + gsb_coord.y(), OPIN, opin_grid_side[1]); break; - } - /* Routing channels*/ - /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ - /* Collect rr_nodes for Tracks for top: chany[x][y+1] */ - /* Create a rr_chan object and check if it is unique in the graph */ - rr_chan = build_one_rr_chan(vpr_device_ctx, CHANX, coordinate); - chan_dir_to_port_dir_mapping[0] = OUT_PORT; /* INC_DIRECTION => OUT_PORT */ - chan_dir_to_port_dir_mapping[1] = IN_PORT; /* DEC_DIRECTION => IN_PORT */ + case BOTTOM: /* BOTTOM = 2*/ + /* For the border, we should take special care */ + if (gsb_coord.y() == 0) { + rr_gsb.clear_one_side(side_manager.get_side()); + break; + } + /* Routing channels*/ + /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ + /* Collect rr_nodes for Tracks for bottom: chany[x][y] */ + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_rr_chan(vpr_device_ctx, CHANY, coordinate); + chan_dir_to_port_dir_mapping[0] = + IN_PORT; /* INC_DIRECTION => IN_PORT */ + chan_dir_to_port_dir_mapping[1] = + OUT_PORT; /* DEC_DIRECTION => OUT_PORT */ - /* Build the Switch block: opin and opin_grid_side */ - /* Assign grid side of OPIN */ - /* Grid[x+1][y+1] BOTTOM side outputs pins */ - opin_grid_side[0] = BOTTOM; - /* Grid[x+1][y] TOP side outputs pins */ - opin_grid_side[1] = TOP; - - /* include Grid[x+1][y+1] Bottom side output pins */ - temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid, - gsb_coord.x() + 1, gsb_coord.y() + 1, OPIN, opin_grid_side[0]); - /* include Grid[x+1][y] Top side output pins */ - temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid, - gsb_coord.x() + 1, gsb_coord.y(), OPIN, opin_grid_side[1]); - break; - case BOTTOM: /* BOTTOM = 2*/ - /* For the border, we should take special care */ - if (gsb_coord.y() == 0) { - rr_gsb.clear_one_side(side_manager.get_side()); + /* Build the Switch block: opin and opin_grid_side */ + /* Assign grid side of OPIN */ + /* Grid[x+1][y] LEFT side outputs pins */ + opin_grid_side[0] = LEFT; + /* Grid[x][y] RIGHT side outputs pins */ + opin_grid_side[1] = RIGHT; + /* include Grid[x+1][y] Left side output pins */ + temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes( + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x() + 1, + gsb_coord.y(), OPIN, opin_grid_side[0]); + /* include Grid[x][y] Right side output pins */ + temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes( + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x(), + gsb_coord.y(), OPIN, opin_grid_side[1]); break; - } - /* Routing channels*/ - /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ - /* Collect rr_nodes for Tracks for bottom: chany[x][y] */ - /* Create a rr_chan object and check if it is unique in the graph */ - rr_chan = build_one_rr_chan(vpr_device_ctx, CHANY, coordinate); - chan_dir_to_port_dir_mapping[0] = IN_PORT; /* INC_DIRECTION => IN_PORT */ - chan_dir_to_port_dir_mapping[1] = OUT_PORT; /* DEC_DIRECTION => OUT_PORT */ + case LEFT: /* LEFT = 3 */ + /* For the border, we should take special care */ + if (gsb_coord.x() == 0) { + rr_gsb.clear_one_side(side_manager.get_side()); + break; + } + /* Routing channels*/ + /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ + /* Collect rr_nodes for Tracks for left: chanx[x][y] */ + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_rr_chan(vpr_device_ctx, CHANX, coordinate); + chan_dir_to_port_dir_mapping[0] = + IN_PORT; /* INC_DIRECTION => IN_PORT */ + chan_dir_to_port_dir_mapping[1] = + OUT_PORT; /* DEC_DIRECTION => OUT_PORT */ - /* Build the Switch block: opin and opin_grid_side */ - /* Assign grid side of OPIN */ - /* Grid[x+1][y] LEFT side outputs pins */ - opin_grid_side[0] = LEFT; - /* Grid[x][y] RIGHT side outputs pins */ - opin_grid_side[1] = RIGHT; - /* include Grid[x+1][y] Left side output pins */ - temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid, - gsb_coord.x() + 1, gsb_coord.y(), OPIN, opin_grid_side[0]); - /* include Grid[x][y] Right side output pins */ - temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid, - gsb_coord.x(), gsb_coord.y(), OPIN, opin_grid_side[1]); - break; - case LEFT: /* LEFT = 3 */ - /* For the border, we should take special care */ - if (gsb_coord.x() == 0) { - rr_gsb.clear_one_side(side_manager.get_side()); + /* Build the Switch block: opin and opin_grid_side */ + /* Grid[x][y+1] BOTTOM side outputs pins */ + opin_grid_side[0] = BOTTOM; + /* Grid[x][y] TOP side outputs pins */ + opin_grid_side[1] = TOP; + /* include Grid[x][y+1] Bottom side outputs pins */ + temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes( + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x(), + gsb_coord.y() + 1, OPIN, opin_grid_side[0]); + /* include Grid[x][y] Top side output pins */ + temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes( + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x(), + gsb_coord.y(), OPIN, opin_grid_side[1]); break; - } - /* Routing channels*/ - /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ - /* Collect rr_nodes for Tracks for left: chanx[x][y] */ - /* Create a rr_chan object and check if it is unique in the graph */ - rr_chan = build_one_rr_chan(vpr_device_ctx, CHANX, coordinate); - chan_dir_to_port_dir_mapping[0] = IN_PORT; /* INC_DIRECTION => IN_PORT */ - chan_dir_to_port_dir_mapping[1] = OUT_PORT; /* DEC_DIRECTION => OUT_PORT */ - - /* Build the Switch block: opin and opin_grid_side */ - /* Grid[x][y+1] BOTTOM side outputs pins */ - opin_grid_side[0] = BOTTOM; - /* Grid[x][y] TOP side outputs pins */ - opin_grid_side[1] = TOP; - /* include Grid[x][y+1] Bottom side outputs pins */ - temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid, - gsb_coord.x(), gsb_coord.y() + 1, OPIN, opin_grid_side[0]); - /* include Grid[x][y] Top side output pins */ - temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid, - gsb_coord.x(), gsb_coord.y(), OPIN, opin_grid_side[1]); - break; - default: - VTR_LOG_ERROR("Invalid side index!\n"); - exit(1); + default: + VTR_LOG_ERROR("Invalid side index!\n"); + exit(1); } /* Organize a vector of port direction */ @@ -243,10 +258,12 @@ RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, rr_chan_dir.resize(rr_chan.get_chan_width()); for (size_t itrack = 0; itrack < rr_chan.get_chan_width(); ++itrack) { /* Identify the directionality, record it in rr_node_direction */ - if (Direction::INC == vpr_device_ctx.rr_graph.node_direction(rr_chan.get_node(itrack))) { + if (Direction::INC == + vpr_device_ctx.rr_graph.node_direction(rr_chan.get_node(itrack))) { rr_chan_dir[itrack] = chan_dir_to_port_dir_mapping[0]; } else { - VTR_ASSERT(Direction::DEC == vpr_device_ctx.rr_graph.node_direction(rr_chan.get_node(itrack))); + VTR_ASSERT(Direction::DEC == vpr_device_ctx.rr_graph.node_direction( + rr_chan.get_node(itrack))); rr_chan_dir[itrack] = chan_dir_to_port_dir_mapping[1]; } } @@ -256,10 +273,12 @@ RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, /* Fill opin_rr_nodes */ /* Copy from temp_opin_rr_node to opin_rr_node */ - for (size_t opin_array_id = 0; opin_array_id < temp_opin_rr_nodes.size(); ++opin_array_id) { + for (size_t opin_array_id = 0; opin_array_id < temp_opin_rr_nodes.size(); + ++opin_array_id) { for (const RRNodeId& inode : temp_opin_rr_nodes[opin_array_id]) { - /* Skip those has no configurable outgoing, they should NOT appear in the GSB connection - * This is for those grid output pins used by direct connections + /* Skip those has no configurable outgoing, they should NOT appear in + * the GSB connection This is for those grid output pins used by direct + * connections */ if (0 == vpr_device_ctx.rr_graph.num_configurable_edges(inode)) { continue; @@ -267,7 +286,8 @@ RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, /* Do not consider OPINs that directly drive an IPIN * they are supposed to be handled by direct connection */ - if (true == is_opin_direct_connected_ipin(vpr_device_ctx.rr_graph, inode)) { + if (true == + is_opin_direct_connected_ipin(vpr_device_ctx.rr_graph, inode)) { continue; } @@ -291,81 +311,85 @@ RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { /* Local variables inside this for loop */ SideManager side_manager(side); - size_t ix; - size_t iy; + size_t ix; + size_t iy; enum e_side chan_side; std::vector temp_ipin_rr_nodes; enum e_side ipin_rr_node_grid_side; - + switch (side) { - case TOP: /* TOP = 0 */ - /* For the bording, we should take special care */ - /* Check if left side chan width is 0 or not */ - chan_side = LEFT; - /* Build the connection block: ipin and ipin_grid_side */ - /* BOTTOM side INPUT Pins of Grid[x][y+1] */ - ix = rr_gsb.get_sb_x(); - iy = rr_gsb.get_sb_y() + 1; - ipin_rr_node_grid_side = BOTTOM; - break; - case RIGHT: /* RIGHT = 1 */ - /* For the bording, we should take special care */ - /* Check if TOP side chan width is 0 or not */ - chan_side = TOP; - /* Build the connection block: ipin and ipin_grid_side */ - /* LEFT side INPUT Pins of Grid[x+1][y+1] */ - ix = rr_gsb.get_sb_x() + 1; - iy = rr_gsb.get_sb_y() + 1; - ipin_rr_node_grid_side = LEFT; - break; - case BOTTOM: /* BOTTOM = 2*/ - /* For the bording, we should take special care */ - /* Check if left side chan width is 0 or not */ - chan_side = LEFT; - /* Build the connection block: ipin and ipin_grid_side */ - /* TOP side INPUT Pins of Grid[x][y] */ - ix = rr_gsb.get_sb_x(); - iy = rr_gsb.get_sb_y(); - ipin_rr_node_grid_side = TOP; - break; - case LEFT: /* LEFT = 3 */ - /* For the bording, we should take special care */ - /* Check if left side chan width is 0 or not */ - chan_side = TOP; - /* Build the connection block: ipin and ipin_grid_side */ - /* RIGHT side INPUT Pins of Grid[x][y+1] */ - ix = rr_gsb.get_sb_x(); - iy = rr_gsb.get_sb_y() + 1; - ipin_rr_node_grid_side = RIGHT; - break; - default: - VTR_LOG_ERROR("Invalid side index!\n"); - exit(1); + case TOP: /* TOP = 0 */ + /* For the bording, we should take special care */ + /* Check if left side chan width is 0 or not */ + chan_side = LEFT; + /* Build the connection block: ipin and ipin_grid_side */ + /* BOTTOM side INPUT Pins of Grid[x][y+1] */ + ix = rr_gsb.get_sb_x(); + iy = rr_gsb.get_sb_y() + 1; + ipin_rr_node_grid_side = BOTTOM; + break; + case RIGHT: /* RIGHT = 1 */ + /* For the bording, we should take special care */ + /* Check if TOP side chan width is 0 or not */ + chan_side = TOP; + /* Build the connection block: ipin and ipin_grid_side */ + /* LEFT side INPUT Pins of Grid[x+1][y+1] */ + ix = rr_gsb.get_sb_x() + 1; + iy = rr_gsb.get_sb_y() + 1; + ipin_rr_node_grid_side = LEFT; + break; + case BOTTOM: /* BOTTOM = 2*/ + /* For the bording, we should take special care */ + /* Check if left side chan width is 0 or not */ + chan_side = LEFT; + /* Build the connection block: ipin and ipin_grid_side */ + /* TOP side INPUT Pins of Grid[x][y] */ + ix = rr_gsb.get_sb_x(); + iy = rr_gsb.get_sb_y(); + ipin_rr_node_grid_side = TOP; + break; + case LEFT: /* LEFT = 3 */ + /* For the bording, we should take special care */ + /* Check if left side chan width is 0 or not */ + chan_side = TOP; + /* Build the connection block: ipin and ipin_grid_side */ + /* RIGHT side INPUT Pins of Grid[x][y+1] */ + ix = rr_gsb.get_sb_x(); + iy = rr_gsb.get_sb_y() + 1; + ipin_rr_node_grid_side = RIGHT; + break; + default: + VTR_LOG_ERROR("Invalid side index!\n"); + exit(1); } - + /* If there is no channel at this side, we skip ipin_node annotation */ if (0 == rr_gsb.get_chan_width(chan_side)) { continue; } - /* 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); - /* Fill the ipin nodes of RRGSB */ + /* 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); + /* 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 GSB connection - * This is for those grid output pins used by direct connections + /* Skip those has no configurable outgoing, they should NOT appear in the + * GSB connection This is for those grid output pins used by direct + * connections */ - if (0 == vpr_device_ctx.rr_graph.node_configurable_in_edges(inode).size()) { + if (0 == + vpr_device_ctx.rr_graph.node_configurable_in_edges(inode).size()) { continue; } /* Do not consider IPINs that are directly connected by an OPIN * they are supposed to be handled by direct connection */ - if (true == is_ipin_direct_connected_opin(vpr_device_ctx.rr_graph, inode)) { + if (true == + is_ipin_direct_connected_opin(vpr_device_ctx.rr_graph, inode)) { continue; } - + rr_gsb.add_ipin_node(inode, side_manager.get_side()); } /* Clear the temp data */ @@ -379,39 +403,43 @@ RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, * Build the annotation for the routing resource graph * by collecting the nodes to the General Switch Block context *******************************************************************/ -void annotate_device_rr_gsb(const DeviceContext& vpr_device_ctx, +void annotate_device_rr_gsb(const DeviceContext& vpr_device_ctx, DeviceRRGSB& device_rr_gsb, const bool& verbose_output) { + vtr::ScopedStartFinishTimer timer( + "Build General Switch Block(GSB) annotation on top of routing resource " + "graph"); - vtr::ScopedStartFinishTimer timer("Build General Switch Block(GSB) annotation on top of routing resource graph"); - - /* 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); + /* 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); device_rr_gsb.reserve(gsb_range); - VTR_LOGV(verbose_output, - "Start annotation GSB up to [%lu][%lu]\n", + VTR_LOGV(verbose_output, "Start annotation GSB up to [%lu][%lu]\n", gsb_range.x(), gsb_range.y()); 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 + /* 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)); - + 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 to device_rr_gsb */ vtr::Point gsb_coordinate = rr_gsb.get_sb_coordinate(); device_rr_gsb.add_rr_gsb(gsb_coordinate, rr_gsb); gsb_cnt++; /* Update counter */ /* Print info */ VTR_LOG("[%lu%] Backannotated GSB[%lu][%lu]\r", - 100 * gsb_cnt / (gsb_range.x() * gsb_range.y()), - ix, iy); + 100 * gsb_cnt / (gsb_range.x() * gsb_range.y()), ix, iy); } } /* Report number of unique mirrors */ @@ -426,13 +454,15 @@ void annotate_device_rr_gsb(const DeviceContext& vpr_device_ctx, void sort_device_rr_gsb_chan_node_in_edges(const RRGraphView& rr_graph, DeviceRRGSB& device_rr_gsb, const bool& verbose_output) { - vtr::ScopedStartFinishTimer timer("Sort incoming edges for each routing track output node of General Switch Block(GSB)"); + vtr::ScopedStartFinishTimer timer( + "Sort incoming edges for each routing track output node of General Switch " + "Block(GSB)"); - /* Note that the GSB array is smaller than the grids by 1 column and 1 row!!! */ + /* Note that the GSB array is smaller than the grids by 1 column and 1 row!!! + */ vtr::Point gsb_range = device_rr_gsb.get_gsb_range(); - VTR_LOGV(verbose_output, - "Start sorting edges for GSBs up to [%lu][%lu]\n", + VTR_LOGV(verbose_output, "Start sorting edges for GSBs up to [%lu][%lu]\n", gsb_range.x(), gsb_range.y()); size_t gsb_cnt = 0; @@ -447,15 +477,18 @@ void sort_device_rr_gsb_chan_node_in_edges(const RRGraphView& rr_graph, gsb_cnt++; /* Update counter */ /* Print info */ - VTR_LOG("[%lu%] Sorted incoming edges for each routing track output node of GSB[%lu][%lu]\r", - 100 * gsb_cnt / (gsb_range.x() * gsb_range.y()), - ix, iy); - } + VTR_LOG( + "[%lu%] Sorted incoming edges for each routing track output node of " + "GSB[%lu][%lu]\r", + 100 * gsb_cnt / (gsb_range.x() * gsb_range.y()), ix, iy); + } } /* Report number of unique mirrors */ - VTR_LOG("Sorted incoming edges for each routing track output node of %d General Switch Blocks (GSBs).\n", - gsb_range.x() * gsb_range.y()); + VTR_LOG( + "Sorted incoming edges for each routing track output node of %d General " + "Switch Blocks (GSBs).\n", + gsb_range.x() * gsb_range.y()); } /******************************************************************** @@ -465,13 +498,14 @@ void sort_device_rr_gsb_chan_node_in_edges(const RRGraphView& rr_graph, void sort_device_rr_gsb_ipin_node_in_edges(const RRGraphView& rr_graph, DeviceRRGSB& device_rr_gsb, const bool& verbose_output) { - vtr::ScopedStartFinishTimer timer("Sort incoming edges for each input pin node of General Switch Block(GSB)"); + vtr::ScopedStartFinishTimer timer( + "Sort incoming edges for each input pin node of General Switch Block(GSB)"); - /* Note that the GSB array is smaller than the grids by 1 column and 1 row!!! */ + /* Note that the GSB array is smaller than the grids by 1 column and 1 row!!! + */ vtr::Point gsb_range = device_rr_gsb.get_gsb_range(); - VTR_LOGV(verbose_output, - "Start sorting edges for GSBs up to [%lu][%lu]\n", + VTR_LOGV(verbose_output, "Start sorting edges for GSBs up to [%lu][%lu]\n", gsb_range.x(), gsb_range.y()); size_t gsb_cnt = 0; @@ -486,205 +520,227 @@ void sort_device_rr_gsb_ipin_node_in_edges(const RRGraphView& rr_graph, gsb_cnt++; /* Update counter */ /* Print info */ - VTR_LOG("[%lu%] Sorted incoming edges for each input pin node of GSB[%lu][%lu]\r", - 100 * gsb_cnt / (gsb_range.x() * gsb_range.y()), - ix, iy); - } + VTR_LOG( + "[%lu%] Sorted incoming edges for each input pin node of " + "GSB[%lu][%lu]\r", + 100 * gsb_cnt / (gsb_range.x() * gsb_range.y()), ix, iy); + } } /* Report number of unique mirrors */ - VTR_LOG("Sorted incoming edges for each input pin node of %d General Switch Blocks (GSBs).\n", - gsb_range.x() * gsb_range.y()); + VTR_LOG( + "Sorted incoming edges for each input pin node of %d General Switch Blocks " + "(GSBs).\n", + gsb_range.x() * gsb_range.y()); } - /******************************************************************** - * Build the link between rr_graph switches to their physical circuit models + * Build the link between rr_graph switches to their physical circuit models * The binding is done based on the name of rr_switches defined in the * OpenFPGA arch XML *******************************************************************/ -static -void annotate_rr_switch_circuit_models(const DeviceContext& vpr_device_ctx, - const Arch& openfpga_arch, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { +static void annotate_rr_switch_circuit_models( + const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { size_t count = 0; - for (size_t rr_switch_id = 0; rr_switch_id < vpr_device_ctx.rr_graph.rr_switch().size(); rr_switch_id++) { - std::string switch_name(vpr_device_ctx.rr_graph.rr_switch()[RRSwitchId(rr_switch_id)].name); + for (size_t rr_switch_id = 0; + rr_switch_id < vpr_device_ctx.rr_graph.rr_switch().size(); + rr_switch_id++) { + std::string switch_name( + vpr_device_ctx.rr_graph.rr_switch()[RRSwitchId(rr_switch_id)].name); /* Skip the delayless switch, which is only used by the edges between * - SOURCE and OPIN - * - IPIN and SINK + * - IPIN and SINK */ if (switch_name == std::string(VPR_DELAYLESS_SWITCH_NAME)) { continue; } CircuitModelId circuit_model = CircuitModelId::INVALID(); - /* The name-to-circuit mapping is stored in either cb_switch-to-circuit or sb_switch-to-circuit, - * Try to find one and update the device annotation - */ + /* The name-to-circuit mapping is stored in either cb_switch-to-circuit or + * sb_switch-to-circuit, Try to find one and update the device annotation + */ if (0 < openfpga_arch.cb_switch2circuit.count(switch_name)) { - circuit_model = openfpga_arch.cb_switch2circuit.at(switch_name); + circuit_model = openfpga_arch.cb_switch2circuit.at(switch_name); } if (0 < openfpga_arch.sb_switch2circuit.count(switch_name)) { if (CircuitModelId::INVALID() != circuit_model) { - VTR_LOG_WARN("Found a connection block and a switch block switch share the same name '%s' and binded to different circuit models '%s' and '%s'!\nWill use the switch block switch binding!\n", - switch_name.c_str(), - openfpga_arch.circuit_lib.model_name(circuit_model).c_str(), - openfpga_arch.circuit_lib.model_name(openfpga_arch.sb_switch2circuit.at(switch_name)).c_str()); + VTR_LOG_WARN( + "Found a connection block and a switch block switch share the same " + "name '%s' and binded to different circuit models '%s' and " + "'%s'!\nWill use the switch block switch binding!\n", + switch_name.c_str(), + openfpga_arch.circuit_lib.model_name(circuit_model).c_str(), + openfpga_arch.circuit_lib + .model_name(openfpga_arch.sb_switch2circuit.at(switch_name)) + .c_str()); } - circuit_model = openfpga_arch.sb_switch2circuit.at(switch_name); + circuit_model = openfpga_arch.sb_switch2circuit.at(switch_name); } /* Cannot find a circuit model, error out! */ if (CircuitModelId::INVALID() == circuit_model) { - VTR_LOG_ERROR("Fail to find a circuit model for a routing resource graph switch '%s'!\nPlease check your OpenFPGA architecture XML!\n", - switch_name.c_str()); + VTR_LOG_ERROR( + "Fail to find a circuit model for a routing resource graph switch " + "'%s'!\nPlease check your OpenFPGA architecture XML!\n", + switch_name.c_str()); exit(1); } /* Check the circuit model type */ - if (CIRCUIT_MODEL_MUX != openfpga_arch.circuit_lib.model_type(circuit_model)) { - VTR_LOG_ERROR("Require circuit model type '%s' for a routing resource graph switch '%s'!\nPlease check your OpenFPGA architecture XML!\n", - CIRCUIT_MODEL_TYPE_STRING[CIRCUIT_MODEL_MUX], - switch_name.c_str()); + if (CIRCUIT_MODEL_MUX != + openfpga_arch.circuit_lib.model_type(circuit_model)) { + VTR_LOG_ERROR( + "Require circuit model type '%s' for a routing resource graph switch " + "'%s'!\nPlease check your OpenFPGA architecture XML!\n", + CIRCUIT_MODEL_TYPE_STRING[CIRCUIT_MODEL_MUX], switch_name.c_str()); exit(1); } - + /* Now update the device annotation */ - vpr_device_annotation.add_rr_switch_circuit_model(RRSwitchId(rr_switch_id), circuit_model); - VTR_LOGV(verbose_output, - "Binded a routing resource graph switch '%s' to circuit model '%s'\n", - switch_name.c_str(), - openfpga_arch.circuit_lib.model_name(circuit_model).c_str()); + vpr_device_annotation.add_rr_switch_circuit_model(RRSwitchId(rr_switch_id), + circuit_model); + VTR_LOGV( + verbose_output, + "Binded a routing resource graph switch '%s' to circuit model '%s'\n", + switch_name.c_str(), + openfpga_arch.circuit_lib.model_name(circuit_model).c_str()); count++; } - + VTR_LOG("Binded %lu routing resource graph switches to circuit models\n", count); } /******************************************************************** - * Build the link between rr_graph routing segments to their physical circuit models - * The binding is done based on the name of rr_segment defined in the + * Build the link between rr_graph routing segments to their physical circuit + *models The binding is done based on the name of rr_segment defined in the * OpenFPGA arch XML *******************************************************************/ -static -void annotate_rr_segment_circuit_models(const DeviceContext& vpr_device_ctx, - const Arch& openfpga_arch, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { +static void annotate_rr_segment_circuit_models( + const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { size_t count = 0; for (size_t iseg = 0; iseg < vpr_device_ctx.arch->Segments.size(); ++iseg) { - std::string segment_name = vpr_device_ctx.arch->Segments[iseg].name; + std::string segment_name = vpr_device_ctx.arch->Segments[iseg].name; CircuitModelId circuit_model = CircuitModelId::INVALID(); - /* The name-to-circuit mapping is stored in either cb_switch-to-circuit or sb_switch-to-circuit, - * Try to find one and update the device annotation - */ + /* The name-to-circuit mapping is stored in either cb_switch-to-circuit or + * sb_switch-to-circuit, Try to find one and update the device annotation + */ if (0 < openfpga_arch.routing_seg2circuit.count(segment_name)) { - circuit_model = openfpga_arch.routing_seg2circuit.at(segment_name); + circuit_model = openfpga_arch.routing_seg2circuit.at(segment_name); } /* Cannot find a circuit model, error out! */ if (CircuitModelId::INVALID() == circuit_model) { - VTR_LOG_ERROR("Fail to find a circuit model for a routing segment '%s'!\nPlease check your OpenFPGA architecture XML!\n", - segment_name.c_str()); + VTR_LOG_ERROR( + "Fail to find a circuit model for a routing segment '%s'!\nPlease " + "check your OpenFPGA architecture XML!\n", + segment_name.c_str()); exit(1); } /* Check the circuit model type */ - if (CIRCUIT_MODEL_CHAN_WIRE != openfpga_arch.circuit_lib.model_type(circuit_model)) { - VTR_LOG_ERROR("Require circuit model type '%s' for a routing segment '%s'!\nPlease check your OpenFPGA architecture XML!\n", - CIRCUIT_MODEL_TYPE_STRING[CIRCUIT_MODEL_CHAN_WIRE], - segment_name.c_str()); + if (CIRCUIT_MODEL_CHAN_WIRE != + openfpga_arch.circuit_lib.model_type(circuit_model)) { + VTR_LOG_ERROR( + "Require circuit model type '%s' for a routing segment '%s'!\nPlease " + "check your OpenFPGA architecture XML!\n", + CIRCUIT_MODEL_TYPE_STRING[CIRCUIT_MODEL_CHAN_WIRE], + segment_name.c_str()); exit(1); } - + /* Now update the device annotation */ - vpr_device_annotation.add_rr_segment_circuit_model(RRSegmentId(iseg), circuit_model); - VTR_LOGV(verbose_output, + vpr_device_annotation.add_rr_segment_circuit_model(RRSegmentId(iseg), + circuit_model); + VTR_LOGV(verbose_output, "Binded a routing segment '%s' to circuit model '%s'\n", segment_name.c_str(), openfpga_arch.circuit_lib.model_name(circuit_model).c_str()); count++; } - - VTR_LOG("Binded %lu routing segments to circuit models\n", - count); + + VTR_LOG("Binded %lu routing segments to circuit models\n", count); } /******************************************************************** - * Build the link between rr_graph direct connection to their physical circuit models - * The binding is done based on the name of directs defined in the + * Build the link between rr_graph direct connection to their physical circuit + *models The binding is done based on the name of directs defined in the * OpenFPGA arch XML *******************************************************************/ -static -void annotate_direct_circuit_models(const DeviceContext& vpr_device_ctx, - const Arch& openfpga_arch, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { +static void annotate_direct_circuit_models( + const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { size_t count = 0; for (int idirect = 0; idirect < vpr_device_ctx.arch->num_directs; ++idirect) { - std::string direct_name = vpr_device_ctx.arch->Directs[idirect].name; - /* The name-to-circuit mapping is stored in either cb_switch-to-circuit or sb_switch-to-circuit, - * Try to find one and update the device annotation - */ + std::string direct_name = vpr_device_ctx.arch->Directs[idirect].name; + /* The name-to-circuit mapping is stored in either cb_switch-to-circuit or + * sb_switch-to-circuit, Try to find one and update the device annotation + */ ArchDirectId direct_id = openfpga_arch.arch_direct.direct(direct_name); /* Cannot find a direct, no annotation needed for this direct */ if (ArchDirectId::INVALID() == direct_id) { continue; } - CircuitModelId circuit_model = openfpga_arch.arch_direct.circuit_model(direct_id); + CircuitModelId circuit_model = + openfpga_arch.arch_direct.circuit_model(direct_id); /* Cannot find a circuit model, error out! */ if (CircuitModelId::INVALID() == circuit_model) { - VTR_LOG_ERROR("Fail to find a circuit model for a direct connection '%s'!\nPlease check your OpenFPGA architecture XML!\n", - direct_name.c_str()); + VTR_LOG_ERROR( + "Fail to find a circuit model for a direct connection '%s'!\nPlease " + "check your OpenFPGA architecture XML!\n", + direct_name.c_str()); exit(1); } /* Check the circuit model type */ - if (CIRCUIT_MODEL_WIRE != openfpga_arch.circuit_lib.model_type(circuit_model)) { - VTR_LOG_ERROR("Require circuit model type '%s' for a direct connection '%s'!\nPlease check your OpenFPGA architecture XML!\n", - CIRCUIT_MODEL_TYPE_STRING[CIRCUIT_MODEL_WIRE], - direct_name.c_str()); + if (CIRCUIT_MODEL_WIRE != + openfpga_arch.circuit_lib.model_type(circuit_model)) { + VTR_LOG_ERROR( + "Require circuit model type '%s' for a direct connection '%s'!\nPlease " + "check your OpenFPGA architecture XML!\n", + CIRCUIT_MODEL_TYPE_STRING[CIRCUIT_MODEL_WIRE], direct_name.c_str()); exit(1); } - + /* Now update the device annotation */ vpr_device_annotation.add_direct_annotation(idirect, direct_id); - VTR_LOGV(verbose_output, + VTR_LOGV(verbose_output, "Binded a direct connection '%s' to circuit model '%s'\n", direct_name.c_str(), openfpga_arch.circuit_lib.model_name(circuit_model).c_str()); count++; } - - VTR_LOG("Binded %lu direct connections to circuit models\n", - count); + + VTR_LOG("Binded %lu direct connections to circuit models\n", count); } /******************************************************************** - * Build the link between + * Build the link between * - rr_graph switches - * - rr_graph segments + * - rr_graph segments * - directlist - * to their physical circuit models + * to their physical circuit models *******************************************************************/ -void annotate_rr_graph_circuit_models(const DeviceContext& vpr_device_ctx, - const Arch& openfpga_arch, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output) { +void annotate_rr_graph_circuit_models( + const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output) { /* Iterate over each rr_switch in the device context and bind with names */ - annotate_rr_switch_circuit_models(vpr_device_ctx, openfpga_arch, vpr_device_annotation, verbose_output); + annotate_rr_switch_circuit_models(vpr_device_ctx, openfpga_arch, + vpr_device_annotation, verbose_output); /* Iterate over each rr_segment in the device context and bind with names */ - annotate_rr_segment_circuit_models(vpr_device_ctx, openfpga_arch, vpr_device_annotation, verbose_output); + annotate_rr_segment_circuit_models(vpr_device_ctx, openfpga_arch, + vpr_device_annotation, verbose_output); - /* Iterate over each direct connection in the device context and bind with names */ - annotate_direct_circuit_models(vpr_device_ctx, openfpga_arch, vpr_device_annotation, verbose_output); + /* Iterate over each direct connection in the device context and bind with + * names */ + annotate_direct_circuit_models(vpr_device_ctx, openfpga_arch, + vpr_device_annotation, verbose_output); } } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/annotate_rr_graph.h b/openfpga/src/annotation/annotate_rr_graph.h index ee0d46aa7..f2822c2a4 100644 --- a/openfpga/src/annotation/annotate_rr_graph.h +++ b/openfpga/src/annotation/annotate_rr_graph.h @@ -4,9 +4,9 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" -#include "openfpga_context.h" #include "device_rr_gsb.h" +#include "openfpga_context.h" +#include "vpr_context.h" /******************************************************************** * Function declaration @@ -15,7 +15,7 @@ /* begin namespace openfpga */ namespace openfpga { -void annotate_device_rr_gsb(const DeviceContext& vpr_device_ctx, +void annotate_device_rr_gsb(const DeviceContext& vpr_device_ctx, DeviceRRGSB& device_rr_gsb, const bool& verbose_output); @@ -27,10 +27,9 @@ void sort_device_rr_gsb_ipin_node_in_edges(const RRGraphView& rr_graph, DeviceRRGSB& device_rr_gsb, const bool& verbose_output); -void annotate_rr_graph_circuit_models(const DeviceContext& vpr_device_ctx, - const Arch& openfpga_arch, - VprDeviceAnnotation& vpr_device_annotation, - const bool& verbose_output); +void annotate_rr_graph_circuit_models( + const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, + VprDeviceAnnotation& vpr_device_annotation, const bool& verbose_output); } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/annotate_simulation_setting.cpp b/openfpga/src/annotation/annotate_simulation_setting.cpp index 874f17a5f..a3d489efe 100644 --- a/openfpga/src/annotation/annotate_simulation_setting.cpp +++ b/openfpga/src/annotation/annotate_simulation_setting.cpp @@ -13,11 +13,10 @@ #include "vtr_log.h" /* Headers from vpr library */ -#include "timing_info.h" #include "AnalysisDelayCalculator.h" -#include "net_delay.h" - #include "annotate_simulation_setting.h" +#include "net_delay.h" +#include "timing_info.h" /* begin namespace openfpga */ namespace openfpga { @@ -27,9 +26,9 @@ constexpr int MIN_NUM_SIM_OPERATING_CLOCK_CYCLES = 2; /******************************************************************** * Find the average signal density for all the nets of user's benchmark *******************************************************************/ -static -float average_atom_net_signal_density(const AtomContext& atom_ctx, - const std::unordered_map& net_activity) { +static float average_atom_net_signal_density( + const AtomContext& atom_ctx, + const std::unordered_map& net_activity) { float avg_density = 0.; size_t net_cnt = 0; @@ -45,21 +44,20 @@ float average_atom_net_signal_density(const AtomContext& atom_ctx, continue; } - avg_density += net_activity.at(atom_net).density; + avg_density += net_activity.at(atom_net).density; net_cnt++; } - return avg_density / net_cnt; -} + return avg_density / net_cnt; +} /******************************************************************** * Find the average signal density for all the nets of user's benchmark * by applying a weight to each net density *******************************************************************/ -static -float average_weighted_atom_net_signal_density(const AtomContext& atom_ctx, - const std::unordered_map& net_activity) { - +static float average_weighted_atom_net_signal_density( + const AtomContext& atom_ctx, + const std::unordered_map& net_activity) { float weighted_avg_density = 0.; size_t weighted_net_cnt = 0; @@ -76,26 +74,29 @@ float average_weighted_atom_net_signal_density(const AtomContext& atom_ctx, } /* Consider the weight of fan-out */ - size_t net_weight; - if (0 == std::distance(atom_ctx.nlist.net_sinks(atom_net).begin(), atom_ctx.nlist.net_sinks(atom_net).end())) { + size_t net_weight; + if (0 == std::distance(atom_ctx.nlist.net_sinks(atom_net).begin(), + atom_ctx.nlist.net_sinks(atom_net).end())) { net_weight = 1; } else { - VTR_ASSERT(0 < std::distance(atom_ctx.nlist.net_sinks(atom_net).begin(), atom_ctx.nlist.net_sinks(atom_net).end())); - net_weight = std::distance(atom_ctx.nlist.net_sinks(atom_net).begin(), atom_ctx.nlist.net_sinks(atom_net).end()); + VTR_ASSERT(0 < std::distance(atom_ctx.nlist.net_sinks(atom_net).begin(), + atom_ctx.nlist.net_sinks(atom_net).end())); + net_weight = std::distance(atom_ctx.nlist.net_sinks(atom_net).begin(), + atom_ctx.nlist.net_sinks(atom_net).end()); } - weighted_avg_density += net_activity.at(atom_net).density* net_weight; + weighted_avg_density += net_activity.at(atom_net).density * net_weight; weighted_net_cnt += net_weight; } - return weighted_avg_density / weighted_net_cnt; + return weighted_avg_density / weighted_net_cnt; } /******************************************************************** - * Find median of signal density of all the nets + * Find median of signal density of all the nets *******************************************************************/ -static -size_t median_atom_net_signal_density(const AtomContext& atom_ctx, - const std::unordered_map& net_activity) { +static size_t median_atom_net_signal_density( + const AtomContext& atom_ctx, + const std::unordered_map& net_activity) { /* Sort the net density */ std::vector net_densities; @@ -113,60 +114,66 @@ size_t median_atom_net_signal_density(const AtomContext& atom_ctx, /* Get the median */ /* check for even case */ - if (net_densities.size() % 2 != 0) { + if (net_densities.size() % 2 != 0) { return net_densities[size_t(net_densities.size() / 2)]; - } - - return 0.5 * (net_densities[size_t((net_densities.size() - 1) / 2)] + net_densities[size_t((net_densities.size() - 1) / 2)]); + } + + return 0.5 * (net_densities[size_t((net_densities.size() - 1) / 2)] + + net_densities[size_t((net_densities.size() - 1) / 2)]); } /******************************************************************** - * Find the number of clock cycles in simulation based on the average signal density + * Find the number of clock cycles in simulation based on the average signal + *density *******************************************************************/ -static -size_t recommend_num_sim_clock_cycle(const AtomContext& atom_ctx, - const std::unordered_map& net_activity, - const float& sim_window_size) { - - float average_density = average_atom_net_signal_density(atom_ctx, net_activity); - float average_weighted_density = average_weighted_atom_net_signal_density(atom_ctx, net_activity); +static size_t recommend_num_sim_clock_cycle( + const AtomContext& atom_ctx, + const std::unordered_map& net_activity, + const float& sim_window_size) { + float average_density = + average_atom_net_signal_density(atom_ctx, net_activity); + float average_weighted_density = + average_weighted_atom_net_signal_density(atom_ctx, net_activity); float median_density = median_atom_net_signal_density(atom_ctx, net_activity); - VTR_LOG("Average net density: %.2f\n", - average_density); - VTR_LOG("Median net density: %.2f\n", - median_density); + VTR_LOG("Average net density: %.2f\n", average_density); + VTR_LOG("Median net density: %.2f\n", median_density); VTR_LOG("Average net density after weighting: %.2f\n", average_weighted_density); - /* We have three choices in selecting the number of clock cycles based on signal density - * 1. average signal density + /* We have three choices in selecting the number of clock cycles based on + * signal density + * 1. average signal density * 2. median signal density - * 3. a mixed of average and median signal density + * 3. a mixed of average and median signal density */ size_t recmd_num_clock_cycles = 0; - if ( (0. == median_density) - && (0. == average_density) ) { + if ((0. == median_density) && (0. == average_density)) { recmd_num_clock_cycles = 1; - VTR_LOG_WARN("All the signal density is zero!\nNumber of clock cycles in simulations are set to be %ld!\n", - recmd_num_clock_cycles); + VTR_LOG_WARN( + "All the signal density is zero!\nNumber of clock cycles in simulations " + "are set to be %ld!\n", + recmd_num_clock_cycles); } else if (0. == average_density) { - recmd_num_clock_cycles = (size_t)round(1 / median_density); + recmd_num_clock_cycles = (size_t)round(1 / median_density); } else if (0. == median_density) { recmd_num_clock_cycles = (size_t)round(1 / average_density); } else { - /* add a sim window size to balance the weight of average density and median density - * In practice, we find that there could be huge difference between avereage and median values - * For a reasonable number of simulation clock cycles, we do this window size. + /* add a sim window size to balance the weight of average density and median + * density In practice, we find that there could be huge difference between + * avereage and median values For a reasonable number of simulation clock + * cycles, we do this window size. */ - recmd_num_clock_cycles = (size_t)round(1 / (sim_window_size * average_density + (1 - sim_window_size) * median_density )); + recmd_num_clock_cycles = + (size_t)round(1 / (sim_window_size * average_density + + (1 - sim_window_size) * median_density)); - VTR_LOG("Window size set for simulation: %.2f\n", - sim_window_size); - VTR_LOG("Net density after applying window size : %.2f\n", - (sim_window_size * average_density + (1 - sim_window_size) * median_density)); + VTR_LOG("Window size set for simulation: %.2f\n", sim_window_size); + VTR_LOG("Net density after applying window size : %.2f\n", + (sim_window_size * average_density + + (1 - sim_window_size) * median_density)); } - + VTR_ASSERT(0 < recmd_num_clock_cycles); /* Minimum number of clock cycles should be at least 2 @@ -176,44 +183,50 @@ size_t recommend_num_sim_clock_cycle(const AtomContext& atom_ctx, recmd_num_clock_cycles = MIN_NUM_SIM_OPERATING_CLOCK_CYCLES; } - return recmd_num_clock_cycles; + return recmd_num_clock_cycles; } /******************************************************************** * Annotate simulation setting based on VPR results * - If the operating clock frequency is set to follow the vpr timing results, * we will set a new operating clock frequency here - * - If the number of clock cycles in simulation is set to be automatically determined, - * we will infer the number based on the average signal density + * - If the number of clock cycles in simulation is set to be automatically + *determined, we will infer the number based on the average signal density *******************************************************************/ -int annotate_simulation_setting(const AtomContext& atom_ctx, - const ClusteringContext& cluster_ctx, - const std::unordered_map& net_activity, - SimulationSetting& sim_setting) { - +int annotate_simulation_setting( + const AtomContext& atom_ctx, const ClusteringContext& cluster_ctx, + const std::unordered_map& net_activity, + SimulationSetting& sim_setting) { /* Find if the operating frequency is binded to vpr results */ if (0. == sim_setting.default_operating_clock_frequency()) { - VTR_LOG("User specified the operating clock frequency to use VPR results\n"); + VTR_LOG( + "User specified the operating clock frequency to use VPR results\n"); /* Run timing analysis and collect critical path delay - * This code is copied from function vpr_analysis() in vpr_api.h + * This code is copied from function vpr_analysis() in vpr_api.h * Should keep updated to latest VPR code base * Note: - * - MUST mention in documentation that VPR should be run in timing enabled mode + * - MUST mention in documentation that VPR should be run in timing + * enabled mode */ - ClbNetPinsMatrix net_delay = make_net_pins_matrix(cluster_ctx.clb_nlist); + ClbNetPinsMatrix net_delay = + make_net_pins_matrix(cluster_ctx.clb_nlist); /* Load the net delays */ load_net_delay_from_routing(net_delay); /* Do final timing analysis */ - auto analysis_delay_calc = std::make_shared(atom_ctx.nlist, atom_ctx.lookup, net_delay); - auto timing_info = make_setup_hold_timing_info(analysis_delay_calc, e_timing_update_type::FULL); + auto analysis_delay_calc = std::make_shared( + atom_ctx.nlist, atom_ctx.lookup, net_delay); + auto timing_info = make_setup_hold_timing_info(analysis_delay_calc, + e_timing_update_type::FULL); timing_info->update(); /* Get critical path delay. Update simulation settings */ - float T_crit = timing_info->least_slack_critical_path().delay() * (1. + sim_setting.operating_clock_frequency_slack()); - sim_setting.set_default_operating_clock_frequency(1 / T_crit); - VTR_LOG("Use VPR critical path delay %g [ns] with a %g [%] slack in OpenFPGA.\n", - T_crit / 1e9, sim_setting.operating_clock_frequency_slack() * 100); + float T_crit = timing_info->least_slack_critical_path().delay() * + (1. + sim_setting.operating_clock_frequency_slack()); + sim_setting.set_default_operating_clock_frequency(1 / T_crit); + VTR_LOG( + "Use VPR critical path delay %g [ns] with a %g [%] slack in OpenFPGA.\n", + T_crit / 1e9, sim_setting.operating_clock_frequency_slack() * 100); } VTR_LOG("Will apply operating clock frequency %g [MHz] to simulations\n", sim_setting.default_operating_clock_frequency() / 1e6); @@ -221,31 +234,38 @@ int annotate_simulation_setting(const AtomContext& atom_ctx, /* Walk through all the clock information */ for (const SimulationClockId& clock_id : sim_setting.clocks()) { if (0. == sim_setting.clock_frequency(clock_id)) { - sim_setting.set_clock_frequency(clock_id, sim_setting.default_operating_clock_frequency()); + sim_setting.set_clock_frequency( + clock_id, sim_setting.default_operating_clock_frequency()); } - VTR_LOG("Will apply clock frequency %g [MHz] to clock '%s[%d:%d]' in simulations\n", - sim_setting.clock_frequency(clock_id) / 1e6, - sim_setting.clock_port(clock_id).get_name().c_str(), - sim_setting.clock_port(clock_id).get_lsb(), - sim_setting.clock_port(clock_id).get_msb()); + VTR_LOG( + "Will apply clock frequency %g [MHz] to clock '%s[%d:%d]' in " + "simulations\n", + sim_setting.clock_frequency(clock_id) / 1e6, + sim_setting.clock_port(clock_id).get_name().c_str(), + sim_setting.clock_port(clock_id).get_lsb(), + sim_setting.clock_port(clock_id).get_msb()); } if (0. == sim_setting.num_clock_cycles()) { - /* Find the number of clock cycles to be used in simulation - * by average over the signal activity + /* Find the number of clock cycles to be used in simulation + * by average over the signal activity */ - VTR_LOG("User specified the number of operating clock cycles to be inferred from signal activities\n"); + VTR_LOG( + "User specified the number of operating clock cycles to be inferred from " + "signal activities\n"); - /* Error out if net activity is not defined */ + /* Error out if net activity is not defined */ if (true == net_activity.empty()) { - VTR_LOG_ERROR("Signal activities are not defined!\nPlease check if activity file is given and properly generated!\n"); + VTR_LOG_ERROR( + "Signal activities are not defined!\nPlease check if activity file is " + "given and properly generated!\n"); return CMD_EXEC_FATAL_ERROR; } - /* Use a fixed simulation window size now. TODO: this could be specified by users */ - size_t num_clock_cycles = recommend_num_sim_clock_cycle(atom_ctx, - net_activity, - 0.5); + /* Use a fixed simulation window size now. TODO: this could be specified by + * users */ + size_t num_clock_cycles = + recommend_num_sim_clock_cycle(atom_ctx, net_activity, 0.5); sim_setting.set_num_clock_cycles(num_clock_cycles); } @@ -253,9 +273,10 @@ int annotate_simulation_setting(const AtomContext& atom_ctx, * so that self-testing testbench can work!!! */ if (MIN_NUM_SIM_OPERATING_CLOCK_CYCLES > sim_setting.num_clock_cycles()) { - VTR_LOG_ERROR("Minimum number of operating clock cycles applicable to simulations is %d, while the specified number is %lu!\n", - MIN_NUM_SIM_OPERATING_CLOCK_CYCLES, - sim_setting.num_clock_cycles()); + VTR_LOG_ERROR( + "Minimum number of operating clock cycles applicable to simulations is " + "%d, while the specified number is %lu!\n", + MIN_NUM_SIM_OPERATING_CLOCK_CYCLES, sim_setting.num_clock_cycles()); return CMD_EXEC_FATAL_ERROR; } diff --git a/openfpga/src/annotation/annotate_simulation_setting.h b/openfpga/src/annotation/annotate_simulation_setting.h index f1c271781..0adfe1f01 100644 --- a/openfpga/src/annotation/annotate_simulation_setting.h +++ b/openfpga/src/annotation/annotate_simulation_setting.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" #include "openfpga_context.h" +#include "vpr_context.h" /******************************************************************** * Function declaration @@ -14,10 +14,10 @@ /* begin namespace openfpga */ namespace openfpga { -int annotate_simulation_setting(const AtomContext& atom_ctx, - const ClusteringContext& cluster_ctx, - const std::unordered_map& net_activity, - SimulationSetting& sim_setting); +int annotate_simulation_setting( + const AtomContext& atom_ctx, const ClusteringContext& cluster_ctx, + const std::unordered_map& net_activity, + SimulationSetting& sim_setting); } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/check_netlist_naming_conflict.cpp b/openfpga/src/annotation/check_netlist_naming_conflict.cpp index a8ab94384..efc8a32d9 100644 --- a/openfpga/src/annotation/check_netlist_naming_conflict.cpp +++ b/openfpga/src/annotation/check_netlist_naming_conflict.cpp @@ -3,24 +3,23 @@ * in the users' BLIF netlist that violates the syntax of OpenFPGA * fabric generator, i.e., Verilog generator and SPICE generator *******************************************************************/ -#include #include +#include /* Headers from vtrutil library */ -#include "vtr_time.h" #include "vtr_assert.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgashell library */ #include "command_exit_codes.h" /* Headers from archopenfpga library */ -#include "write_xml_utils.h" +#include "write_xml_utils.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - #include "check_netlist_naming_conflict.h" +#include "openfpga_digest.h" /* Include global variables of VPR */ #include "globals.h" @@ -29,14 +28,13 @@ namespace openfpga { /******************************************************************** - * This function aims to check if the name contains any of the + * This function aims to check if the name contains any of the * sensitive characters in the list * Return a string of sensitive characters which are contained * in the name *******************************************************************/ -static -std::string name_contain_sensitive_chars(const std::string& name, - const std::string& sensitive_chars) { +static std::string name_contain_sensitive_chars( + const std::string& name, const std::string& sensitive_chars) { std::string violation; for (const char& sensitive_char : sensitive_chars) { @@ -50,14 +48,13 @@ std::string name_contain_sensitive_chars(const std::string& name, } /******************************************************************** - * This function aims to fix up a name that contains any of the + * This function aims to fix up a name that contains any of the * sensitive characters in the list * Return a string the fixed name *******************************************************************/ -static -std::string fix_name_contain_sensitive_chars(const std::string& name, - const std::string& sensitive_chars, - const std::string& fix_chars) { +static std::string fix_name_contain_sensitive_chars( + const std::string& name, const std::string& sensitive_chars, + const std::string& fix_chars) { std::string fixed_name = name; VTR_ASSERT(sensitive_chars.length() == fix_chars.length()); @@ -65,7 +62,8 @@ std::string fix_name_contain_sensitive_chars(const std::string& name, for (size_t ichar = 0; ichar < sensitive_chars.length(); ++ichar) { /* Keep fixing the characters until we cannot find anymore */ std::string::size_type pos = 0u; - while (std::string::npos != (pos = fixed_name.find(sensitive_chars[ichar], pos))) { + while (std::string::npos != + (pos = fixed_name.find(sensitive_chars[ichar], pos))) { fixed_name.replace(pos, 1, std::string(1, fix_chars[ichar])); pos += 1; } @@ -75,22 +73,22 @@ std::string fix_name_contain_sensitive_chars(const std::string& name, } /******************************************************************** - * Detect and report any naming conflict by checking a list of + * Detect and report any naming conflict by checking a list of * sensitive characters - * - Iterate over all the blocks and see if any block name contain + * - Iterate over all the blocks and see if any block name contain * any sensitive character - * - Iterate over all the nets and see if any net name contain + * - Iterate over all the nets and see if any net name contain * any sensitive character *******************************************************************/ -static -size_t detect_netlist_naming_conflict(const AtomNetlist& atom_netlist, - const std::string& sensitive_chars) { +static size_t detect_netlist_naming_conflict( + const AtomNetlist& atom_netlist, const std::string& sensitive_chars) { size_t num_conflicts = 0; /* Walk through blocks in the netlist */ for (const auto& block : atom_netlist.blocks()) { const std::string& block_name = atom_netlist.block_name(block); - const std::string& violation = name_contain_sensitive_chars(block_name, sensitive_chars); + const std::string& violation = + name_contain_sensitive_chars(block_name, sensitive_chars); if (false == violation.empty()) { VTR_LOG("Block '%s' contains illegal characters '%s'\n", block_name.c_str(), violation.c_str()); @@ -101,40 +99,42 @@ size_t detect_netlist_naming_conflict(const AtomNetlist& atom_netlist, /* Walk through nets in the netlist */ for (const auto& net : atom_netlist.nets()) { const std::string& net_name = atom_netlist.net_name(net); - const std::string& violation = name_contain_sensitive_chars(net_name, sensitive_chars); + const std::string& violation = + name_contain_sensitive_chars(net_name, sensitive_chars); if (false == violation.empty()) { - VTR_LOG("Net '%s' contains illegal characters '%s'\n", - net_name.c_str(), violation.c_str()); + VTR_LOG("Net '%s' contains illegal characters '%s'\n", net_name.c_str(), + violation.c_str()); num_conflicts++; } } return num_conflicts; -} +} /******************************************************************** - * Correct and report any naming conflict by checking a list of + * Correct and report any naming conflict by checking a list of * sensitive characters - * - Iterate over all the blocks and correct any block name that contains + * - Iterate over all the blocks and correct any block name that contains * any sensitive character * - Iterate over all the nets and correct any net name that contains * any sensitive character *******************************************************************/ -static -void fix_netlist_naming_conflict(const AtomNetlist& atom_netlist, - const std::string& sensitive_chars, - const std::string& fix_chars, - VprNetlistAnnotation& vpr_netlist_annotation) { +static void fix_netlist_naming_conflict( + const AtomNetlist& atom_netlist, const std::string& sensitive_chars, + const std::string& fix_chars, VprNetlistAnnotation& vpr_netlist_annotation) { size_t num_fixes = 0; /* Walk through blocks in the netlist */ for (const auto& block : atom_netlist.blocks()) { const std::string& block_name = atom_netlist.block_name(block); - const std::string& violation = name_contain_sensitive_chars(block_name, sensitive_chars); + const std::string& violation = + name_contain_sensitive_chars(block_name, sensitive_chars); if (false == violation.empty()) { /* Apply fix-up here */ - vpr_netlist_annotation.rename_block(block, fix_name_contain_sensitive_chars(block_name, sensitive_chars, fix_chars)); + vpr_netlist_annotation.rename_block( + block, fix_name_contain_sensitive_chars(block_name, sensitive_chars, + fix_chars)); num_fixes++; } } @@ -142,17 +142,19 @@ void fix_netlist_naming_conflict(const AtomNetlist& atom_netlist, /* Walk through nets in the netlist */ for (const auto& net : atom_netlist.nets()) { const std::string& net_name = atom_netlist.net_name(net); - const std::string& violation = name_contain_sensitive_chars(net_name, sensitive_chars); + const std::string& violation = + name_contain_sensitive_chars(net_name, sensitive_chars); if (false == violation.empty()) { /* Apply fix-up here */ - vpr_netlist_annotation.rename_net(net, fix_name_contain_sensitive_chars(net_name, sensitive_chars, fix_chars)); + vpr_netlist_annotation.rename_net( + net, + fix_name_contain_sensitive_chars(net_name, sensitive_chars, fix_chars)); num_fixes++; } } if (0 < num_fixes) { - VTR_LOG("Fixed %ld naming conflicts in the netlist.\n", - num_fixes); + VTR_LOG("Fixed %ld naming conflicts in the netlist.\n", num_fixes); } } @@ -160,10 +162,9 @@ void fix_netlist_naming_conflict(const AtomNetlist& atom_netlist, * Report all the fix-up in the naming of netlist components, * i.e., blocks, nets *******************************************************************/ -static -void print_netlist_naming_fix_report(const std::string& fname, - const AtomNetlist& atom_netlist, - const VprNetlistAnnotation& vpr_netlist_annotation) { +static void print_netlist_naming_fix_report( + const std::string& fname, const AtomNetlist& atom_netlist, + const VprNetlistAnnotation& vpr_netlist_annotation) { /* Create a file handler */ std::fstream fp; /* Open the file stream */ @@ -172,40 +173,57 @@ void print_netlist_naming_fix_report(const std::string& fname, /* Validate the file stream */ openfpga::check_file_stream(fname.c_str(), fp); - fp << " " << "\n"; - fp << "" << "\n"; + fp << " " + << "\n"; + fp << "" + << "\n"; + + fp << "\t" + << "" + << "\n"; - fp << "\t" << "" << "\n"; - for (const auto& block : atom_netlist.blocks()) { const std::string& block_name = atom_netlist.block_name(block); if (false == vpr_netlist_annotation.is_block_renamed(block)) { continue; } - fp << "\t\t" << "" << "\n"; + write_xml_attribute(fp, "current", + vpr_netlist_annotation.block_name(block).c_str()); + fp << "/>" + << "\n"; } - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; + + fp << "\t" + << "" + << "\n"; - fp << "\t" << "" << "\n"; - for (const auto& net : atom_netlist.nets()) { const std::string& net_name = atom_netlist.net_name(net); if (false == vpr_netlist_annotation.is_net_renamed(net)) { continue; } - fp << "\t\t" << "" << "\n"; + write_xml_attribute(fp, "current", + vpr_netlist_annotation.net_name(net).c_str()); + fp << "/>" + << "\n"; } - fp << "\t" << "" << "\n"; + fp << "\t" + << "" + << "\n"; - fp << "" << "\n"; + fp << "" + << "\n"; /* Close the file stream */ fp.close(); @@ -217,22 +235,28 @@ void print_netlist_naming_fix_report(const std::string& fname, * fabric generator, i.e., Verilog generator and SPICE generator *******************************************************************/ int check_netlist_naming_conflict(OpenfpgaContext& openfpga_context, - const Command& cmd, const CommandContext& cmd_context) { - vtr::ScopedStartFinishTimer timer("Check naming violations of netlist blocks and nets"); + const Command& cmd, + const CommandContext& cmd_context) { + vtr::ScopedStartFinishTimer timer( + "Check naming violations of netlist blocks and nets"); /* By default, we replace all the illegal characters with '_' */ const std::string& sensitive_chars(".,:;\'\"+-<>()[]{}!@#$%^&*~`?/"); - const std::string& fix_chars("____________________________"); + const std::string& fix_chars("____________________________"); CommandOptionId opt_fix = cmd.option("fix"); - /* Do the main job first: detect any naming in the BLIF netlist that violates the syntax */ + /* Do the main job first: detect any naming in the BLIF netlist that violates + * the syntax */ if (false == cmd_context.option_enable(cmd, opt_fix)) { - size_t num_conflicts = detect_netlist_naming_conflict(g_vpr_ctx.atom().nlist, sensitive_chars); - VTR_LOGV_ERROR((0 < num_conflicts && (false == cmd_context.option_enable(cmd, opt_fix))), - "Found %ld naming conflicts in the netlist. Please correct so as to use any fabric generators.\n", - num_conflicts); - VTR_LOGV(0 == num_conflicts, + size_t num_conflicts = + detect_netlist_naming_conflict(g_vpr_ctx.atom().nlist, sensitive_chars); + VTR_LOGV_ERROR( + (0 < num_conflicts && (false == cmd_context.option_enable(cmd, opt_fix))), + "Found %ld naming conflicts in the netlist. Please correct so as to use " + "any fabric generators.\n", + num_conflicts); + VTR_LOGV(0 == num_conflicts, "Check naming conflicts in the netlist passed.\n"); /* If we see conflicts, report minor error */ @@ -247,22 +271,22 @@ int check_netlist_naming_conflict(OpenfpgaContext& openfpga_context, /* If the auto correction is enabled, we apply a fix */ if (true == cmd_context.option_enable(cmd, opt_fix)) { - fix_netlist_naming_conflict(g_vpr_ctx.atom().nlist, sensitive_chars, - fix_chars, openfpga_context.mutable_vpr_netlist_annotation()); + fix_netlist_naming_conflict( + g_vpr_ctx.atom().nlist, sensitive_chars, fix_chars, + openfpga_context.mutable_vpr_netlist_annotation()); CommandOptionId opt_report = cmd.option("report"); if (true == cmd_context.option_enable(cmd, opt_report)) { - print_netlist_naming_fix_report(cmd_context.option_value(cmd, opt_report), - g_vpr_ctx.atom().nlist, - openfpga_context.vpr_netlist_annotation()); + print_netlist_naming_fix_report( + cmd_context.option_value(cmd, opt_report), g_vpr_ctx.atom().nlist, + openfpga_context.vpr_netlist_annotation()); VTR_LOG("Naming fix-up report is generated to file '%s'\n", cmd_context.option_value(cmd, opt_report).c_str()); } - } + } /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; -} +} } /* end namespace openfpga */ - diff --git a/openfpga/src/annotation/check_netlist_naming_conflict.h b/openfpga/src/annotation/check_netlist_naming_conflict.h index cad6c3963..1dc064117 100644 --- a/openfpga/src/annotation/check_netlist_naming_conflict.h +++ b/openfpga/src/annotation/check_netlist_naming_conflict.h @@ -16,7 +16,8 @@ namespace openfpga { int check_netlist_naming_conflict(OpenfpgaContext& openfpga_context, - const Command& cmd, const CommandContext& cmd_context); + const Command& cmd, + const CommandContext& cmd_context); } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/check_pb_graph_annotation.cpp b/openfpga/src/annotation/check_pb_graph_annotation.cpp index 2b86667eb..1d3e2031a 100644 --- a/openfpga/src/annotation/check_pb_graph_annotation.cpp +++ b/openfpga/src/annotation/check_pb_graph_annotation.cpp @@ -3,26 +3,27 @@ * the physical pb_graph_node and pb_graph_pin *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" -#include "vtr_assert.h" -#include "vtr_log.h" +#include "check_pb_graph_annotation.h" #include "pb_type_utils.h" -#include "check_pb_graph_annotation.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * A function to check if a physical pb_graph_pin for a pb_graph_pin + * A function to check if a physical pb_graph_pin for a pb_graph_pin * Print error to log file/screen when checking fails *******************************************************************/ -static -bool check_physical_pb_graph_pin(t_pb_graph_pin* pb_graph_pin, - const VprDeviceAnnotation& vpr_device_annotation) { +static bool check_physical_pb_graph_pin( + t_pb_graph_pin* pb_graph_pin, + const VprDeviceAnnotation& vpr_device_annotation) { if (nullptr == vpr_device_annotation.physical_pb_graph_pin(pb_graph_pin)) { - VTR_LOG_ERROR("Found a pb_graph_pin '%s' missing physical pb_graph_pin binding!\n", - pb_graph_pin->port->name); + VTR_LOG_ERROR( + "Found a pb_graph_pin '%s' missing physical pb_graph_pin binding!\n", + pb_graph_pin->port->name); return false; } @@ -32,24 +33,29 @@ bool check_physical_pb_graph_pin(t_pb_graph_pin* pb_graph_pin, /******************************************************************** * This function will recursively walk through all the pb_graph nodes * starting from a top node. - * It aims to check - * - if each primitive pb_graph node has been binded to a physical + * It aims to check + * - if each primitive pb_graph node has been binded to a physical * pb_graph_node - * - if each pin of the primitive pb_graph node has been binded to + * - if each pin of the primitive pb_graph node has been binded to * a physical graph_pin *******************************************************************/ -static -void rec_check_vpr_physical_pb_graph_node_annotation(t_pb_graph_node* pb_graph_node, - const VprDeviceAnnotation& vpr_device_annotation, - size_t& num_err) { +static void rec_check_vpr_physical_pb_graph_node_annotation( + t_pb_graph_node* pb_graph_node, + const VprDeviceAnnotation& vpr_device_annotation, size_t& num_err) { /* Go recursive first until we touch the primitive node */ if (false == is_primitive_pb_type(pb_graph_node->pb_type)) { for (int imode = 0; imode < pb_graph_node->pb_type->num_modes; ++imode) { - for (int ipb = 0; ipb < pb_graph_node->pb_type->modes[imode].num_pb_type_children; ++ipb) { + for (int ipb = 0; + ipb < pb_graph_node->pb_type->modes[imode].num_pb_type_children; + ++ipb) { /* Each child may exist multiple times in the hierarchy*/ - for (int jpb = 0; jpb < pb_graph_node->pb_type->modes[imode].pb_type_children[ipb].num_pb; ++jpb) { - rec_check_vpr_physical_pb_graph_node_annotation(&(pb_graph_node->child_pb_graph_nodes[imode][ipb][jpb]), - vpr_device_annotation, num_err); + for (int jpb = 0; + jpb < + pb_graph_node->pb_type->modes[imode].pb_type_children[ipb].num_pb; + ++jpb) { + rec_check_vpr_physical_pb_graph_node_annotation( + &(pb_graph_node->child_pb_graph_nodes[imode][ipb][jpb]), + vpr_device_annotation, num_err); } } } @@ -57,42 +63,53 @@ void rec_check_vpr_physical_pb_graph_node_annotation(t_pb_graph_node* pb_graph_n } /* Ensure that the pb_graph_node has been mapped to a physical node */ - t_pb_graph_node* physical_pb_graph_node = vpr_device_annotation.physical_pb_graph_node(pb_graph_node); - if (nullptr == physical_pb_graph_node) { - VTR_LOG_ERROR("Found a pb_graph_node '%s' missing physical pb_graph_node binding!\n", - pb_graph_node->pb_type->name); + t_pb_graph_node* physical_pb_graph_node = + vpr_device_annotation.physical_pb_graph_node(pb_graph_node); + if (nullptr == physical_pb_graph_node) { + VTR_LOG_ERROR( + "Found a pb_graph_node '%s' missing physical pb_graph_node binding!\n", + pb_graph_node->pb_type->name); num_err++; return; /* Invalid pointer already, further check is not applicable */ - } + } /* Reach here, we should have a valid pointer to the physical pb_graph_node, - * Check the physical pb_graph_pin for each pin + * Check the physical pb_graph_pin for each pin */ - for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; ++ipin) { - if (false == check_physical_pb_graph_pin(&(physical_pb_graph_node->input_pins[iport][ipin]), - vpr_device_annotation)) { + for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; + ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; + ++ipin) { + if (false == check_physical_pb_graph_pin( + &(physical_pb_graph_node->input_pins[iport][ipin]), + vpr_device_annotation)) { num_err++; } - } + } } - for (int iport = 0; iport < physical_pb_graph_node->num_output_ports; ++iport) { - for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; ++ipin) { - if (false == check_physical_pb_graph_pin(&(physical_pb_graph_node->output_pins[iport][ipin]), - vpr_device_annotation)) { + for (int iport = 0; iport < physical_pb_graph_node->num_output_ports; + ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; + ++ipin) { + if (false == check_physical_pb_graph_pin( + &(physical_pb_graph_node->output_pins[iport][ipin]), + vpr_device_annotation)) { num_err++; } - } + } } - for (int iport = 0; iport < physical_pb_graph_node->num_clock_ports; ++iport) { - for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; ++ipin) { - if (false == check_physical_pb_graph_pin(&(physical_pb_graph_node->clock_pins[iport][ipin]), - vpr_device_annotation)) { + for (int iport = 0; iport < physical_pb_graph_node->num_clock_ports; + ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; + ++ipin) { + if (false == check_physical_pb_graph_pin( + &(physical_pb_graph_node->clock_pins[iport][ipin]), + vpr_device_annotation)) { num_err++; } - } + } } } @@ -101,23 +118,28 @@ void rec_check_vpr_physical_pb_graph_node_annotation(t_pb_graph_node* pb_graph_n * - It has been binded to an physical pb_graph_node * - Each pin has been binded to a physical pb_graph_node pin *******************************************************************/ -void check_physical_pb_graph_node_annotation(const DeviceContext& vpr_device_ctx, - const VprDeviceAnnotation& vpr_device_annotation) { +void check_physical_pb_graph_node_annotation( + const DeviceContext& vpr_device_ctx, + const VprDeviceAnnotation& vpr_device_annotation) { size_t num_err = 0; - - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_graph head */ if (nullptr == lb_type.pb_graph_head) { continue; } - rec_check_vpr_physical_pb_graph_node_annotation(lb_type.pb_graph_head, vpr_device_annotation, num_err); + rec_check_vpr_physical_pb_graph_node_annotation( + lb_type.pb_graph_head, vpr_device_annotation, num_err); } if (0 == num_err) { VTR_LOG("Check pb_graph annotation for physical nodes and pins passed.\n"); } else { - VTR_LOG_ERROR("Check pb_graph annotation for physical nodes and pins failed with %ld errors!\n", - num_err); + VTR_LOG_ERROR( + "Check pb_graph annotation for physical nodes and pins failed with %ld " + "errors!\n", + num_err); } } diff --git a/openfpga/src/annotation/check_pb_graph_annotation.h b/openfpga/src/annotation/check_pb_graph_annotation.h index 8416800c0..1550d97b6 100644 --- a/openfpga/src/annotation/check_pb_graph_annotation.h +++ b/openfpga/src/annotation/check_pb_graph_annotation.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" #include "openfpga_context.h" +#include "vpr_context.h" #include "vpr_device_annotation.h" /******************************************************************** @@ -15,8 +15,9 @@ /* begin namespace openfpga */ namespace openfpga { -void check_physical_pb_graph_node_annotation(const DeviceContext& vpr_device_ctx, - const VprDeviceAnnotation& vpr_device_annotation); +void check_physical_pb_graph_node_annotation( + const DeviceContext& vpr_device_ctx, + const VprDeviceAnnotation& vpr_device_annotation); } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/check_pb_type_annotation.cpp b/openfpga/src/annotation/check_pb_type_annotation.cpp index 1ed6fea8b..92df530c9 100644 --- a/openfpga/src/annotation/check_pb_type_annotation.cpp +++ b/openfpga/src/annotation/check_pb_type_annotation.cpp @@ -3,13 +3,13 @@ * in particular to annotate the physical mode and physical pb_type *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" +#include "check_pb_type_annotation.h" + +#include "circuit_library_utils.h" +#include "pb_type_utils.h" #include "vtr_assert.h" #include "vtr_log.h" - -#include "pb_type_utils.h" -#include "circuit_library_utils.h" -#include "check_pb_type_annotation.h" +#include "vtr_time.h" /* begin namespace openfpga */ namespace openfpga { @@ -19,11 +19,9 @@ namespace openfpga { * 1. there is only a physical mode under each pb_type * 2. physical mode appears only when its parent is a physical mode. *******************************************************************/ -static -void rec_check_vpr_physical_pb_mode_annotation(t_pb_type* cur_pb_type, - const bool& expect_physical_mode, - const VprDeviceAnnotation& vpr_device_annotation, - size_t& num_err) { +static void rec_check_vpr_physical_pb_mode_annotation( + t_pb_type* cur_pb_type, const bool& expect_physical_mode, + const VprDeviceAnnotation& vpr_device_annotation, size_t& num_err) { /* We do not check any primitive pb_type */ if (true == is_primitive_pb_type(cur_pb_type)) { return; @@ -31,14 +29,15 @@ void rec_check_vpr_physical_pb_mode_annotation(t_pb_type* cur_pb_type, /* For non-primitive pb_type: * - If we expect a physical mode to exist under this pb_type - * we should be able to find one in the annoation - * - If we do NOT expect a physical mode, make sure we find + * we should be able to find one in the annoation + * - If we do NOT expect a physical mode, make sure we find * nothing in the annotation */ if (true == expect_physical_mode) { if (nullptr == vpr_device_annotation.physical_mode(cur_pb_type)) { - VTR_LOG_ERROR("Unable to find a physical mode for a multi-mode pb_type '%s'!\n", - cur_pb_type->name); + VTR_LOG_ERROR( + "Unable to find a physical mode for a multi-mode pb_type '%s'!\n", + cur_pb_type->name); VTR_LOG_ERROR("Please specify in the OpenFPGA architecture\n"); num_err++; return; @@ -46,27 +45,31 @@ void rec_check_vpr_physical_pb_mode_annotation(t_pb_type* cur_pb_type, } else { VTR_ASSERT_SAFE(false == expect_physical_mode); if (nullptr != vpr_device_annotation.physical_mode(cur_pb_type)) { - VTR_LOG_ERROR("Find a physical mode '%s' for pb_type '%s' which is not under any physical mode!\n", - vpr_device_annotation.physical_mode(cur_pb_type)->name, - cur_pb_type->name); + VTR_LOG_ERROR( + "Find a physical mode '%s' for pb_type '%s' which is not under any " + "physical mode!\n", + vpr_device_annotation.physical_mode(cur_pb_type)->name, + cur_pb_type->name); num_err++; return; } } /* Traverse all the modes - * - for pb_type children under a physical mode, we expect an physical mode - * - for pb_type children under non-physical mode, we expect no physical mode + * - for pb_type children under a physical mode, we expect an physical mode + * - for pb_type children under non-physical mode, we expect no physical mode */ for (int imode = 0; imode < cur_pb_type->num_modes; ++imode) { bool expect_child_physical_mode = false; - if (&(cur_pb_type->modes[imode]) == vpr_device_annotation.physical_mode(cur_pb_type)) { - expect_child_physical_mode = true && expect_physical_mode; + if (&(cur_pb_type->modes[imode]) == + vpr_device_annotation.physical_mode(cur_pb_type)) { + expect_child_physical_mode = true && expect_physical_mode; } - for (int ichild = 0; ichild < cur_pb_type->modes[imode].num_pb_type_children; ++ichild) { - rec_check_vpr_physical_pb_mode_annotation(&(cur_pb_type->modes[imode].pb_type_children[ichild]), - expect_child_physical_mode, vpr_device_annotation, - num_err); + for (int ichild = 0; + ichild < cur_pb_type->modes[imode].num_pb_type_children; ++ichild) { + rec_check_vpr_physical_pb_mode_annotation( + &(cur_pb_type->modes[imode].pb_type_children[ichild]), + expect_child_physical_mode, vpr_device_annotation, num_err); } } } @@ -75,48 +78,55 @@ void rec_check_vpr_physical_pb_mode_annotation(t_pb_type* cur_pb_type, * This function will check the physical mode annotation for * each pb_type in the device *******************************************************************/ -void check_vpr_physical_pb_mode_annotation(const DeviceContext& vpr_device_ctx, - const VprDeviceAnnotation& vpr_device_annotation) { +void check_vpr_physical_pb_mode_annotation( + const DeviceContext& vpr_device_ctx, + const VprDeviceAnnotation& vpr_device_annotation) { size_t num_err = 0; - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } /* Top pb_type should always has a physical mode! */ - rec_check_vpr_physical_pb_mode_annotation(lb_type.pb_type, true, vpr_device_annotation, num_err); + rec_check_vpr_physical_pb_mode_annotation(lb_type.pb_type, true, + vpr_device_annotation, num_err); } if (0 == num_err) { VTR_LOG("Check physical mode annotation for pb_types passed.\n"); } else { - VTR_LOG_ERROR("Check physical mode annotation for pb_types failed with %ld errors!\n", - num_err); + VTR_LOG_ERROR( + "Check physical mode annotation for pb_types failed with %ld errors!\n", + num_err); } } /******************************************************************** - * This function will check - * - if a primitive pb_type has been mapped to a physical pb_type + * This function will check + * - if a primitive pb_type has been mapped to a physical pb_type * - if every port of the pb_type have been linked a port of a physical pb_type *******************************************************************/ -static -void check_vpr_physical_primitive_pb_type_annotation(t_pb_type* cur_pb_type, - const VprDeviceAnnotation& vpr_device_annotation, - size_t& num_err) { +static void check_vpr_physical_primitive_pb_type_annotation( + t_pb_type* cur_pb_type, const VprDeviceAnnotation& vpr_device_annotation, + size_t& num_err) { if (nullptr == vpr_device_annotation.physical_pb_type(cur_pb_type)) { - VTR_LOG_ERROR("Find a pb_type '%s' which has not been mapped to any physical pb_type!\n", - cur_pb_type->name); + VTR_LOG_ERROR( + "Find a pb_type '%s' which has not been mapped to any physical " + "pb_type!\n", + cur_pb_type->name); VTR_LOG_ERROR("Please specify in the OpenFPGA architecture\n"); - num_err++; + num_err++; return; } - /* Now we need to check each port of the pb_type */ + /* Now we need to check each port of the pb_type */ for (t_port* pb_port : pb_type_ports(cur_pb_type)) { if (0 == vpr_device_annotation.physical_pb_port(pb_port).size()) { - VTR_LOG_ERROR("Find a port '%s' of pb_type '%s' which has not been mapped to any physical port!\n", - pb_port->name, cur_pb_type->name); + VTR_LOG_ERROR( + "Find a port '%s' of pb_type '%s' which has not been mapped to any " + "physical port!\n", + pb_port->name, cur_pb_type->name); VTR_LOG_ERROR("Please specify in the OpenFPGA architecture\n"); num_err++; } @@ -130,22 +140,23 @@ void check_vpr_physical_primitive_pb_type_annotation(t_pb_type* cur_pb_type, * 1. there is only a physical mode under each pb_type * 2. physical mode appears only when its parent is a physical mode. *******************************************************************/ -static -void rec_check_vpr_physical_pb_type_annotation(t_pb_type* cur_pb_type, - const VprDeviceAnnotation& vpr_device_annotation, - size_t& num_err) { +static void rec_check_vpr_physical_pb_type_annotation( + t_pb_type* cur_pb_type, const VprDeviceAnnotation& vpr_device_annotation, + size_t& num_err) { /* Primitive pb_type should always been binded to a physical pb_type */ if (true == is_primitive_pb_type(cur_pb_type)) { - check_vpr_physical_primitive_pb_type_annotation(cur_pb_type, vpr_device_annotation, num_err); + check_vpr_physical_primitive_pb_type_annotation( + cur_pb_type, vpr_device_annotation, num_err); return; } /* Traverse all the modes */ for (int imode = 0; imode < cur_pb_type->num_modes; ++imode) { - for (int ichild = 0; ichild < cur_pb_type->modes[imode].num_pb_type_children; ++ichild) { - rec_check_vpr_physical_pb_type_annotation(&(cur_pb_type->modes[imode].pb_type_children[ichild]), - vpr_device_annotation, - num_err); + for (int ichild = 0; + ichild < cur_pb_type->modes[imode].num_pb_type_children; ++ichild) { + rec_check_vpr_physical_pb_type_annotation( + &(cur_pb_type->modes[imode].pb_type_children[ichild]), + vpr_device_annotation, num_err); } } } @@ -156,23 +167,28 @@ void rec_check_vpr_physical_pb_type_annotation(t_pb_type* cur_pb_type, * Every pb_type should have been linked to a physical pb_type * and every port of the pb_type have been linked a port of a physical pb_type *******************************************************************/ -void check_vpr_physical_pb_type_annotation(const DeviceContext& vpr_device_ctx, - const VprDeviceAnnotation& vpr_device_annotation) { +void check_vpr_physical_pb_type_annotation( + const DeviceContext& vpr_device_ctx, + const VprDeviceAnnotation& vpr_device_annotation) { size_t num_err = 0; - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } /* Top pb_type should always has a physical mode! */ - rec_check_vpr_physical_pb_type_annotation(lb_type.pb_type, vpr_device_annotation, num_err); + rec_check_vpr_physical_pb_type_annotation(lb_type.pb_type, + vpr_device_annotation, num_err); } if (0 == num_err) { VTR_LOG("Check physical pb_type annotation for pb_types passed.\n"); } else { - VTR_LOG_ERROR("Check physical pb_type annotation for pb_types failed with %ld errors!\n", - num_err); + VTR_LOG_ERROR( + "Check physical pb_type annotation for pb_types failed with %ld " + "errors!\n", + num_err); } } @@ -180,67 +196,78 @@ void check_vpr_physical_pb_type_annotation(const DeviceContext& vpr_device_ctx, * This function will recursively traverse only the physical mode * and physical pb_types in the graph to ensure * - Every physical pb_type should be linked to a valid circuit model - * - Every port of the pb_type have been linked to a valid port of a circuit model + * - Every port of the pb_type have been linked to a valid port of a circuit + *model * - Every interconnect has been linked to a valid circuit model * in a correct type *******************************************************************/ -static -void rec_check_vpr_pb_type_circuit_model_annotation(t_pb_type* cur_pb_type, - const CircuitLibrary& circuit_lib, - const VprDeviceAnnotation& vpr_device_annotation, - size_t& num_err) { +static void rec_check_vpr_pb_type_circuit_model_annotation( + t_pb_type* cur_pb_type, const CircuitLibrary& circuit_lib, + const VprDeviceAnnotation& vpr_device_annotation, size_t& num_err) { /* Primitive pb_type should always been binded to a physical pb_type */ if (true == is_primitive_pb_type(cur_pb_type)) { /* Every physical pb_type should be linked to a valid circuit model */ - if (CircuitModelId::INVALID() == vpr_device_annotation.pb_type_circuit_model(cur_pb_type)) { - VTR_LOG_ERROR("Found a physical pb_type '%s' missing circuit model binding!\n", - generate_pb_type_hierarchy_path(cur_pb_type).c_str()); + if (CircuitModelId::INVALID() == + vpr_device_annotation.pb_type_circuit_model(cur_pb_type)) { + VTR_LOG_ERROR( + "Found a physical pb_type '%s' missing circuit model binding!\n", + generate_pb_type_hierarchy_path(cur_pb_type).c_str()); num_err++; return; /* Invalid id already, further check is not applicable */ } - /* Every port of the pb_type have been linked to a valid port of a circuit model */ + /* Every port of the pb_type have been linked to a valid port of a circuit + * model */ for (t_port* port : pb_type_ports(cur_pb_type)) { - if (CircuitPortId::INVALID() == vpr_device_annotation.pb_circuit_port(port)) { - VTR_LOG_ERROR("Found a port '%s' of physical pb_type '%s' missing circuit port binding!\n", - port->name, - generate_pb_type_hierarchy_path(cur_pb_type).c_str()); + if (CircuitPortId::INVALID() == + vpr_device_annotation.pb_circuit_port(port)) { + VTR_LOG_ERROR( + "Found a port '%s' of physical pb_type '%s' missing circuit port " + "binding!\n", + port->name, generate_pb_type_hierarchy_path(cur_pb_type).c_str()); num_err++; } } return; } - /* Every interconnect in the physical mode has been linked to a valid circuit model in a correct type */ + /* Every interconnect in the physical mode has been linked to a valid circuit + * model in a correct type */ t_mode* physical_mode = vpr_device_annotation.physical_mode(cur_pb_type); for (t_interconnect* interc : pb_mode_interconnects(physical_mode)) { - CircuitModelId interc_circuit_model = vpr_device_annotation.interconnect_circuit_model(interc); + CircuitModelId interc_circuit_model = + vpr_device_annotation.interconnect_circuit_model(interc); if (CircuitModelId::INVALID() == interc_circuit_model) { - VTR_LOG_ERROR("Found an interconnect '%s' under physical mode '%s' of pb_type '%s' missing circuit model binding!\n", - interc->name, - physical_mode->name, - generate_pb_type_hierarchy_path(cur_pb_type).c_str()); + VTR_LOG_ERROR( + "Found an interconnect '%s' under physical mode '%s' of pb_type '%s' " + "missing circuit model binding!\n", + interc->name, physical_mode->name, + generate_pb_type_hierarchy_path(cur_pb_type).c_str()); num_err++; continue; } - e_circuit_model_type required_circuit_model_type = pb_interconnect_require_circuit_model_type(vpr_device_annotation.interconnect_physical_type(interc)); - if (circuit_lib.model_type(interc_circuit_model) != required_circuit_model_type) { - VTR_LOG_ERROR("Found an interconnect '%s' under physical mode '%s' of pb_type '%s' linked to a circuit model '%s' with a wrong type!\nExpect: '%s' Linked: '%s'\n", - interc->name, - physical_mode->name, - generate_pb_type_hierarchy_path(cur_pb_type).c_str(), - circuit_lib.model_name(interc_circuit_model).c_str(), - CIRCUIT_MODEL_TYPE_STRING[circuit_lib.model_type(interc_circuit_model)], - CIRCUIT_MODEL_TYPE_STRING[required_circuit_model_type]); + e_circuit_model_type required_circuit_model_type = + pb_interconnect_require_circuit_model_type( + vpr_device_annotation.interconnect_physical_type(interc)); + if (circuit_lib.model_type(interc_circuit_model) != + required_circuit_model_type) { + VTR_LOG_ERROR( + "Found an interconnect '%s' under physical mode '%s' of pb_type '%s' " + "linked to a circuit model '%s' with a wrong type!\nExpect: '%s' " + "Linked: '%s'\n", + interc->name, physical_mode->name, + generate_pb_type_hierarchy_path(cur_pb_type).c_str(), + circuit_lib.model_name(interc_circuit_model).c_str(), + CIRCUIT_MODEL_TYPE_STRING[circuit_lib.model_type(interc_circuit_model)], + CIRCUIT_MODEL_TYPE_STRING[required_circuit_model_type]); num_err++; } - } + } /* Traverse only the physical mode */ - for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { - rec_check_vpr_pb_type_circuit_model_annotation(&(physical_mode->pb_type_children[ichild]), - circuit_lib, - vpr_device_annotation, - num_err); + for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { + rec_check_vpr_pb_type_circuit_model_annotation( + &(physical_mode->pb_type_children[ichild]), circuit_lib, + vpr_device_annotation, num_err); } } @@ -252,86 +279,102 @@ void rec_check_vpr_pb_type_circuit_model_annotation(t_pb_type* cur_pb_type, * - Every interconnect has been linked to a valid circuit model * in a correct type *******************************************************************/ -void check_vpr_pb_type_circuit_model_annotation(const DeviceContext& vpr_device_ctx, - const CircuitLibrary& circuit_lib, - const VprDeviceAnnotation& vpr_device_annotation) { +void check_vpr_pb_type_circuit_model_annotation( + const DeviceContext& vpr_device_ctx, const CircuitLibrary& circuit_lib, + const VprDeviceAnnotation& vpr_device_annotation) { size_t num_err = 0; - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } /* Top pb_type should always has a physical mode! */ - rec_check_vpr_pb_type_circuit_model_annotation(lb_type.pb_type, circuit_lib, vpr_device_annotation, num_err); + rec_check_vpr_pb_type_circuit_model_annotation( + lb_type.pb_type, circuit_lib, vpr_device_annotation, num_err); } if (0 == num_err) { VTR_LOG("Check physical pb_type annotation for circuit model passed.\n"); } else { - VTR_LOG_ERROR("Check physical pb_type annotation for circuit model failed with %ld errors!\n", - num_err); + VTR_LOG_ERROR( + "Check physical pb_type annotation for circuit model failed with %ld " + "errors!\n", + num_err); } } /******************************************************************** - * This function will recursively traverse all the primitive pb_types + * This function will recursively traverse all the primitive pb_types * in the graph to ensure - * - If a primitive pb_type has mode bits, it must have been linked to a physical pb_type - * and the circuit model must have a port for mode selection. + * - If a primitive pb_type has mode bits, it must have been linked to a + *physical pb_type and the circuit model must have a port for mode selection. * And the port size must match the length of mode bits *******************************************************************/ -static -void rec_check_vpr_pb_type_mode_bits_annotation(t_pb_type* cur_pb_type, - const CircuitLibrary& circuit_lib, - const VprDeviceAnnotation& vpr_device_annotation, - size_t& num_err) { +static void rec_check_vpr_pb_type_mode_bits_annotation( + t_pb_type* cur_pb_type, const CircuitLibrary& circuit_lib, + const VprDeviceAnnotation& vpr_device_annotation, size_t& num_err) { /* Primitive pb_type should always been binded to a physical pb_type */ if (true == is_primitive_pb_type(cur_pb_type)) { /* Find the physical pb_type - * If the physical pb_type has mode selection bits, this pb_type must have as well! + * If the physical pb_type has mode selection bits, this pb_type must have + * as well! */ - t_pb_type* physical_pb_type = vpr_device_annotation.physical_pb_type(cur_pb_type); + t_pb_type* physical_pb_type = + vpr_device_annotation.physical_pb_type(cur_pb_type); if (nullptr == physical_pb_type) { - VTR_LOG_ERROR("Find a pb_type '%s' which has not been mapped to any physical pb_type!\n", - cur_pb_type->name); + VTR_LOG_ERROR( + "Find a pb_type '%s' which has not been mapped to any physical " + "pb_type!\n", + cur_pb_type->name); VTR_LOG_ERROR("Please specify in the OpenFPGA architecture\n"); num_err++; return; } - if (vpr_device_annotation.pb_type_mode_bits(cur_pb_type).size() != vpr_device_annotation.pb_type_mode_bits(physical_pb_type).size()) { - VTR_LOG_ERROR("Found different sizes of mode_bits for pb_type '%s' and its physical pb_type '%s'\n", - cur_pb_type->name, - physical_pb_type->name); + if (vpr_device_annotation.pb_type_mode_bits(cur_pb_type).size() != + vpr_device_annotation.pb_type_mode_bits(physical_pb_type).size()) { + VTR_LOG_ERROR( + "Found different sizes of mode_bits for pb_type '%s' and its physical " + "pb_type '%s'\n", + cur_pb_type->name, physical_pb_type->name); num_err++; return; } - - /* Try to find a mode selection port for the circuit model linked to the circuit model */ - CircuitModelId circuit_model = vpr_device_annotation.pb_type_circuit_model(physical_pb_type); - if (CircuitModelId::INVALID() == vpr_device_annotation.pb_type_circuit_model(physical_pb_type)) { - VTR_LOG_ERROR("Found a physical pb_type '%s' missing circuit model binding!\n", - physical_pb_type->name); + + /* Try to find a mode selection port for the circuit model linked to the + * circuit model */ + CircuitModelId circuit_model = + vpr_device_annotation.pb_type_circuit_model(physical_pb_type); + if (CircuitModelId::INVALID() == + vpr_device_annotation.pb_type_circuit_model(physical_pb_type)) { + VTR_LOG_ERROR( + "Found a physical pb_type '%s' missing circuit model binding!\n", + physical_pb_type->name); num_err++; return; /* Invalid id already, further check is not applicable */ } - + if (0 == vpr_device_annotation.pb_type_mode_bits(cur_pb_type).size()) { /* No mode bits to be checked! */ return; } - /* Search the ports of this circuit model and we must have a mode selection port */ - std::vector mode_select_ports = find_circuit_mode_select_sram_ports(circuit_lib, circuit_model); + /* Search the ports of this circuit model and we must have a mode selection + * port */ + std::vector mode_select_ports = + find_circuit_mode_select_sram_ports(circuit_lib, circuit_model); size_t port_num_mode_bits = 0; for (const CircuitPortId& mode_select_port : mode_select_ports) { port_num_mode_bits += circuit_lib.port_size(mode_select_port); } - if (port_num_mode_bits != vpr_device_annotation.pb_type_mode_bits(cur_pb_type).size()) { - VTR_LOG_ERROR("Length of mode bits of pb_type '%s' does not match the size(%ld) of mode selection ports of circuit model '%s'!\n", - cur_pb_type->name, - port_num_mode_bits, - circuit_lib.model_name(circuit_model).c_str()); + if (port_num_mode_bits != + vpr_device_annotation.pb_type_mode_bits(cur_pb_type).size()) { + VTR_LOG_ERROR( + "Length of mode bits of pb_type '%s' does not match the size(%ld) of " + "mode selection ports of circuit model '%s'!\n", + cur_pb_type->name, port_num_mode_bits, + circuit_lib.model_name(circuit_model).c_str()); num_err++; } @@ -340,42 +383,49 @@ void rec_check_vpr_pb_type_mode_bits_annotation(t_pb_type* cur_pb_type, /* Traverse all the modes */ for (int imode = 0; imode < cur_pb_type->num_modes; ++imode) { - for (int ichild = 0; ichild < cur_pb_type->modes[imode].num_pb_type_children; ++ichild) { - rec_check_vpr_pb_type_mode_bits_annotation(&(cur_pb_type->modes[imode].pb_type_children[ichild]), - circuit_lib, vpr_device_annotation, - num_err); + for (int ichild = 0; + ichild < cur_pb_type->modes[imode].num_pb_type_children; ++ichild) { + rec_check_vpr_pb_type_mode_bits_annotation( + &(cur_pb_type->modes[imode].pb_type_children[ichild]), circuit_lib, + vpr_device_annotation, num_err); } } } /******************************************************************** - * This function will check the mode_bits annotation for each pb_type - * - If a primitive pb_type has mode bits, it must have been linked to a physical pb_type - * - If a primitive pb_type has mode bits, the circuit model must have - * a port for mode selection. And the port size must match the length of mode bits + * This function will check the mode_bits annotation for each pb_type + * - If a primitive pb_type has mode bits, it must have been linked to a + *physical pb_type + * - If a primitive pb_type has mode bits, the circuit model must have + * a port for mode selection. And the port size must match the length of mode + *bits * * Note: - * - This function should be run after circuit mode and mode bits annotation - * is completed + * - This function should be run after circuit mode and mode bits annotation + * is completed *******************************************************************/ -void check_vpr_pb_type_mode_bits_annotation(const DeviceContext& vpr_device_ctx, - const CircuitLibrary& circuit_lib, - const VprDeviceAnnotation& vpr_device_annotation) { +void check_vpr_pb_type_mode_bits_annotation( + const DeviceContext& vpr_device_ctx, const CircuitLibrary& circuit_lib, + const VprDeviceAnnotation& vpr_device_annotation) { size_t num_err = 0; - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_type head */ if (nullptr == lb_type.pb_type) { continue; } /* Top pb_type should always has a physical mode! */ - rec_check_vpr_pb_type_mode_bits_annotation(lb_type.pb_type, circuit_lib, vpr_device_annotation, num_err); + rec_check_vpr_pb_type_mode_bits_annotation(lb_type.pb_type, circuit_lib, + vpr_device_annotation, num_err); } if (0 == num_err) { VTR_LOG("Check pb_type annotation for mode selection bits passed.\n"); } else { - VTR_LOG_ERROR("Check physical pb_type annotation for mode selection bits failed with %ld errors!\n", - num_err); + VTR_LOG_ERROR( + "Check physical pb_type annotation for mode selection bits failed with " + "%ld errors!\n", + num_err); } } diff --git a/openfpga/src/annotation/check_pb_type_annotation.h b/openfpga/src/annotation/check_pb_type_annotation.h index 5183c5e10..44b98d09f 100644 --- a/openfpga/src/annotation/check_pb_type_annotation.h +++ b/openfpga/src/annotation/check_pb_type_annotation.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" #include "openfpga_context.h" +#include "vpr_context.h" #include "vpr_device_annotation.h" /******************************************************************** @@ -15,19 +15,21 @@ /* begin namespace openfpga */ namespace openfpga { -void check_vpr_physical_pb_mode_annotation(const DeviceContext& vpr_device_ctx, - const VprDeviceAnnotation& vpr_device_annotation); +void check_vpr_physical_pb_mode_annotation( + const DeviceContext& vpr_device_ctx, + const VprDeviceAnnotation& vpr_device_annotation); -void check_vpr_physical_pb_type_annotation(const DeviceContext& vpr_device_ctx, - const VprDeviceAnnotation& vpr_device_annotation); +void check_vpr_physical_pb_type_annotation( + const DeviceContext& vpr_device_ctx, + const VprDeviceAnnotation& vpr_device_annotation); -void check_vpr_pb_type_circuit_model_annotation(const DeviceContext& vpr_device_ctx, - const CircuitLibrary& circuit_lib, - const VprDeviceAnnotation& vpr_device_annotation); +void check_vpr_pb_type_circuit_model_annotation( + const DeviceContext& vpr_device_ctx, const CircuitLibrary& circuit_lib, + const VprDeviceAnnotation& vpr_device_annotation); -void check_vpr_pb_type_mode_bits_annotation(const DeviceContext& vpr_device_ctx, - const CircuitLibrary& circuit_lib, - const VprDeviceAnnotation& vpr_device_annotation); +void check_vpr_pb_type_mode_bits_annotation( + const DeviceContext& vpr_device_ctx, const CircuitLibrary& circuit_lib, + const VprDeviceAnnotation& vpr_device_annotation); } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/device_rr_gsb.cpp b/openfpga/src/annotation/device_rr_gsb.cpp index d9c33cbb6..341cd8993 100644 --- a/openfpga/src/annotation/device_rr_gsb.cpp +++ b/openfpga/src/annotation/device_rr_gsb.cpp @@ -1,11 +1,12 @@ /************************************************************************ * Member functions for class DeviceRRGSB ***********************************************************************/ -#include "vtr_log.h" -#include "vtr_assert.h" -#include "rr_gsb_utils.h" #include "device_rr_gsb.h" +#include "rr_gsb_utils.h" +#include "vtr_assert.h" +#include "vtr_log.h" + /* namespace openfpga begins */ namespace openfpga { @@ -13,8 +14,7 @@ namespace openfpga { * Constructors ***********************************************************************/ DeviceRRGSB::DeviceRRGSB(const VprDeviceAnnotation& device_annotation) - : device_annotation_(device_annotation) { -} + : device_annotation_(device_annotation) {} /************************************************************************ * Public accessors @@ -26,36 +26,36 @@ vtr::Point DeviceRRGSB::get_gsb_range() const { for (size_t x = 0; x < rr_gsb_.size(); ++x) { max_y = std::max(max_y, rr_gsb_[x].size()); } - + vtr::Point coordinate(rr_gsb_.size(), max_y); return coordinate; -} +} /* Get a rr switch block in the array with a coordinate */ const RRGSB& DeviceRRGSB::get_gsb(const vtr::Point& coordinate) const { VTR_ASSERT(validate_coordinate(coordinate)); return rr_gsb_[coordinate.x()][coordinate.y()]; -} +} /* Get a rr switch block in the array with a coordinate */ -const RRGSB& DeviceRRGSB::get_gsb(const size_t& x, const size_t& y) const { - vtr::Point coordinate(x, y); +const RRGSB& DeviceRRGSB::get_gsb(const size_t& x, const size_t& y) const { + vtr::Point coordinate(x, y); return get_gsb(coordinate); } /* 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)); - switch(cb_type) { - case CHANX: - return cbx_unique_module_.size(); - case CHANY: - return cby_unique_module_.size(); - default: - VTR_LOG_ERROR("Invalid type of connection block!\n"); - exit(1); + VTR_ASSERT(validate_cb_type(cb_type)); + switch (cb_type) { + case CHANX: + return cbx_unique_module_.size(); + case CHANY: + return cby_unique_module_.size(); + default: + VTR_LOG_ERROR("Invalid type of connection block!\n"); + exit(1); } -} +} /* Identify if a GSB actually exists at a location */ bool DeviceRRGSB::is_gsb_exist(const vtr::Point coord) const { @@ -83,76 +83,84 @@ bool DeviceRRGSB::is_gsb_exist(const vtr::Point coord) const { /* get the number of unique mirrors of switch blocks */ size_t DeviceRRGSB::get_num_sb_unique_module() const { return sb_unique_module_.size(); -} +} /* get the number of unique mirrors of switch blocks */ size_t DeviceRRGSB::get_num_gsb_unique_module() const { return gsb_unique_module_.size(); -} +} -/* Get a rr switch block which a unique mirror */ +/* Get a rr switch block which a unique mirror */ const RRGSB& DeviceRRGSB::get_gsb_unique_module(const size_t& index) const { - VTR_ASSERT (validate_gsb_unique_module_index(index)); - + VTR_ASSERT(validate_gsb_unique_module_index(index)); + return rr_gsb_[gsb_unique_module_[index].x()][gsb_unique_module_[index].y()]; } -/* Get a rr switch block which a unique mirror */ +/* Get a rr switch block which a unique mirror */ const RRGSB& DeviceRRGSB::get_sb_unique_module(const size_t& index) const { - VTR_ASSERT (validate_sb_unique_module_index(index)); - + VTR_ASSERT(validate_sb_unique_module_index(index)); + return rr_gsb_[sb_unique_module_[index].x()][sb_unique_module_[index].y()]; } -/* Get a rr switch block which a unique mirror */ -const RRGSB& DeviceRRGSB::get_cb_unique_module(const t_rr_type& cb_type, const size_t& index) const { - VTR_ASSERT (validate_cb_unique_module_index(cb_type, index)); - VTR_ASSERT (validate_cb_type(cb_type)); - switch(cb_type) { - case CHANX: - return rr_gsb_[cbx_unique_module_[index].x()][cbx_unique_module_[index].y()]; - case CHANY: - return rr_gsb_[cby_unique_module_[index].x()][cby_unique_module_[index].y()]; - default: - VTR_LOG_ERROR("Invalid type of connection block!\n"); - exit(1); - } +/* Get a rr switch block which a unique mirror */ +const RRGSB& DeviceRRGSB::get_cb_unique_module(const t_rr_type& cb_type, + const size_t& index) const { + VTR_ASSERT(validate_cb_unique_module_index(cb_type, index)); + VTR_ASSERT(validate_cb_type(cb_type)); + switch (cb_type) { + case CHANX: + return rr_gsb_[cbx_unique_module_[index].x()] + [cbx_unique_module_[index].y()]; + case CHANY: + return rr_gsb_[cby_unique_module_[index].x()] + [cby_unique_module_[index].y()]; + default: + VTR_LOG_ERROR("Invalid type of connection block!\n"); + exit(1); + } } -/* Give a coordinate of a rr switch block, and return its unique mirror */ -const RRGSB& DeviceRRGSB::get_cb_unique_module(const t_rr_type& cb_type, const vtr::Point& coordinate) const { +/* Give a coordinate of a rr switch block, and return its unique mirror */ +const RRGSB& DeviceRRGSB::get_cb_unique_module( + const t_rr_type& cb_type, const vtr::Point& coordinate) const { VTR_ASSERT(validate_cb_type(cb_type)); VTR_ASSERT(validate_coordinate(coordinate)); size_t cb_unique_module_id; - switch(cb_type) { - case CHANX: - cb_unique_module_id = cbx_unique_module_id_[coordinate.x()][coordinate.y()]; - break; - case CHANY: - cb_unique_module_id = cby_unique_module_id_[coordinate.x()][coordinate.y()]; - break; - default: - VTR_LOG_ERROR("Invalid type of connection block!\n"); - exit(1); - } + switch (cb_type) { + case CHANX: + cb_unique_module_id = + cbx_unique_module_id_[coordinate.x()][coordinate.y()]; + break; + case CHANY: + cb_unique_module_id = + cby_unique_module_id_[coordinate.x()][coordinate.y()]; + break; + default: + VTR_LOG_ERROR("Invalid type of connection block!\n"); + exit(1); + } return get_cb_unique_module(cb_type, cb_unique_module_id); -} +} -/* Give a coordinate of a rr switch block, and return its unique mirror */ -const RRGSB& DeviceRRGSB::get_sb_unique_module(const vtr::Point& coordinate) const { +/* Give a coordinate of a rr switch block, and return its unique mirror */ +const RRGSB& DeviceRRGSB::get_sb_unique_module( + const vtr::Point& coordinate) const { VTR_ASSERT(validate_coordinate(coordinate)); - size_t sb_unique_module_id = sb_unique_module_id_[coordinate.x()][coordinate.y()]; + size_t sb_unique_module_id = + sb_unique_module_id_[coordinate.x()][coordinate.y()]; return get_sb_unique_module(sb_unique_module_id); -} +} /************************************************************************ * Public mutators ***********************************************************************/ -/* Pre-allocate the rr_switch_block array that the device requires */ -void DeviceRRGSB::reserve(const vtr::Point& coordinate) { +/* Pre-allocate the rr_switch_block array that the device requires */ +void DeviceRRGSB::reserve(const vtr::Point& coordinate) { rr_gsb_.resize(coordinate.x()); gsb_unique_module_id_.resize(coordinate.x()); @@ -163,19 +171,19 @@ void DeviceRRGSB::reserve(const vtr::Point& coordinate) { cby_unique_module_id_.resize(coordinate.x()); for (size_t x = 0; x < coordinate.x(); ++x) { - rr_gsb_[x].resize(coordinate.y()); + rr_gsb_[x].resize(coordinate.y()); - gsb_unique_module_id_[x].resize(coordinate.y()); + gsb_unique_module_id_[x].resize(coordinate.y()); - sb_unique_module_id_[x].resize(coordinate.y()); + sb_unique_module_id_[x].resize(coordinate.y()); cbx_unique_module_id_[x].resize(coordinate.y()); - cby_unique_module_id_[x].resize(coordinate.y()); + cby_unique_module_id_[x].resize(coordinate.y()); } } /* Resize rr_switch_block array is needed*/ -void DeviceRRGSB::resize_upon_need(const vtr::Point& coordinate) { +void DeviceRRGSB::resize_upon_need(const vtr::Point& coordinate) { if (coordinate.x() + 1 > rr_gsb_.size()) { rr_gsb_.resize(coordinate.x() + 1); @@ -194,30 +202,33 @@ void DeviceRRGSB::resize_upon_need(const vtr::Point& coordinate) { } } -/* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ -void DeviceRRGSB::add_rr_gsb(const vtr::Point& coordinate, +/* Add a switch block to the array, which will automatically identify and update + * the lists of unique mirrors and rotatable mirrors */ +void DeviceRRGSB::add_rr_gsb(const vtr::Point& coordinate, const RRGSB& rr_gsb) { /* Resize upon needs*/ resize_upon_need(coordinate); /* Add the switch block into array */ - rr_gsb_[coordinate.x()][coordinate.y()] = rr_gsb; + rr_gsb_[coordinate.x()][coordinate.y()] = rr_gsb; } /* Get a rr switch block in the array with a coordinate */ RRGSB& DeviceRRGSB::get_mutable_gsb(const vtr::Point& coordinate) { VTR_ASSERT(validate_coordinate(coordinate)); return rr_gsb_[coordinate.x()][coordinate.y()]; -} +} /* Get a rr switch block in the array with a coordinate */ -RRGSB& DeviceRRGSB::get_mutable_gsb(const size_t& x, const size_t& y) { - vtr::Point coordinate(x, y); +RRGSB& DeviceRRGSB::get_mutable_gsb(const size_t& x, const size_t& y) { + vtr::Point coordinate(x, y); return get_mutable_gsb(coordinate); } -/* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ -void DeviceRRGSB::build_cb_unique_module(const RRGraphView& rr_graph, const t_rr_type& cb_type) { +/* Add a switch block to the array, which will automatically identify and update + * the lists of unique mirrors and rotatable mirrors */ +void DeviceRRGSB::build_cb_unique_module(const RRGraphView& rr_graph, + const t_rr_type& cb_type) { /* Make sure a clean start */ clear_cb_unique_module(cb_type); @@ -227,18 +238,19 @@ void DeviceRRGSB::build_cb_unique_module(const RRGraphView& rr_graph, const t_rr vtr::Point gsb_coordinate(ix, iy); /* Bypass non-exist CB */ - if ( false == rr_gsb_[ix][iy].is_cb_exist(cb_type) ) { + if (false == rr_gsb_[ix][iy].is_cb_exist(cb_type)) { continue; } /* Traverse the unique_mirror list and check it is an mirror of another */ for (size_t id = 0; id < get_num_cb_unique_module(cb_type); ++id) { const RRGSB& unique_module = get_cb_unique_module(cb_type, id); - if (true == is_cb_mirror(rr_graph, device_annotation_, rr_gsb_[ix][iy], unique_module, cb_type)) { + if (true == is_cb_mirror(rr_graph, device_annotation_, rr_gsb_[ix][iy], + unique_module, cb_type)) { /* This is a mirror, raise the flag and we finish */ is_unique_module = false; /* Record the id of unique mirror */ - set_cb_unique_module_id(cb_type, gsb_coordinate, id); + set_cb_unique_module_id(cb_type, gsb_coordinate, id); break; } } @@ -246,13 +258,15 @@ void DeviceRRGSB::build_cb_unique_module(const RRGraphView& rr_graph, const t_rr if (true == is_unique_module) { add_cb_unique_module(cb_type, gsb_coordinate); /* Record the id of unique mirror */ - set_cb_unique_module_id(cb_type, gsb_coordinate, get_num_cb_unique_module(cb_type) - 1); + set_cb_unique_module_id(cb_type, gsb_coordinate, + get_num_cb_unique_module(cb_type) - 1); } } - } + } } -/* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ +/* Add a switch block to the array, which will automatically identify and update + * the lists of unique mirrors and rotatable mirrors */ void DeviceRRGSB::build_sb_unique_module(const RRGraphView& rr_graph) { /* Make sure a clean start */ clear_sb_unique_module(); @@ -266,15 +280,16 @@ void DeviceRRGSB::build_sb_unique_module(const RRGraphView& rr_graph) { /* Traverse the unique_mirror list and check it is an mirror of another */ for (size_t id = 0; id < get_num_sb_unique_module(); ++id) { /* Check if the two modules have the same submodules, - * if so, these two modules are the same, indicating the sb is not unique. - * else the sb is unique + * if so, these two modules are the same, indicating the sb is not + * unique. else the sb is unique */ const RRGSB& unique_module = get_sb_unique_module(id); - if (true == is_sb_mirror(rr_graph, device_annotation_, rr_gsb_[ix][iy], unique_module)) { + if (true == is_sb_mirror(rr_graph, device_annotation_, rr_gsb_[ix][iy], + unique_module)) { /* This is a mirror, raise the flag and we finish */ is_unique_module = false; /* Record the id of unique mirror */ - sb_unique_module_id_[ix][iy] = id; + sb_unique_module_id_[ix][iy] = id; break; } } @@ -283,13 +298,14 @@ void DeviceRRGSB::build_sb_unique_module(const RRGraphView& rr_graph) { if (true == is_unique_module) { sb_unique_module_.push_back(sb_coordinate); /* Record the id of unique mirror */ - sb_unique_module_id_[ix][iy] = sb_unique_module_.size() - 1; + sb_unique_module_id_[ix][iy] = sb_unique_module_.size() - 1; } } - } + } } -/* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ +/* Add a switch block to the array, which will automatically identify and update + * the lists of unique mirrors and rotatable mirrors */ /* Find repeatable GSB block in the array */ void DeviceRRGSB::build_gsb_unique_module() { @@ -303,17 +319,25 @@ void DeviceRRGSB::build_gsb_unique_module() { /* Traverse the unique_mirror list and check it is an mirror of another */ for (size_t id = 0; id < get_num_gsb_unique_module(); ++id) { - /* We have alreay built sb and cb unique module list - * We just need to check if the unique module id of SBs, CBX and CBY are the same or not + /* We have alreay built sb and cb unique module list + * We just need to check if the unique module id of SBs, CBX and CBY are + * the same or not */ - const vtr::Point& gsb_unique_module_coordinate = gsb_unique_module_[id]; - if ((sb_unique_module_id_[ix][iy] == sb_unique_module_id_[gsb_unique_module_coordinate.x()][gsb_unique_module_coordinate.y()]) - && (cbx_unique_module_id_[ix][iy] == cbx_unique_module_id_[gsb_unique_module_coordinate.x()][gsb_unique_module_coordinate.y()]) - && (cby_unique_module_id_[ix][iy] == cby_unique_module_id_[gsb_unique_module_coordinate.x()][gsb_unique_module_coordinate.y()])) { + const vtr::Point& gsb_unique_module_coordinate = + gsb_unique_module_[id]; + if ((sb_unique_module_id_[ix][iy] == + sb_unique_module_id_[gsb_unique_module_coordinate.x()] + [gsb_unique_module_coordinate.y()]) && + (cbx_unique_module_id_[ix][iy] == + cbx_unique_module_id_[gsb_unique_module_coordinate.x()] + [gsb_unique_module_coordinate.y()]) && + (cby_unique_module_id_[ix][iy] == + cby_unique_module_id_[gsb_unique_module_coordinate.x()] + [gsb_unique_module_coordinate.y()])) { /* This is a mirror, raise the flag and we finish */ is_unique_module = false; /* Record the id of unique mirror */ - gsb_unique_module_id_[ix][iy] = id; + gsb_unique_module_id_[ix][iy] = id; break; } } @@ -324,7 +348,7 @@ void DeviceRRGSB::build_gsb_unique_module() { gsb_unique_module_id_[ix][iy] = get_num_gsb_unique_module() - 1; } } - } + } } void DeviceRRGSB::build_unique_module(const RRGraphView& rr_graph) { @@ -337,38 +361,41 @@ void DeviceRRGSB::build_unique_module(const RRGraphView& rr_graph) { } void DeviceRRGSB::add_gsb_unique_module(const vtr::Point& coordinate) { - gsb_unique_module_.push_back(coordinate); + gsb_unique_module_.push_back(coordinate); } -void DeviceRRGSB::add_cb_unique_module(const t_rr_type& cb_type, const vtr::Point& coordinate) { - VTR_ASSERT (validate_cb_type(cb_type)); - switch(cb_type) { - case CHANX: - cbx_unique_module_.push_back(coordinate); - return; - case CHANY: - cby_unique_module_.push_back(coordinate); - return; - default: - VTR_LOG_ERROR("Invalid type of connection block!\n"); - exit(1); +void DeviceRRGSB::add_cb_unique_module(const t_rr_type& cb_type, + const vtr::Point& coordinate) { + VTR_ASSERT(validate_cb_type(cb_type)); + switch (cb_type) { + case CHANX: + cbx_unique_module_.push_back(coordinate); + return; + case CHANY: + cby_unique_module_.push_back(coordinate); + return; + default: + VTR_LOG_ERROR("Invalid type of connection block!\n"); + exit(1); } } -void DeviceRRGSB::set_cb_unique_module_id(const t_rr_type& cb_type, const vtr::Point& coordinate, size_t id) { +void DeviceRRGSB::set_cb_unique_module_id(const t_rr_type& cb_type, + const vtr::Point& coordinate, + size_t id) { VTR_ASSERT(validate_cb_type(cb_type)); size_t x = coordinate.x(); size_t y = coordinate.y(); - switch(cb_type) { - case CHANX: - cbx_unique_module_id_[x][y] = id; - return; - case CHANY: - cby_unique_module_id_[x][y] = id; - return; - default: - VTR_LOG_ERROR("Invalid type of connection block!\n"); - exit(1); + switch (cb_type) { + case CHANX: + cbx_unique_module_id_[x][y] = id; + return; + case CHANY: + cby_unique_module_id_[x][y] = id; + return; + default: + VTR_LOG_ERROR("Invalid type of connection block!\n"); + exit(1); } } @@ -376,7 +403,7 @@ void DeviceRRGSB::set_cb_unique_module_id(const t_rr_type& cb_type, const vtr::P * Public clean-up functions: ***********************************************************************/ /* clean the content */ -void DeviceRRGSB::clear() { +void DeviceRRGSB::clear() { clear_gsb(); clear_gsb_unique_module(); @@ -396,7 +423,7 @@ void DeviceRRGSB::clear() { void DeviceRRGSB::clear_gsb() { /* clean gsb array */ for (size_t x = 0; x < rr_gsb_.size(); ++x) { - rr_gsb_[x].clear(); + rr_gsb_[x].clear(); } rr_gsb_.clear(); } @@ -404,33 +431,33 @@ void DeviceRRGSB::clear_gsb() { void DeviceRRGSB::clear_gsb_unique_module_id() { /* clean rr_switch_block array */ for (size_t x = 0; x < rr_gsb_.size(); ++x) { - gsb_unique_module_id_[x].clear(); + gsb_unique_module_id_[x].clear(); } } void DeviceRRGSB::clear_sb_unique_module_id() { /* clean rr_switch_block array */ for (size_t x = 0; x < rr_gsb_.size(); ++x) { - sb_unique_module_id_[x].clear(); + sb_unique_module_id_[x].clear(); } } void DeviceRRGSB::clear_cb_unique_module_id(const t_rr_type& cb_type) { - VTR_ASSERT (validate_cb_type(cb_type)); - switch(cb_type) { - case CHANX: - for (size_t x = 0; x < rr_gsb_.size(); ++x) { - cbx_unique_module_id_[x].clear(); - } - return; - case CHANY: - for (size_t x = 0; x < rr_gsb_.size(); ++x) { - cby_unique_module_id_[x].clear(); - } - return; - default: - VTR_LOG_ERROR("Invalid type of connection block!\n"); - exit(1); + VTR_ASSERT(validate_cb_type(cb_type)); + switch (cb_type) { + case CHANX: + for (size_t x = 0; x < rr_gsb_.size(); ++x) { + cbx_unique_module_id_[x].clear(); + } + return; + case CHANY: + for (size_t x = 0; x < rr_gsb_.size(); ++x) { + cby_unique_module_id_[x].clear(); + } + return; + default: + VTR_LOG_ERROR("Invalid type of connection block!\n"); + exit(1); } } @@ -438,26 +465,26 @@ void DeviceRRGSB::clear_cb_unique_module_id(const t_rr_type& cb_type) { void DeviceRRGSB::clear_gsb_unique_module() { /* clean unique mirror */ gsb_unique_module_.clear(); -} +} /* clean the content related to unique_mirrors */ void DeviceRRGSB::clear_sb_unique_module() { /* clean unique mirror */ sb_unique_module_.clear(); -} +} void DeviceRRGSB::clear_cb_unique_module(const t_rr_type& cb_type) { - VTR_ASSERT (validate_cb_type(cb_type)); - switch(cb_type) { - case CHANX: - cbx_unique_module_.clear(); - return; - case CHANY: - cby_unique_module_.clear(); - return; - default: - VTR_LOG_ERROR("Invalid type of connection block!\n"); - exit(1); + VTR_ASSERT(validate_cb_type(cb_type)); + switch (cb_type) { + case CHANX: + cbx_unique_module_.clear(); + return; + case CHANY: + cby_unique_module_.clear(); + return; + default: + VTR_LOG_ERROR("Invalid type of connection block!\n"); + exit(1); } } @@ -465,34 +492,36 @@ void DeviceRRGSB::clear_cb_unique_module(const t_rr_type& cb_type) { * Internal validators ***********************************************************************/ /* Validate if the (x,y) is the range of this device */ -bool DeviceRRGSB::validate_coordinate(const vtr::Point& coordinate) const { +bool DeviceRRGSB::validate_coordinate( + const vtr::Point& coordinate) const { if (coordinate.x() >= rr_gsb_.capacity()) { return false; } return (coordinate.y() < rr_gsb_[coordinate.x()].capacity()); -} +} /* Validate if the index in the range of unique_mirror vector*/ -bool DeviceRRGSB::validate_gsb_unique_module_index(const size_t& index) const { +bool DeviceRRGSB::validate_gsb_unique_module_index(const size_t& index) const { return (index < gsb_unique_module_.size()); } /* Validate if the index in the range of unique_mirror vector*/ -bool DeviceRRGSB::validate_sb_unique_module_index(const size_t& index) const { +bool DeviceRRGSB::validate_sb_unique_module_index(const size_t& index) const { return (index < sb_unique_module_.size()); } -bool DeviceRRGSB::validate_cb_unique_module_index(const t_rr_type& cb_type, const size_t& index) const { +bool DeviceRRGSB::validate_cb_unique_module_index(const t_rr_type& cb_type, + const size_t& index) const { VTR_ASSERT(validate_cb_type(cb_type)); - switch(cb_type) { - case CHANX: - return (index < cbx_unique_module_.size()); - case CHANY: - return (index < cby_unique_module_.size()); - default: - VTR_LOG_ERROR("Invalid type of connection block!\n"); - exit(1); - } + switch (cb_type) { + case CHANX: + return (index < cbx_unique_module_.size()); + case CHANY: + return (index < cby_unique_module_.size()); + default: + VTR_LOG_ERROR("Invalid type of connection block!\n"); + exit(1); + } return false; } diff --git a/openfpga/src/annotation/device_rr_gsb.h b/openfpga/src/annotation/device_rr_gsb.h index 6a19f45dd..0856486d2 100644 --- a/openfpga/src/annotation/device_rr_gsb.h +++ b/openfpga/src/annotation/device_rr_gsb.h @@ -9,7 +9,6 @@ /* Header files from vpr library */ #include "rr_graph_view.h" - #include "rr_gsb.h" #include "vpr_device_annotation.h" @@ -17,78 +16,142 @@ namespace openfpga { /******************************************************************** - * Object Device Routing Resource Switch Block + * Object Device Routing Resource Switch Block * This includes: - * 1. a collection of RRSwitch blocks, each of which can be used to instance Switch blocks in the top-level netlists - * 2. a collection of unique mirrors of RRGSBs, which can be used to output Verilog / SPICE modules - * 3. a colleciton of unique rotatable of RRGSBs, which can be used to output Verilog / SPICE modules - * The rotatable RRGSBs are more generic mirrors, which allow SwitchBlocks to be wired by rotating the pins, - * further reduce the number of Verilog/SPICE modules outputted. This will lead to rapid layout generation + * 1. a collection of RRSwitch blocks, each of which can be used to instance + *Switch blocks in the top-level netlists + * 2. a collection of unique mirrors of RRGSBs, which can be used to output + *Verilog / SPICE modules + * 3. a colleciton of unique rotatable of RRGSBs, which can be used to output + *Verilog / SPICE modules The rotatable RRGSBs are more generic mirrors, which + *allow SwitchBlocks to be wired by rotating the pins, further reduce the number + *of Verilog/SPICE modules outputted. This will lead to rapid layout generation *******************************************************************/ class DeviceRRGSB { - public: /* Contructors */ - DeviceRRGSB(const VprDeviceAnnotation& device_annotation); - public: /* Accessors */ - vtr::Point get_gsb_range() const; /* get the max coordinate of the switch block array */ - const RRGSB& get_gsb(const vtr::Point& coordinate) 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 */ - size_t get_num_gsb_unique_module() const; /* get the number of unique mirrors of GSB */ - size_t get_num_sb_unique_module() const; /* get the number of unique mirrors of switch blocks */ - const RRGSB& get_gsb_unique_module(const size_t& index) const; /* Get a rr-gsb which is a unique mirror */ - const RRGSB& get_sb_unique_module(const size_t& index) const; /* Get a rr switch block which a unique mirror */ - const RRGSB& get_sb_unique_module(const vtr::Point& coordinate) const; /* Get a rr switch block which a unique mirror */ - const RRGSB& get_cb_unique_module(const t_rr_type& cb_type, const size_t& index) const; /* Get a rr switch block which a unique mirror */ - const RRGSB& get_cb_unique_module(const t_rr_type& cb_type, const vtr::Point& coordinate) const; - size_t get_num_cb_unique_module(const t_rr_type& cb_type) const; /* get the number of unique mirrors of CBs */ - bool is_gsb_exist(const vtr::Point coord) const; - public: /* Mutators */ - void reserve(const vtr::Point& coordinate); /* Pre-allocate the rr_switch_block array that the device requires */ - void reserve_sb_unique_submodule_id(const vtr::Point& coordinate); /* Pre-allocate the rr_sb_unique_module_id matrix that the device requires */ - void resize_upon_need(const vtr::Point& coordinate); /* Resize the rr_switch_block array if needed */ - void add_rr_gsb(const vtr::Point& coordinate, const RRGSB& rr_gsb); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ - RRGSB& get_mutable_gsb(const vtr::Point& coordinate); /* Get a rr switch block in the array with a coordinate */ - RRGSB& get_mutable_gsb(const size_t& x, const size_t& y); /* Get a rr switch block in the array with a coordinate */ - void build_unique_module(const RRGraphView& rr_graph); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ - void clear(); /* clean the content */ - private: /* Internal cleaners */ - void clear_gsb(); /* clean the content */ - void clear_cb_unique_module(const t_rr_type& cb_type); /* clean the content */ - void clear_cb_unique_module_id(const t_rr_type& cb_type); /* clean the content */ - void clear_sb_unique_module(); /* clean the content */ - void clear_sb_unique_module_id(); /* clean the content */ - void clear_gsb_unique_module(); /* clean the content */ - void clear_gsb_unique_module_id(); /* clean the content */ - private: /* Validators */ - bool validate_coordinate(const vtr::Point& coordinate) const; /* Validate if the (x,y) is the range of this device */ - bool validate_side(const e_side& side) const; /* validate if side is in the range of unique_side_module_ */ - bool validate_gsb_unique_module_index(const size_t& index) const; /* Validate if the index in the range of unique_mirror vector*/ - bool validate_sb_unique_module_index(const size_t& index) const; /* Validate if the index in the range of unique_mirror vector*/ - bool validate_cb_unique_module_index(const t_rr_type& cb_type, const size_t& index) const; /* Validate if the index in the range of unique_mirror vector*/ - bool validate_cb_type(const t_rr_type& cb_type) const; - private: /* Internal builders */ - void add_gsb_unique_module(const vtr::Point& coordinate); - void add_cb_unique_module(const t_rr_type& cb_type, const vtr::Point& coordinate); - void set_cb_unique_module_id(const t_rr_type& cb_type, const vtr::Point& coordinate, size_t id); - void build_sb_unique_module(const RRGraphView& rr_graph); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ - void build_cb_unique_module(const RRGraphView& rr_graph, const t_rr_type& cb_type); /* Add a switch block to the array, which will automatically identify and update the lists of unique side module */ - void build_gsb_unique_module(); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ - private: /* Internal Data */ - std::vector> rr_gsb_; + public: /* Contructors */ + DeviceRRGSB(const VprDeviceAnnotation& device_annotation); - std::vector> gsb_unique_module_id_; /* A map from rr_gsb to its unique mirror */ - std::vector> gsb_unique_module_; + public: /* Accessors */ + vtr::Point get_gsb_range() + const; /* get the max coordinate of the switch block array */ + const RRGSB& get_gsb(const vtr::Point& coordinate) + 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 */ + size_t get_num_gsb_unique_module() + const; /* get the number of unique mirrors of GSB */ + size_t get_num_sb_unique_module() + const; /* get the number of unique mirrors of switch blocks */ + const RRGSB& get_gsb_unique_module( + const size_t& index) const; /* Get a rr-gsb which is a unique mirror */ + const RRGSB& get_sb_unique_module(const size_t& index) + const; /* Get a rr switch block which a unique mirror */ + const RRGSB& get_sb_unique_module(const vtr::Point& coordinate) + const; /* Get a rr switch block which a unique mirror */ + const RRGSB& get_cb_unique_module(const t_rr_type& cb_type, + const size_t& index) + const; /* Get a rr switch block which a unique mirror */ + const RRGSB& get_cb_unique_module(const t_rr_type& cb_type, + const vtr::Point& coordinate) const; + size_t get_num_cb_unique_module(const t_rr_type& cb_type) + const; /* get the number of unique mirrors of CBs */ + bool is_gsb_exist(const vtr::Point coord) const; - std::vector> sb_unique_module_id_; /* A map from rr_gsb to its unique mirror */ - std::vector> sb_unique_module_; + public: /* Mutators */ + void reserve( + const vtr::Point& coordinate); /* Pre-allocate the rr_switch_block + array that the device requires */ + void reserve_sb_unique_submodule_id( + const vtr::Point& + coordinate); /* Pre-allocate the rr_sb_unique_module_id matrix that the + device requires */ + void resize_upon_need( + const vtr::Point& + coordinate); /* Resize the rr_switch_block array if needed */ + void add_rr_gsb( + const vtr::Point& coordinate, + const RRGSB& rr_gsb); /* Add a switch block to the array, which will + automatically identify and update the lists of + unique mirrors and rotatable mirrors */ + RRGSB& get_mutable_gsb( + const vtr::Point& + coordinate); /* Get a rr switch block in the array with a coordinate */ + RRGSB& get_mutable_gsb( + const size_t& x, + const size_t& y); /* Get a rr switch block in the array with a coordinate */ + void build_unique_module( + const RRGraphView& rr_graph); /* Add a switch block to the array, which will + automatically identify and update the lists + of unique mirrors and rotatable mirrors */ + void clear(); /* clean the content */ + private: /* Internal cleaners */ + void clear_gsb(); /* clean the content */ + void clear_cb_unique_module(const t_rr_type& cb_type); /* clean the content */ + void clear_cb_unique_module_id( + const t_rr_type& cb_type); /* clean the content */ + void clear_sb_unique_module(); /* clean the content */ + void clear_sb_unique_module_id(); /* clean the content */ + void clear_gsb_unique_module(); /* clean the content */ + void clear_gsb_unique_module_id(); /* clean the content */ + private: /* Validators */ + bool validate_coordinate(const vtr::Point& coordinate) + const; /* Validate if the (x,y) is the range of this device */ + bool validate_side(const e_side& side) + const; /* validate if side is in the range of unique_side_module_ */ + bool validate_gsb_unique_module_index(const size_t& index) + const; /* Validate if the index in the range of unique_mirror vector*/ + bool validate_sb_unique_module_index(const size_t& index) + const; /* Validate if the index in the range of unique_mirror vector*/ + bool validate_cb_unique_module_index(const t_rr_type& cb_type, + const size_t& index) + const; /* Validate if the index in the range of unique_mirror vector*/ + bool validate_cb_type(const t_rr_type& cb_type) const; - std::vector> cbx_unique_module_id_; /* A map from rr_gsb to its unique mirror */ - std::vector> cbx_unique_module_; /* For each side of connection block, we identify a list of unique modules based on its connection. This is a matrix [0..num_module] */ + private: /* Internal builders */ + void add_gsb_unique_module(const vtr::Point& coordinate); + void add_cb_unique_module(const t_rr_type& cb_type, + const vtr::Point& coordinate); + void set_cb_unique_module_id(const t_rr_type& cb_type, + const vtr::Point& coordinate, size_t id); + void build_sb_unique_module( + const RRGraphView& rr_graph); /* Add a switch block to the array, which will + automatically identify and update the lists + of unique mirrors and rotatable mirrors */ + void build_cb_unique_module( + const RRGraphView& rr_graph, + const t_rr_type& + cb_type); /* Add a switch block to the array, which will automatically + identify and update the lists of unique side module */ + void build_gsb_unique_module(); /* Add a switch block to the array, which will + automatically identify and update the lists + of unique mirrors and rotatable mirrors */ + private: /* Internal Data */ + std::vector> rr_gsb_; - std::vector> cby_unique_module_id_; /* A map from rr_gsb to its unique mirror */ - std::vector> cby_unique_module_; /* For each side of connection block, we identify a list of unique modules based on its connection. This is a matrix [0..num_module] */ + std::vector> + gsb_unique_module_id_; /* A map from rr_gsb to its unique mirror */ + std::vector> gsb_unique_module_; - /* Cached data */ - const VprDeviceAnnotation& device_annotation_; + std::vector> + sb_unique_module_id_; /* A map from rr_gsb to its unique mirror */ + std::vector> sb_unique_module_; + + std::vector> + cbx_unique_module_id_; /* A map from rr_gsb to its unique mirror */ + std::vector> + cbx_unique_module_; /* For each side of connection block, we identify a list + of unique modules based on its connection. This is a + matrix [0..num_module] */ + + std::vector> + cby_unique_module_id_; /* A map from rr_gsb to its unique mirror */ + std::vector> + cby_unique_module_; /* For each side of connection block, we identify a list + of unique modules based on its connection. This is a + matrix [0..num_module] */ + + /* Cached data */ + const VprDeviceAnnotation& device_annotation_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/openfpga_annotate_routing.cpp b/openfpga/src/annotation/openfpga_annotate_routing.cpp index 144c1e0b4..577106359 100644 --- a/openfpga/src/annotation/openfpga_annotate_routing.cpp +++ b/openfpga/src/annotation/openfpga_annotate_routing.cpp @@ -3,33 +3,35 @@ * from VPR to OpenFPGA *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_assert.h" -#include "vtr_log.h" +#include "openfpga_annotate_routing.h" #include "annotate_routing.h" -#include "openfpga_annotate_routing.h" +#include "vtr_assert.h" +#include "vtr_log.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * Create a mapping between each rr_node and its mapped nets + * Create a mapping between each rr_node and its mapped nets * based on VPR routing results - * - Unmapped rr_node will use invalid ids + * - Unmapped rr_node will use invalid ids *******************************************************************/ void annotate_vpr_rr_node_nets(const DeviceContext& device_ctx, const ClusteringContext& clustering_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); - 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)]); + vtr::vector node2net = annotate_rr_node_nets( + device_ctx, clustering_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)]); } VTR_LOG("Loaded node-to-net mapping\n"); } - /******************************************************************** * This function will find a previous node for a given rr_node * from the routing traces @@ -38,16 +40,16 @@ void annotate_vpr_rr_node_nets(const DeviceContext& device_ctx, * Try to validate a candidate by searching it from driving node list * If not validated, try to find a right one in the routing traces *******************************************************************/ -static -RRNodeId find_previous_node_from_routing_traces(const RRGraphView& rr_graph, - t_trace* routing_trace_head, - const RRNodeId& prev_node_candidate, - const RRNodeId& cur_rr_node) { +static RRNodeId find_previous_node_from_routing_traces( + const RRGraphView& rr_graph, t_trace* routing_trace_head, + const RRNodeId& prev_node_candidate, const RRNodeId& cur_rr_node) { RRNodeId prev_node = prev_node_candidate; - /* For a valid prev_node, ensure prev node is one of the driving nodes for this rr_node! */ + /* For a valid prev_node, ensure prev node is one of the driving nodes for + * this rr_node! */ if (prev_node) { - /* Try to spot the previous node in the incoming node list of this rr_node */ + /* Try to spot the previous node in the incoming node list of this rr_node + */ bool valid_prev_node = false; for (const RREdgeId& in_edge : rr_graph.node_in_edges(cur_rr_node)) { if (prev_node == rr_graph.edge_src_node(in_edge)) { @@ -61,7 +63,7 @@ RRNodeId find_previous_node_from_routing_traces(const RRGraphView& rr_graph, return prev_node; } - /* If we cannot find one, it could be possible that this rr_node branches + /* If we cannot find one, it could be possible that this rr_node branches * from an earlier point in the routing tree * * +----- ... --->prev_node @@ -70,12 +72,12 @@ RRNodeId find_previous_node_from_routing_traces(const RRGraphView& rr_graph, * | * +-----+ rr_node * - * Our job now is to start from the head of the traces and find the prev_node - * that drives this rr_node + * Our job now is to start from the head of the traces and find the + * prev_node that drives this rr_node * * This search will find the first-fit and finish. - * This is reasonable because if there is a second-fit, it should be a longer path - * which should be considered in routing optimization + * This is reasonable because if there is a second-fit, it should be a + * longer path which should be considered in routing optimization */ if (false == valid_prev_node) { t_trace* tptr = routing_trace_head; @@ -88,7 +90,7 @@ RRNodeId find_previous_node_from_routing_traces(const RRGraphView& rr_graph, break; } } - + if (true == is_good_cand) { /* Update prev_node */ prev_node = cand_prev_node; @@ -98,10 +100,10 @@ RRNodeId find_previous_node_from_routing_traces(const RRGraphView& rr_graph, /* Move on to the next */ tptr = tptr->next; } - } + } } - return prev_node; + return prev_node; } /******************************************************************** @@ -109,15 +111,14 @@ RRNodeId find_previous_node_from_routing_traces(const RRGraphView& rr_graph, * based on VPR routing results * - Unmapped rr_node will have an invalid id of previous rr_node *******************************************************************/ -void annotate_rr_node_previous_nodes(const DeviceContext& device_ctx, - const ClusteringContext& clustering_ctx, - const RoutingContext& routing_ctx, - VprRoutingAnnotation& vpr_routing_annotation, - const bool& verbose) { +void annotate_rr_node_previous_nodes( + const DeviceContext& device_ctx, const ClusteringContext& clustering_ctx, + const RoutingContext& routing_ctx, + VprRoutingAnnotation& vpr_routing_annotation, const bool& verbose) { size_t counter = 0; VTR_LOG("Annotating previous nodes for rr_node..."); VTR_LOGV(verbose, "\n"); - + for (auto net_id : clustering_ctx.clb_nlist.nets()) { /* Ignore nets that are not routed */ if (true == clustering_ctx.clb_nlist.net_is_ignored(net_id)) { @@ -127,7 +128,7 @@ void annotate_rr_node_previous_nodes(const DeviceContext& device_ctx, if (false == clustering_ctx.clb_nlist.net_sinks(net_id).size()) { continue; } - + /* Cache Previous nodes */ RRNodeId prev_node = RRNodeId::INVALID(); @@ -136,14 +137,14 @@ void annotate_rr_node_previous_nodes(const DeviceContext& device_ctx, RRNodeId rr_node = RRNodeId(tptr->index); /* Find the right previous node */ - prev_node = find_previous_node_from_routing_traces(device_ctx.rr_graph, - routing_ctx.trace[net_id].head, - prev_node, - rr_node); + prev_node = find_previous_node_from_routing_traces( + device_ctx.rr_graph, routing_ctx.trace[net_id].head, prev_node, + rr_node); /* Only update mapped nodes */ if (prev_node) { - vpr_routing_annotation.set_rr_node_prev_node(device_ctx.rr_graph, rr_node, prev_node); + vpr_routing_annotation.set_rr_node_prev_node(device_ctx.rr_graph, + rr_node, prev_node); counter++; } @@ -159,4 +160,3 @@ void annotate_rr_node_previous_nodes(const DeviceContext& device_ctx, } } /* end namespace openfpga */ - diff --git a/openfpga/src/annotation/openfpga_annotate_routing.h b/openfpga/src/annotation/openfpga_annotate_routing.h index d03a0a6fc..aa79e69d5 100644 --- a/openfpga/src/annotation/openfpga_annotate_routing.h +++ b/openfpga/src/annotation/openfpga_annotate_routing.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" #include "openfpga_context.h" +#include "vpr_context.h" #include "vpr_routing_annotation.h" /******************************************************************** @@ -21,11 +21,10 @@ void annotate_vpr_rr_node_nets(const DeviceContext& device_ctx, VprRoutingAnnotation& vpr_routing_annotation, const bool& verbose); -void annotate_rr_node_previous_nodes(const DeviceContext& device_ctx, - const ClusteringContext& clustering_ctx, - const RoutingContext& routing_ctx, - VprRoutingAnnotation& vpr_routing_annotation, - const bool& verbose); +void annotate_rr_node_previous_nodes( + const DeviceContext& device_ctx, const ClusteringContext& clustering_ctx, + const RoutingContext& routing_ctx, + VprRoutingAnnotation& vpr_routing_annotation, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/rr_gsb_writer_option.cpp b/openfpga/src/annotation/rr_gsb_writer_option.cpp index dd4f77577..4c2de351d 100644 --- a/openfpga/src/annotation/rr_gsb_writer_option.cpp +++ b/openfpga/src/annotation/rr_gsb_writer_option.cpp @@ -1,14 +1,15 @@ /****************************************************************************** * Memember functions for data structure RRGSBWriterOption ******************************************************************************/ -#include +#include "rr_gsb_writer_option.h" + #include +#include + +#include "openfpga_tokenizer.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "rr_gsb_writer_option.h" -#include "openfpga_tokenizer.h" - /* begin namespace openfpga */ namespace openfpga { @@ -25,7 +26,7 @@ RRGSBWriterOption::RRGSBWriterOption() { } /************************************************** - * Public Accessors + * Public Accessors *************************************************/ std::string RRGSBWriterOption::output_directory() const { return output_directory_; @@ -35,9 +36,7 @@ bool RRGSBWriterOption::unique_module_only() const { return unique_module_only_; } -bool RRGSBWriterOption::include_rr_info() const { - return !exclude_content_[0]; -} +bool RRGSBWriterOption::include_rr_info() const { return !exclude_content_[0]; } bool RRGSBWriterOption::include_cb_content(const t_rr_type& cb_type) const { if (cb_type == CHANX) { @@ -55,9 +54,7 @@ std::vector RRGSBWriterOption::include_gsb_names() const { return include_gsb_names_; } -bool RRGSBWriterOption::verbose_output() const { - return verbose_output_; -} +bool RRGSBWriterOption::verbose_output() const { return verbose_output_; } /****************************************************************************** * Private Mutators @@ -80,7 +77,7 @@ void RRGSBWriterOption::set_exclude_content(const std::string& content) { StringToken tokenizer(content); std::vector tokens = tokenizer.split(','); /* Parse each token */ - std::map token2index = { {"sb", 3}, {"cbx", 1}, {"cby", 2} }; + std::map token2index = {{"sb", 3}, {"cbx", 1}, {"cby", 2}}; for (std::string token : tokens) { auto result = token2index.find(token); if (result == token2index.end()) { @@ -90,7 +87,9 @@ void RRGSBWriterOption::set_exclude_content(const std::string& content) { keyword_list += pair.first + "|"; } keyword_list.pop_back(); - std::string err_msg = std::string("Invalid content '") + token + std::string("' to skip, expect [ ") + keyword_list + std::string(" ]"); + std::string err_msg = std::string("Invalid content '") + token + + std::string("' to skip, expect [ ") + keyword_list + + std::string(" ]"); VTR_LOG_ERROR(err_msg.c_str()); num_parse_errors_++; continue; @@ -113,7 +112,7 @@ void RRGSBWriterOption::set_verbose_output(const bool& enabled) { bool RRGSBWriterOption::valid() const { if (output_directory_.empty()) { return false; - } + } if (num_parse_errors_) { return false; } diff --git a/openfpga/src/annotation/rr_gsb_writer_option.h b/openfpga/src/annotation/rr_gsb_writer_option.h index 239f0432a..40ddfe1b0 100644 --- a/openfpga/src/annotation/rr_gsb_writer_option.h +++ b/openfpga/src/annotation/rr_gsb_writer_option.h @@ -6,6 +6,7 @@ *******************************************************************/ #include #include + #include "rr_node_types.h" /* Begin namespace openfpga */ @@ -15,51 +16,55 @@ namespace openfpga { * Options for RRGSB writer *******************************************************************/ class RRGSBWriterOption { - public: /* Public constructor */ - /* Set default options */ - RRGSBWriterOption(); - public: /* Public accessors */ - std::string output_directory() const; - bool unique_module_only() const; - bool include_rr_info() const; - bool include_cb_content(const t_rr_type& cb_type) const; - bool include_sb_content() const; - std::vector include_gsb_names() const; - bool verbose_output() const; - public: /* Public mutators */ - void set_output_directory(const std::string& output_dir); - void set_unique_module_only(const bool& enabled); - void set_exclude_rr_info(const bool& enabled); - /* Parse the string which contains the content to be excluded - * Accepted string format is [sb|cbx|cby] - * Allow the use ',' as splitter - * For example: sb,cby - */ - void set_exclude_content(const std::string& content); - void set_include_gsb_names(const std::string& gsb_names); - void set_verbose_output(const bool& enabled); - public: /* Public validators */ - /* Check if the following internal data is valid or not: - * - output directory is assigned - * - no parsing errors - */ - bool valid() const; - private: /* Internal Data */ - std::string output_directory_; - bool unique_module_only_; - /* Flags to mark what content to be skipped when outputting: - * 0 : rr_info - * 1 : cbx - * 2 : cby - * 3 : sb - */ - std::array exclude_content_; + public: /* Public constructor */ + /* Set default options */ + RRGSBWriterOption(); - std::vector include_gsb_names_; - bool verbose_output_; + public: /* Public accessors */ + std::string output_directory() const; + bool unique_module_only() const; + bool include_rr_info() const; + bool include_cb_content(const t_rr_type& cb_type) const; + bool include_sb_content() const; + std::vector include_gsb_names() const; + bool verbose_output() const; - /* A flag to indicate if the data parse is invalid or not */ - int num_parse_errors_; + public: /* Public mutators */ + void set_output_directory(const std::string& output_dir); + void set_unique_module_only(const bool& enabled); + void set_exclude_rr_info(const bool& enabled); + /* Parse the string which contains the content to be excluded + * Accepted string format is [sb|cbx|cby] + * Allow the use ',' as splitter + * For example: sb,cby + */ + void set_exclude_content(const std::string& content); + void set_include_gsb_names(const std::string& gsb_names); + void set_verbose_output(const bool& enabled); + + public: /* Public validators */ + /* Check if the following internal data is valid or not: + * - output directory is assigned + * - no parsing errors + */ + bool valid() const; + + private: /* Internal Data */ + std::string output_directory_; + bool unique_module_only_; + /* Flags to mark what content to be skipped when outputting: + * 0 : rr_info + * 1 : cbx + * 2 : cby + * 3 : sb + */ + std::array exclude_content_; + + std::vector include_gsb_names_; + bool verbose_output_; + + /* A flag to indicate if the data parse is invalid or not */ + int num_parse_errors_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/vpr_bitstream_annotation.cpp b/openfpga/src/annotation/vpr_bitstream_annotation.cpp index 38842cbff..1f7c47cff 100644 --- a/openfpga/src/annotation/vpr_bitstream_annotation.cpp +++ b/openfpga/src/annotation/vpr_bitstream_annotation.cpp @@ -1,10 +1,11 @@ /************************************************************************ * Member functions for class VprBitstreamAnnotation ***********************************************************************/ -#include "vtr_log.h" -#include "vtr_assert.h" #include "vpr_bitstream_annotation.h" + #include "mux_bitstream_constants.h" +#include "vtr_assert.h" +#include "vtr_log.h" /* namespace openfpga begins */ namespace openfpga { @@ -12,14 +13,13 @@ namespace openfpga { /************************************************************************ * Constructors ***********************************************************************/ -VprBitstreamAnnotation::VprBitstreamAnnotation() { - return; -} +VprBitstreamAnnotation::VprBitstreamAnnotation() { return; } /************************************************************************ * Public accessors ***********************************************************************/ -VprBitstreamAnnotation::e_bitstream_source_type VprBitstreamAnnotation::pb_type_bitstream_source(t_pb_type* pb_type) const { +VprBitstreamAnnotation::e_bitstream_source_type +VprBitstreamAnnotation::pb_type_bitstream_source(t_pb_type* pb_type) const { auto result = bitstream_sources_.find(pb_type); if (result != bitstream_sources_.end()) { return result->second; @@ -29,7 +29,8 @@ VprBitstreamAnnotation::e_bitstream_source_type VprBitstreamAnnotation::pb_type_ return NUM_BITSTREAM_SOURCE_TYPES; } -std::string VprBitstreamAnnotation::pb_type_bitstream_content(t_pb_type* pb_type) const { +std::string VprBitstreamAnnotation::pb_type_bitstream_content( + t_pb_type* pb_type) const { auto result = bitstream_contents_.find(pb_type); if (result != bitstream_contents_.end()) { return result->second; @@ -39,7 +40,8 @@ std::string VprBitstreamAnnotation::pb_type_bitstream_content(t_pb_type* pb_type return std::string(); } -size_t VprBitstreamAnnotation::pb_type_bitstream_offset(t_pb_type* pb_type) const { +size_t VprBitstreamAnnotation::pb_type_bitstream_offset( + t_pb_type* pb_type) const { auto result = bitstream_offsets_.find(pb_type); if (result != bitstream_offsets_.end()) { return result->second; @@ -49,7 +51,9 @@ size_t VprBitstreamAnnotation::pb_type_bitstream_offset(t_pb_type* pb_type) cons return 0; } -VprBitstreamAnnotation::e_bitstream_source_type VprBitstreamAnnotation::pb_type_mode_select_bitstream_source(t_pb_type* pb_type) const { +VprBitstreamAnnotation::e_bitstream_source_type +VprBitstreamAnnotation::pb_type_mode_select_bitstream_source( + t_pb_type* pb_type) const { auto result = mode_select_bitstream_sources_.find(pb_type); if (result != mode_select_bitstream_sources_.end()) { return result->second; @@ -59,7 +63,8 @@ VprBitstreamAnnotation::e_bitstream_source_type VprBitstreamAnnotation::pb_type_ return NUM_BITSTREAM_SOURCE_TYPES; } -std::string VprBitstreamAnnotation::pb_type_mode_select_bitstream_content(t_pb_type* pb_type) const { +std::string VprBitstreamAnnotation::pb_type_mode_select_bitstream_content( + t_pb_type* pb_type) const { auto result = mode_select_bitstream_contents_.find(pb_type); if (result != mode_select_bitstream_contents_.end()) { return result->second; @@ -69,7 +74,8 @@ std::string VprBitstreamAnnotation::pb_type_mode_select_bitstream_content(t_pb_t return std::string(); } -size_t VprBitstreamAnnotation::pb_type_mode_select_bitstream_offset(t_pb_type* pb_type) const { +size_t VprBitstreamAnnotation::pb_type_mode_select_bitstream_offset( + t_pb_type* pb_type) const { auto result = mode_select_bitstream_offsets_.find(pb_type); if (result != mode_select_bitstream_offsets_.end()) { return result->second; @@ -79,7 +85,8 @@ size_t VprBitstreamAnnotation::pb_type_mode_select_bitstream_offset(t_pb_type* p return 0; } -size_t VprBitstreamAnnotation::interconnect_default_path_id(t_interconnect* interconnect) const { +size_t VprBitstreamAnnotation::interconnect_default_path_id( + t_interconnect* interconnect) const { auto result = interconnect_default_path_ids_.find(interconnect); if (result != interconnect_default_path_ids_.end()) { return result->second; @@ -92,38 +99,38 @@ size_t VprBitstreamAnnotation::interconnect_default_path_id(t_interconnect* inte /************************************************************************ * Public mutators ***********************************************************************/ -void VprBitstreamAnnotation::set_pb_type_bitstream_source(t_pb_type* pb_type, - const e_bitstream_source_type& bitstream_source) { - bitstream_sources_[pb_type] = bitstream_source; +void VprBitstreamAnnotation::set_pb_type_bitstream_source( + t_pb_type* pb_type, const e_bitstream_source_type& bitstream_source) { + bitstream_sources_[pb_type] = bitstream_source; } -void VprBitstreamAnnotation::set_pb_type_bitstream_content(t_pb_type* pb_type, - const std::string& bitstream_content) { - bitstream_contents_[pb_type] = bitstream_content; +void VprBitstreamAnnotation::set_pb_type_bitstream_content( + t_pb_type* pb_type, const std::string& bitstream_content) { + bitstream_contents_[pb_type] = bitstream_content; } -void VprBitstreamAnnotation::set_pb_type_bitstream_offset(t_pb_type* pb_type, - const size_t& offset) { - bitstream_offsets_[pb_type] = offset; +void VprBitstreamAnnotation::set_pb_type_bitstream_offset( + t_pb_type* pb_type, const size_t& offset) { + bitstream_offsets_[pb_type] = offset; } -void VprBitstreamAnnotation::set_pb_type_mode_select_bitstream_source(t_pb_type* pb_type, - const e_bitstream_source_type& bitstream_source) { - mode_select_bitstream_sources_[pb_type] = bitstream_source; +void VprBitstreamAnnotation::set_pb_type_mode_select_bitstream_source( + t_pb_type* pb_type, const e_bitstream_source_type& bitstream_source) { + mode_select_bitstream_sources_[pb_type] = bitstream_source; } -void VprBitstreamAnnotation::set_pb_type_mode_select_bitstream_content(t_pb_type* pb_type, - const std::string& bitstream_content) { - mode_select_bitstream_contents_[pb_type] = bitstream_content; +void VprBitstreamAnnotation::set_pb_type_mode_select_bitstream_content( + t_pb_type* pb_type, const std::string& bitstream_content) { + mode_select_bitstream_contents_[pb_type] = bitstream_content; } -void VprBitstreamAnnotation::set_pb_type_mode_select_bitstream_offset(t_pb_type* pb_type, - const size_t& offset) { - mode_select_bitstream_offsets_[pb_type] = offset; +void VprBitstreamAnnotation::set_pb_type_mode_select_bitstream_offset( + t_pb_type* pb_type, const size_t& offset) { + mode_select_bitstream_offsets_[pb_type] = offset; } -void VprBitstreamAnnotation::set_interconnect_default_path_id(t_interconnect* interconnect, - const size_t& default_path_id) { +void VprBitstreamAnnotation::set_interconnect_default_path_id( + t_interconnect* interconnect, const size_t& default_path_id) { interconnect_default_path_ids_[interconnect] = default_path_id; } diff --git a/openfpga/src/annotation/vpr_bitstream_annotation.h b/openfpga/src/annotation/vpr_bitstream_annotation.h index 134530f25..6d99d60e9 100644 --- a/openfpga/src/annotation/vpr_bitstream_annotation.h +++ b/openfpga/src/annotation/vpr_bitstream_annotation.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files required by the data structure definition *******************************************************************/ -#include -#include +#include +#include /* Header from vpr library */ #include "vpr_context.h" @@ -23,60 +23,64 @@ namespace openfpga { * or an attribute line in the .eblif file *******************************************************************/ class VprBitstreamAnnotation { - public: /* Type */ - enum e_bitstream_source_type { - BITSTREAM_SOURCE_EBLIF, - NUM_BITSTREAM_SOURCE_TYPES - }; - public: /* Constructor */ - VprBitstreamAnnotation(); - public: /* Public accessors */ - e_bitstream_source_type pb_type_bitstream_source(t_pb_type* pb_type) const; - std::string pb_type_bitstream_content(t_pb_type* pb_type) const; - size_t pb_type_bitstream_offset(t_pb_type* pb_type) const; + public: /* Type */ + enum e_bitstream_source_type { + BITSTREAM_SOURCE_EBLIF, + NUM_BITSTREAM_SOURCE_TYPES + }; - e_bitstream_source_type pb_type_mode_select_bitstream_source(t_pb_type* pb_type) const; - std::string pb_type_mode_select_bitstream_content(t_pb_type* pb_type) const; - size_t pb_type_mode_select_bitstream_offset(t_pb_type* pb_type) const; - size_t interconnect_default_path_id(t_interconnect* interconnect) const; - public: /* Public mutators */ - void set_pb_type_bitstream_source(t_pb_type* pb_type, - const e_bitstream_source_type& bitstream_source); - void set_pb_type_bitstream_content(t_pb_type* pb_type, - const std::string& bitstream_content); - void set_pb_type_bitstream_offset(t_pb_type* pb_type, - const size_t& offset); + public: /* Constructor */ + VprBitstreamAnnotation(); - void set_pb_type_mode_select_bitstream_source(t_pb_type* pb_type, - const e_bitstream_source_type& bitstream_source); - void set_pb_type_mode_select_bitstream_content(t_pb_type* pb_type, - const std::string& bitstream_content); - void set_pb_type_mode_select_bitstream_offset(t_pb_type* pb_type, - const size_t& offset); - void set_interconnect_default_path_id(t_interconnect* interconnect, - const size_t& default_path_id); - private: /* Internal data */ - /* For regular bitstreams */ - /* A look up for pb type to find bitstream source type */ - std::map bitstream_sources_; - /* Binding from pb type to bitstream content */ - std::map bitstream_contents_; - /* Offset to be applied to bitstream */ - std::map bitstream_offsets_; + public: /* Public accessors */ + e_bitstream_source_type pb_type_bitstream_source(t_pb_type* pb_type) const; + std::string pb_type_bitstream_content(t_pb_type* pb_type) const; + size_t pb_type_bitstream_offset(t_pb_type* pb_type) const; - /* For mode-select bitstreams */ - /* A look up for pb type to find bitstream source type */ - std::map mode_select_bitstream_sources_; - /* Binding from pb type to bitstream content */ - std::map mode_select_bitstream_contents_; - /* Offset to be applied to mode-select bitstream */ - std::map mode_select_bitstream_offsets_; + e_bitstream_source_type pb_type_mode_select_bitstream_source( + t_pb_type* pb_type) const; + std::string pb_type_mode_select_bitstream_content(t_pb_type* pb_type) const; + size_t pb_type_mode_select_bitstream_offset(t_pb_type* pb_type) const; + size_t interconnect_default_path_id(t_interconnect* interconnect) const; - /* A look up for interconnect to find default path indices - * Note: this is different from the default path in bitstream setting which is the index - * of inputs in the context of the interconnect input string - */ - std::map interconnect_default_path_ids_; + public: /* Public mutators */ + void set_pb_type_bitstream_source( + t_pb_type* pb_type, const e_bitstream_source_type& bitstream_source); + void set_pb_type_bitstream_content(t_pb_type* pb_type, + const std::string& bitstream_content); + void set_pb_type_bitstream_offset(t_pb_type* pb_type, const size_t& offset); + + void set_pb_type_mode_select_bitstream_source( + t_pb_type* pb_type, const e_bitstream_source_type& bitstream_source); + void set_pb_type_mode_select_bitstream_content( + t_pb_type* pb_type, const std::string& bitstream_content); + void set_pb_type_mode_select_bitstream_offset(t_pb_type* pb_type, + const size_t& offset); + void set_interconnect_default_path_id(t_interconnect* interconnect, + const size_t& default_path_id); + + private: /* Internal data */ + /* For regular bitstreams */ + /* A look up for pb type to find bitstream source type */ + std::map bitstream_sources_; + /* Binding from pb type to bitstream content */ + std::map bitstream_contents_; + /* Offset to be applied to bitstream */ + std::map bitstream_offsets_; + + /* For mode-select bitstreams */ + /* A look up for pb type to find bitstream source type */ + std::map mode_select_bitstream_sources_; + /* Binding from pb type to bitstream content */ + std::map mode_select_bitstream_contents_; + /* Offset to be applied to mode-select bitstream */ + std::map mode_select_bitstream_offsets_; + + /* A look up for interconnect to find default path indices + * Note: this is different from the default path in bitstream setting which is + * the index of inputs in the context of the interconnect input string + */ + std::map interconnect_default_path_ids_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/vpr_clustering_annotation.cpp b/openfpga/src/annotation/vpr_clustering_annotation.cpp index a707c7128..292383be9 100644 --- a/openfpga/src/annotation/vpr_clustering_annotation.cpp +++ b/openfpga/src/annotation/vpr_clustering_annotation.cpp @@ -1,32 +1,34 @@ /************************************************************************ * Member functions for class VprClusteringAnnotation ***********************************************************************/ -#include "vtr_log.h" -#include "vtr_assert.h" #include "vpr_clustering_annotation.h" +#include "vtr_assert.h" +#include "vtr_log.h" + /* namespace openfpga begins */ namespace openfpga { /************************************************************************ * Constructors ***********************************************************************/ -VprClusteringAnnotation::VprClusteringAnnotation() { - return; -} +VprClusteringAnnotation::VprClusteringAnnotation() { return; } /************************************************************************ * Public accessors ***********************************************************************/ -bool VprClusteringAnnotation::is_net_renamed(const ClusterBlockId& block_id, const int& pin_index) const { +bool VprClusteringAnnotation::is_net_renamed(const ClusterBlockId& block_id, + const int& pin_index) const { /* Ensure that the block_id is in the list */ if (net_names_.end() == net_names_.find(block_id)) { return false; } - return (net_names_.at(block_id).end() != net_names_.at(block_id).find(pin_index)); + return (net_names_.at(block_id).end() != + net_names_.at(block_id).find(pin_index)); } -ClusterNetId VprClusteringAnnotation::net(const ClusterBlockId& block_id, const int& pin_index) const { +ClusterNetId VprClusteringAnnotation::net(const ClusterBlockId& block_id, + const int& pin_index) const { VTR_ASSERT(true == is_net_renamed(block_id, pin_index)); return net_names_.at(block_id).at(pin_index); } @@ -41,7 +43,8 @@ AtomNetlist::TruthTable VprClusteringAnnotation::truth_table(t_pb* pb) const { return block_truth_tables_.at(pb); } -PhysicalPb VprClusteringAnnotation::physical_pb(const ClusterBlockId& block_id) const { +PhysicalPb VprClusteringAnnotation::physical_pb( + const ClusterBlockId& block_id) const { if (physical_pbs_.end() == physical_pbs_.find(block_id)) { return PhysicalPb(); } @@ -52,24 +55,30 @@ PhysicalPb VprClusteringAnnotation::physical_pb(const ClusterBlockId& block_id) /************************************************************************ * Public mutators ***********************************************************************/ -void VprClusteringAnnotation::rename_net(const ClusterBlockId& block_id, const int& pin_index, - const ClusterNetId& net_id) { +void VprClusteringAnnotation::rename_net(const ClusterBlockId& block_id, + const int& pin_index, + const ClusterNetId& net_id) { /* Warn any override attempt */ - if ( (net_names_.end() != net_names_.find(block_id)) - && (net_names_.at(block_id).end() != net_names_.at(block_id).find(pin_index)) ) { - VTR_LOG_WARN("Override the net '%ld' for block '%ld' pin '%d' with in clustering context annotation!\n", - size_t(net_id), size_t(block_id), pin_index); + if ((net_names_.end() != net_names_.find(block_id)) && + (net_names_.at(block_id).end() != + net_names_.at(block_id).find(pin_index))) { + VTR_LOG_WARN( + "Override the net '%ld' for block '%ld' pin '%d' with in clustering " + "context annotation!\n", + size_t(net_id), size_t(block_id), pin_index); } net_names_[block_id][pin_index] = net_id; } -void VprClusteringAnnotation::adapt_truth_table(t_pb* pb, - const AtomNetlist::TruthTable& tt) { +void VprClusteringAnnotation::adapt_truth_table( + t_pb* pb, const AtomNetlist::TruthTable& tt) { /* Warn any override attempt */ if (block_truth_tables_.end() != block_truth_tables_.find(pb)) { - VTR_LOG_WARN("Override the truth table for pb '%s' in clustering context annotation!\n", - pb->name); + VTR_LOG_WARN( + "Override the truth table for pb '%s' in clustering context " + "annotation!\n", + pb->name); } block_truth_tables_[pb] = tt; @@ -79,21 +88,22 @@ void VprClusteringAnnotation::add_physical_pb(const ClusterBlockId& block_id, const PhysicalPb& physical_pb) { /* Warn any override attempt */ if (physical_pbs_.end() != physical_pbs_.find(block_id)) { - VTR_LOG_WARN("Override the physical pb for clustered block %lu in clustering context annotation!\n", - size_t(block_id)); + VTR_LOG_WARN( + "Override the physical pb for clustered block %lu in clustering context " + "annotation!\n", + size_t(block_id)); } physical_pbs_[block_id] = physical_pb; } -PhysicalPb& VprClusteringAnnotation::mutable_physical_pb(const ClusterBlockId& block_id) { +PhysicalPb& VprClusteringAnnotation::mutable_physical_pb( + const ClusterBlockId& block_id) { VTR_ASSERT(physical_pbs_.end() != physical_pbs_.find(block_id)); return physical_pbs_.at(block_id); } -void VprClusteringAnnotation::clear_net_remapping() { - net_names_.clear(); -} +void VprClusteringAnnotation::clear_net_remapping() { net_names_.clear(); } } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/vpr_clustering_annotation.h b/openfpga/src/annotation/vpr_clustering_annotation.h index ba5e3d0db..b308e4d99 100644 --- a/openfpga/src/annotation/vpr_clustering_annotation.h +++ b/openfpga/src/annotation/vpr_clustering_annotation.h @@ -4,11 +4,10 @@ /******************************************************************** * Include header files required by the data structure definition *******************************************************************/ -#include +#include /* Header from vpr library */ #include "clustered_netlist.h" - #include "physical_pb.h" /* Begin namespace openfpga */ @@ -24,33 +23,40 @@ namespace openfpga { * 4. what is the mode pointer that represents the physical mode for a pb_type *******************************************************************/ class VprClusteringAnnotation { - public: /* Constructor */ - VprClusteringAnnotation(); - public: /* Public accessors */ - /* Xifan Tang: I created two functions for each data query in purpose! - * As this is an annotation, some net/block may be changed to invalid id - * In this case, return an invalid value does not mean that a net is not renamed - */ - bool is_net_renamed(const ClusterBlockId& block_id, const int& pin_index) const; - ClusterNetId net(const ClusterBlockId& block_id, const int& pin_index) const; - bool is_truth_table_adapted(t_pb* pb) const; - AtomNetlist::TruthTable truth_table(t_pb* pb) const; - PhysicalPb physical_pb(const ClusterBlockId& block_id) const; - public: /* Public mutators */ - void rename_net(const ClusterBlockId& block_id, const int& pin_index, - const ClusterNetId& net_id); - void adapt_truth_table(t_pb* pb, const AtomNetlist::TruthTable& tt); - void add_physical_pb(const ClusterBlockId& block_id, const PhysicalPb& physical_pb); - PhysicalPb& mutable_physical_pb(const ClusterBlockId& block_id); - public: /* Clean-up */ - void clear_net_remapping(); - private: /* Internal data */ - /* Pair a regular pb_type to its physical pb_type */ - std::map> net_names_; - std::map block_truth_tables_; + public: /* Constructor */ + VprClusteringAnnotation(); - /* Link clustered blocks to physical pb (mapping results) */ - std::map physical_pbs_; + public: /* Public accessors */ + /* Xifan Tang: I created two functions for each data query in purpose! + * As this is an annotation, some net/block may be changed to invalid id + * In this case, return an invalid value does not mean that a net is not + * renamed + */ + bool is_net_renamed(const ClusterBlockId& block_id, + const int& pin_index) const; + ClusterNetId net(const ClusterBlockId& block_id, const int& pin_index) const; + bool is_truth_table_adapted(t_pb* pb) const; + AtomNetlist::TruthTable truth_table(t_pb* pb) const; + PhysicalPb physical_pb(const ClusterBlockId& block_id) const; + + public: /* Public mutators */ + void rename_net(const ClusterBlockId& block_id, const int& pin_index, + const ClusterNetId& net_id); + void adapt_truth_table(t_pb* pb, const AtomNetlist::TruthTable& tt); + void add_physical_pb(const ClusterBlockId& block_id, + const PhysicalPb& physical_pb); + PhysicalPb& mutable_physical_pb(const ClusterBlockId& block_id); + + public: /* Clean-up */ + void clear_net_remapping(); + + private: /* Internal data */ + /* Pair a regular pb_type to its physical pb_type */ + std::map> net_names_; + std::map block_truth_tables_; + + /* Link clustered blocks to physical pb (mapping results) */ + std::map physical_pbs_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/vpr_device_annotation.cpp b/openfpga/src/annotation/vpr_device_annotation.cpp index e8eae0346..07f686302 100644 --- a/openfpga/src/annotation/vpr_device_annotation.cpp +++ b/openfpga/src/annotation/vpr_device_annotation.cpp @@ -1,11 +1,12 @@ /************************************************************************ * Member functions for class VprDeviceAnnotation ***********************************************************************/ +#include "vpr_device_annotation.h" + #include -#include "vtr_log.h" #include "vtr_assert.h" -#include "vpr_device_annotation.h" +#include "vtr_log.h" /* namespace openfpga begins */ namespace openfpga { @@ -13,26 +14,27 @@ namespace openfpga { /************************************************************************ * Constructors ***********************************************************************/ -VprDeviceAnnotation::VprDeviceAnnotation() { - return; -} +VprDeviceAnnotation::VprDeviceAnnotation() { return; } /************************************************************************ * Public accessors ***********************************************************************/ bool VprDeviceAnnotation::is_physical_pb_type(t_pb_type* pb_type) const { /* Ensure that the pb_type is in the list */ - std::map::const_iterator it = physical_pb_types_.find(pb_type); + std::map::const_iterator it = + physical_pb_types_.find(pb_type); if (it == physical_pb_types_.end()) { return false; } - /* A physical pb_type should be mapped to itself! Otherwise, it is an operating pb_type */ + /* A physical pb_type should be mapped to itself! Otherwise, it is an + * operating pb_type */ return pb_type == physical_pb_types_.at(pb_type); } t_mode* VprDeviceAnnotation::physical_mode(t_pb_type* pb_type) const { /* Ensure that the pb_type is in the list */ - std::map::const_iterator it = physical_pb_modes_.find(pb_type); + std::map::const_iterator it = + physical_pb_modes_.find(pb_type); if (it == physical_pb_modes_.end()) { return nullptr; } @@ -41,40 +43,49 @@ t_mode* VprDeviceAnnotation::physical_mode(t_pb_type* pb_type) const { t_pb_type* VprDeviceAnnotation::physical_pb_type(t_pb_type* pb_type) const { /* Ensure that the pb_type is in the list */ - std::map::const_iterator it = physical_pb_types_.find(pb_type); + std::map::const_iterator it = + physical_pb_types_.find(pb_type); if (it == physical_pb_types_.end()) { return nullptr; } return physical_pb_types_.at(pb_type); } -std::vector VprDeviceAnnotation::physical_pb_port(t_port* pb_port) const { +std::vector VprDeviceAnnotation::physical_pb_port( + t_port* pb_port) const { /* Ensure that the pb_type is in the list */ - std::map>::const_iterator it = physical_pb_ports_.find(pb_port); + std::map>::const_iterator it = + physical_pb_ports_.find(pb_port); if (it == physical_pb_ports_.end()) { return std::vector(); } return physical_pb_ports_.at(pb_port); } -BasicPort VprDeviceAnnotation::physical_pb_port_range(t_port* operating_pb_port, - t_port* physical_pb_port) const { +BasicPort VprDeviceAnnotation::physical_pb_port_range( + t_port* operating_pb_port, t_port* physical_pb_port) const { /* Ensure that the pb_type is in the list */ - std::map>::const_iterator it = physical_pb_port_ranges_.find(operating_pb_port); + std::map>::const_iterator it = + physical_pb_port_ranges_.find(operating_pb_port); if (it == physical_pb_port_ranges_.end()) { - /* Return an invalid port. As such the port width will be 0, which is an invalid value */ + /* Return an invalid port. As such the port width will be 0, which is an + * invalid value */ return BasicPort(); } - if (0 == physical_pb_port_ranges_.at(operating_pb_port).count(physical_pb_port)) { - /* Return an invalid port. As such the port width will be 0, which is an invalid value */ + if (0 == + physical_pb_port_ranges_.at(operating_pb_port).count(physical_pb_port)) { + /* Return an invalid port. As such the port width will be 0, which is an + * invalid value */ return BasicPort(); } return physical_pb_port_ranges_.at(operating_pb_port).at(physical_pb_port); } -CircuitModelId VprDeviceAnnotation::pb_type_circuit_model(t_pb_type* physical_pb_type) const { +CircuitModelId VprDeviceAnnotation::pb_type_circuit_model( + t_pb_type* physical_pb_type) const { /* Ensure that the pb_type is in the list */ - std::map::const_iterator it = pb_type_circuit_models_.find(physical_pb_type); + std::map::const_iterator it = + pb_type_circuit_models_.find(physical_pb_type); if (it == pb_type_circuit_models_.end()) { /* Return an invalid circuit model id */ return CircuitModelId::INVALID(); @@ -82,9 +93,11 @@ CircuitModelId VprDeviceAnnotation::pb_type_circuit_model(t_pb_type* physical_pb return pb_type_circuit_models_.at(physical_pb_type); } -CircuitModelId VprDeviceAnnotation::interconnect_circuit_model(t_interconnect* pb_interconnect) const { +CircuitModelId VprDeviceAnnotation::interconnect_circuit_model( + t_interconnect* pb_interconnect) const { /* Ensure that the pb_type is in the list */ - std::map::const_iterator it = interconnect_circuit_models_.find(pb_interconnect); + std::map::const_iterator it = + interconnect_circuit_models_.find(pb_interconnect); if (it == interconnect_circuit_models_.end()) { /* Return an invalid circuit model id */ return CircuitModelId::INVALID(); @@ -92,9 +105,11 @@ CircuitModelId VprDeviceAnnotation::interconnect_circuit_model(t_interconnect* p return interconnect_circuit_models_.at(pb_interconnect); } -e_interconnect VprDeviceAnnotation::interconnect_physical_type(t_interconnect* pb_interconnect) const { +e_interconnect VprDeviceAnnotation::interconnect_physical_type( + t_interconnect* pb_interconnect) const { /* Ensure that the pb_type is in the list */ - std::map::const_iterator it = interconnect_physical_types_.find(pb_interconnect); + std::map::const_iterator it = + interconnect_physical_types_.find(pb_interconnect); if (it == interconnect_physical_types_.end()) { /* Return an invalid interconnect type */ return NUM_INTERC_TYPES; @@ -104,7 +119,8 @@ e_interconnect VprDeviceAnnotation::interconnect_physical_type(t_interconnect* p CircuitPortId VprDeviceAnnotation::pb_circuit_port(t_port* pb_port) const { /* Ensure that the pb_type is in the list */ - std::map::const_iterator it = pb_circuit_ports_.find(pb_port); + std::map::const_iterator it = + pb_circuit_ports_.find(pb_port); if (it == pb_circuit_ports_.end()) { /* Return an invalid circuit port id */ return CircuitPortId::INVALID(); @@ -112,9 +128,11 @@ CircuitPortId VprDeviceAnnotation::pb_circuit_port(t_port* pb_port) const { return pb_circuit_ports_.at(pb_port); } -std::vector VprDeviceAnnotation::pb_type_mode_bits(t_pb_type* pb_type) const { +std::vector VprDeviceAnnotation::pb_type_mode_bits( + t_pb_type* pb_type) const { /* Ensure that the pb_type is in the list */ - std::map>::const_iterator it = pb_type_mode_bits_.find(pb_type); + std::map>::const_iterator it = + pb_type_mode_bits_.find(pb_type); if (it == pb_type_mode_bits_.end()) { /* Return an empty vector */ return std::vector(); @@ -122,30 +140,36 @@ std::vector VprDeviceAnnotation::pb_type_mode_bits(t_pb_type* pb_type) c return pb_type_mode_bits_.at(pb_type); } -PbGraphNodeId VprDeviceAnnotation::pb_graph_node_unique_index(t_pb_graph_node* pb_graph_node) const { +PbGraphNodeId VprDeviceAnnotation::pb_graph_node_unique_index( + t_pb_graph_node* pb_graph_node) const { /* Ensure that the pb_type is in the list */ - std::map>::const_iterator it = pb_graph_node_unique_index_.find(pb_graph_node->pb_type); + std::map>::const_iterator it = + pb_graph_node_unique_index_.find(pb_graph_node->pb_type); if (it == pb_graph_node_unique_index_.end()) { /* Invalid pb_type, return a null pointer */ return PbGraphNodeId::INVALID(); } /* Try to find the pb_graph_node in the vector */ - std::vector::const_iterator it_node = std::find(pb_graph_node_unique_index_.at(pb_graph_node->pb_type).begin(), - pb_graph_node_unique_index_.at(pb_graph_node->pb_type).end(), - pb_graph_node); + std::vector::const_iterator it_node = + std::find(pb_graph_node_unique_index_.at(pb_graph_node->pb_type).begin(), + pb_graph_node_unique_index_.at(pb_graph_node->pb_type).end(), + pb_graph_node); /* If it exists, return the index * Otherwise, return an invalid id */ if (it_node == pb_graph_node_unique_index_.at(pb_graph_node->pb_type).end()) { return PbGraphNodeId::INVALID(); } - return PbGraphNodeId(it_node - pb_graph_node_unique_index_.at(pb_graph_node->pb_type).begin()); + return PbGraphNodeId( + it_node - pb_graph_node_unique_index_.at(pb_graph_node->pb_type).begin()); } -t_pb_graph_node* VprDeviceAnnotation::pb_graph_node(t_pb_type* pb_type, const PbGraphNodeId& unique_index) const { +t_pb_graph_node* VprDeviceAnnotation::pb_graph_node( + t_pb_type* pb_type, const PbGraphNodeId& unique_index) const { /* Ensure that the pb_type is in the list */ - std::map>::const_iterator it = pb_graph_node_unique_index_.find(pb_type); + std::map>::const_iterator it = + pb_graph_node_unique_index_.find(pb_type); if (it == pb_graph_node_unique_index_.end()) { /* Invalid pb_type, return a null pointer */ return nullptr; @@ -154,25 +178,30 @@ t_pb_graph_node* VprDeviceAnnotation::pb_graph_node(t_pb_type* pb_type, const Pb * - Out of range: return a null pointer * - In range: return the pointer */ - if ((size_t)unique_index > pb_graph_node_unique_index_.at(pb_type).size() - 1) { + if ((size_t)unique_index > + pb_graph_node_unique_index_.at(pb_type).size() - 1) { return nullptr; } return pb_graph_node_unique_index_.at(pb_type)[size_t(unique_index)]; } -t_pb_graph_node* VprDeviceAnnotation::physical_pb_graph_node(t_pb_graph_node* pb_graph_node) const { +t_pb_graph_node* VprDeviceAnnotation::physical_pb_graph_node( + t_pb_graph_node* pb_graph_node) const { /* Ensure that the pb_graph_node is in the list */ - std::map::const_iterator it = physical_pb_graph_nodes_.find(pb_graph_node); + std::map::const_iterator it = + physical_pb_graph_nodes_.find(pb_graph_node); if (it == physical_pb_graph_nodes_.end()) { return nullptr; } return physical_pb_graph_nodes_.at(pb_graph_node); } -float VprDeviceAnnotation::physical_pb_type_index_factor(t_pb_type* pb_type) const { +float VprDeviceAnnotation::physical_pb_type_index_factor( + t_pb_type* pb_type) const { /* Ensure that the pb_type is in the list */ - std::map::const_iterator it = physical_pb_type_index_factors_.find(pb_type); + std::map::const_iterator it = + physical_pb_type_index_factors_.find(pb_type); if (it == physical_pb_type_index_factors_.end()) { /* Default value is 1 */ return 1.; @@ -180,9 +209,11 @@ float VprDeviceAnnotation::physical_pb_type_index_factor(t_pb_type* pb_type) con return physical_pb_type_index_factors_.at(pb_type); } -int VprDeviceAnnotation::physical_pb_type_index_offset(t_pb_type* pb_type) const { +int VprDeviceAnnotation::physical_pb_type_index_offset( + t_pb_type* pb_type) const { /* Ensure that the pb_type is in the list */ - std::map::const_iterator it = physical_pb_type_index_offsets_.find(pb_type); + std::map::const_iterator it = + physical_pb_type_index_offsets_.find(pb_type); if (it == physical_pb_type_index_offsets_.end()) { /* Default value is 0 */ return 0; @@ -190,109 +221,129 @@ int VprDeviceAnnotation::physical_pb_type_index_offset(t_pb_type* pb_type) const return physical_pb_type_index_offsets_.at(pb_type); } -int VprDeviceAnnotation::physical_pb_pin_initial_offset(t_port* operating_pb_port, - t_port* physical_pb_port) const { +int VprDeviceAnnotation::physical_pb_pin_initial_offset( + t_port* operating_pb_port, t_port* physical_pb_port) const { /* Ensure that the pb_type is in the list */ - std::map>::const_iterator it = physical_pb_pin_initial_offsets_.find(operating_pb_port); + std::map>::const_iterator it = + physical_pb_pin_initial_offsets_.find(operating_pb_port); if (it == physical_pb_pin_initial_offsets_.end()) { /* Default value is 0 */ return 0; } - if (0 == physical_pb_pin_initial_offsets_.at(operating_pb_port).count(physical_pb_port)) { + if (0 == physical_pb_pin_initial_offsets_.at(operating_pb_port) + .count(physical_pb_port)) { /* Default value is 0 */ return 0; } - return physical_pb_pin_initial_offsets_.at(operating_pb_port).at(physical_pb_port); + return physical_pb_pin_initial_offsets_.at(operating_pb_port) + .at(physical_pb_port); } -int VprDeviceAnnotation::physical_pb_pin_rotate_offset(t_port* operating_pb_port, - t_port* physical_pb_port) const { +int VprDeviceAnnotation::physical_pb_pin_rotate_offset( + t_port* operating_pb_port, t_port* physical_pb_port) const { /* Ensure that the pb_type is in the list */ - std::map>::const_iterator it = physical_pb_pin_rotate_offsets_.find(operating_pb_port); + std::map>::const_iterator it = + physical_pb_pin_rotate_offsets_.find(operating_pb_port); if (it == physical_pb_pin_rotate_offsets_.end()) { /* Default value is 0 */ return 0; } - if (0 == physical_pb_pin_rotate_offsets_.at(operating_pb_port).count(physical_pb_port)) { + if (0 == physical_pb_pin_rotate_offsets_.at(operating_pb_port) + .count(physical_pb_port)) { /* Default value is 0 */ return 0; } - return physical_pb_pin_rotate_offsets_.at(operating_pb_port).at(physical_pb_port); + return physical_pb_pin_rotate_offsets_.at(operating_pb_port) + .at(physical_pb_port); } -int VprDeviceAnnotation::physical_pb_port_rotate_offset(t_port* operating_pb_port, - t_port* physical_pb_port) const { +int VprDeviceAnnotation::physical_pb_port_rotate_offset( + t_port* operating_pb_port, t_port* physical_pb_port) const { /* Ensure that the pb_type is in the list */ - std::map>::const_iterator it = physical_pb_port_rotate_offsets_.find(operating_pb_port); + std::map>::const_iterator it = + physical_pb_port_rotate_offsets_.find(operating_pb_port); if (it == physical_pb_port_rotate_offsets_.end()) { /* Default value is 0 */ return 0; } - if (0 == physical_pb_port_rotate_offsets_.at(operating_pb_port).count(physical_pb_port)) { + if (0 == physical_pb_port_rotate_offsets_.at(operating_pb_port) + .count(physical_pb_port)) { /* Default value is 0 */ return 0; } - return physical_pb_port_rotate_offsets_.at(operating_pb_port).at(physical_pb_port); + return physical_pb_port_rotate_offsets_.at(operating_pb_port) + .at(physical_pb_port); } -int VprDeviceAnnotation::physical_pb_pin_offset(t_port* operating_pb_port, - t_port* physical_pb_port) const { +int VprDeviceAnnotation::physical_pb_pin_offset( + t_port* operating_pb_port, t_port* physical_pb_port) const { /* Ensure that the pb_type is in the list */ - std::map>::const_iterator it = physical_pb_pin_offsets_.find(operating_pb_port); + std::map>::const_iterator it = + physical_pb_pin_offsets_.find(operating_pb_port); if (it == physical_pb_pin_offsets_.end()) { /* Default value is 0 */ return 0; } - if (0 == physical_pb_pin_offsets_.at(operating_pb_port).count(physical_pb_port)) { + if (0 == + physical_pb_pin_offsets_.at(operating_pb_port).count(physical_pb_port)) { /* Default value is 0 */ return 0; } return physical_pb_pin_offsets_.at(operating_pb_port).at(physical_pb_port); } -int VprDeviceAnnotation::physical_pb_port_offset(t_port* operating_pb_port, - t_port* physical_pb_port) const { +int VprDeviceAnnotation::physical_pb_port_offset( + t_port* operating_pb_port, t_port* physical_pb_port) const { /* Ensure that the pb_type is in the list */ - std::map>::const_iterator it = physical_pb_port_offsets_.find(operating_pb_port); + std::map>::const_iterator it = + physical_pb_port_offsets_.find(operating_pb_port); if (it == physical_pb_port_offsets_.end()) { /* Default value is 0 */ return 0; } - if (0 == physical_pb_port_offsets_.at(operating_pb_port).count(physical_pb_port)) { + if (0 == + physical_pb_port_offsets_.at(operating_pb_port).count(physical_pb_port)) { /* Default value is 0 */ return 0; } return physical_pb_port_offsets_.at(operating_pb_port).at(physical_pb_port); } -t_pb_graph_pin* VprDeviceAnnotation::physical_pb_graph_pin(const t_pb_graph_pin* pb_graph_pin) const { +t_pb_graph_pin* VprDeviceAnnotation::physical_pb_graph_pin( + const t_pb_graph_pin* pb_graph_pin) const { /* Ensure that the pb_type is in the list */ - std::map::const_iterator it = physical_pb_graph_pins_.find(pb_graph_pin); + std::map::const_iterator it = + physical_pb_graph_pins_.find(pb_graph_pin); if (it == physical_pb_graph_pins_.end()) { return nullptr; } return physical_pb_graph_pins_.at(pb_graph_pin); } -CircuitModelId VprDeviceAnnotation::rr_switch_circuit_model(const RRSwitchId& rr_switch) const { +CircuitModelId VprDeviceAnnotation::rr_switch_circuit_model( + const RRSwitchId& rr_switch) const { /* Ensure that the rr_switch is in the list */ - std::map::const_iterator it = rr_switch_circuit_models_.find(rr_switch); + std::map::const_iterator it = + rr_switch_circuit_models_.find(rr_switch); if (it == rr_switch_circuit_models_.end()) { return CircuitModelId::INVALID(); } return rr_switch_circuit_models_.at(rr_switch); } -CircuitModelId VprDeviceAnnotation::rr_segment_circuit_model(const RRSegmentId& rr_segment) const { +CircuitModelId VprDeviceAnnotation::rr_segment_circuit_model( + const RRSegmentId& rr_segment) const { /* Ensure that the rr_switch is in the list */ - std::map::const_iterator it = rr_segment_circuit_models_.find(rr_segment); + std::map::const_iterator it = + rr_segment_circuit_models_.find(rr_segment); if (it == rr_segment_circuit_models_.end()) { return CircuitModelId::INVALID(); } return rr_segment_circuit_models_.at(rr_segment); } -ArchDirectId VprDeviceAnnotation::direct_annotation(const size_t& direct) const { +ArchDirectId VprDeviceAnnotation::direct_annotation( + const size_t& direct) const { /* Ensure that the rr_switch is in the list */ if (0 == direct_annotations_.count(direct)) { return ArchDirectId::INVALID(); @@ -300,7 +351,8 @@ ArchDirectId VprDeviceAnnotation::direct_annotation(const size_t& direct) const return direct_annotations_.at(direct); } -LbRRGraph VprDeviceAnnotation::physical_lb_rr_graph(t_pb_graph_node* pb_graph_head) const { +LbRRGraph VprDeviceAnnotation::physical_lb_rr_graph( + t_pb_graph_node* pb_graph_head) const { /* Ensure that the rr_switch is in the list */ if (0 == physical_lb_rr_graphs_.count(pb_graph_head)) { return LbRRGraph(); @@ -308,10 +360,11 @@ LbRRGraph VprDeviceAnnotation::physical_lb_rr_graph(t_pb_graph_node* pb_graph_he return physical_lb_rr_graphs_.at(pb_graph_head); } -BasicPort VprDeviceAnnotation::physical_tile_pin_port_info(t_physical_tile_type_ptr physical_tile, - const int& pin_index) const { +BasicPort VprDeviceAnnotation::physical_tile_pin_port_info( + t_physical_tile_type_ptr physical_tile, const int& pin_index) const { /* Try to find the physical tile in the fast look-up */ - auto physical_tile_search_result = physical_tile_pin2port_info_map_.find(physical_tile); + auto physical_tile_search_result = + physical_tile_pin2port_info_map_.find(physical_tile); if (physical_tile_search_result == physical_tile_pin2port_info_map_.end()) { /* Not found. Return an invalid port */ return BasicPort(); @@ -323,15 +376,16 @@ BasicPort VprDeviceAnnotation::physical_tile_pin_port_info(t_physical_tile_type_ /* Not found. Return an invalid port */ return BasicPort(); } - + /* Reach here, we should find a port. Return the port information */ return pin_search_result->second; } -int VprDeviceAnnotation::physical_tile_pin_subtile_index(t_physical_tile_type_ptr physical_tile, - const int& pin_index) const { +int VprDeviceAnnotation::physical_tile_pin_subtile_index( + t_physical_tile_type_ptr physical_tile, const int& pin_index) const { /* Try to find the physical tile in the fast look-up */ - auto physical_tile_search_result = physical_tile_pin_subtile_indices_.find(physical_tile); + auto physical_tile_search_result = + physical_tile_pin_subtile_indices_.find(physical_tile); if (physical_tile_search_result == physical_tile_pin_subtile_indices_.end()) { /* Not found. Return an invalid index */ return -1; @@ -343,16 +397,18 @@ int VprDeviceAnnotation::physical_tile_pin_subtile_index(t_physical_tile_type_pt /* Not found. Return an invalid index */ return -1; } - + /* Reach here, we should find a port. Return the port information */ return pin_search_result->second; } -int VprDeviceAnnotation::physical_tile_z_to_subtile_index(t_physical_tile_type_ptr physical_tile, - const int& sub_tile_z) const { +int VprDeviceAnnotation::physical_tile_z_to_subtile_index( + t_physical_tile_type_ptr physical_tile, const int& sub_tile_z) const { /* Try to find the physical tile in the fast look-up */ - auto physical_tile_search_result = physical_tile_z_to_subtile_indices_.find(physical_tile); - if (physical_tile_search_result == physical_tile_z_to_subtile_indices_.end()) { + auto physical_tile_search_result = + physical_tile_z_to_subtile_indices_.find(physical_tile); + if (physical_tile_search_result == + physical_tile_z_to_subtile_indices_.end()) { /* Not found. Return an invalid index */ return -1; } @@ -363,16 +419,18 @@ int VprDeviceAnnotation::physical_tile_z_to_subtile_index(t_physical_tile_type_p /* Not found. Return an invalid index */ return -1; } - + /* Reach here, we should find a port. Return the port information */ return pin_search_result->second; } -int VprDeviceAnnotation::physical_tile_z_to_start_pin_index(t_physical_tile_type_ptr physical_tile, - const int& sub_tile_z) const { +int VprDeviceAnnotation::physical_tile_z_to_start_pin_index( + t_physical_tile_type_ptr physical_tile, const int& sub_tile_z) const { /* Try to find the physical tile in the fast look-up */ - auto physical_tile_search_result = physical_tile_z_to_start_pin_indices_.find(physical_tile); - if (physical_tile_search_result == physical_tile_z_to_start_pin_indices_.end()) { + auto physical_tile_search_result = + physical_tile_z_to_start_pin_indices_.find(physical_tile); + if (physical_tile_search_result == + physical_tile_z_to_start_pin_indices_.end()) { /* Not found. Return an invalid index */ return -1; } @@ -383,7 +441,7 @@ int VprDeviceAnnotation::physical_tile_z_to_start_pin_index(t_physical_tile_type /* Not found. Return an invalid index */ return -1; } - + /* Reach here, we should find a port. Return the port information */ return pin_search_result->second; } @@ -391,23 +449,31 @@ int VprDeviceAnnotation::physical_tile_z_to_start_pin_index(t_physical_tile_type /************************************************************************ * Public mutators ***********************************************************************/ -void VprDeviceAnnotation::add_pb_type_physical_mode(t_pb_type* pb_type, t_mode* physical_mode) { +void VprDeviceAnnotation::add_pb_type_physical_mode(t_pb_type* pb_type, + t_mode* physical_mode) { /* Warn any override attempt */ - std::map::const_iterator it = physical_pb_modes_.find(pb_type); + std::map::const_iterator it = + physical_pb_modes_.find(pb_type); if (it != physical_pb_modes_.end()) { - VTR_LOG_WARN("Override the annotation between pb_type '%s' and it physical mode '%s'!\n", - pb_type->name, physical_mode->name); + VTR_LOG_WARN( + "Override the annotation between pb_type '%s' and it physical mode " + "'%s'!\n", + pb_type->name, physical_mode->name); } physical_pb_modes_[pb_type] = physical_mode; } -void VprDeviceAnnotation::add_physical_pb_type(t_pb_type* operating_pb_type, t_pb_type* physical_pb_type) { +void VprDeviceAnnotation::add_physical_pb_type(t_pb_type* operating_pb_type, + t_pb_type* physical_pb_type) { /* Warn any override attempt */ - std::map::const_iterator it = physical_pb_types_.find(operating_pb_type); + std::map::const_iterator it = + physical_pb_types_.find(operating_pb_type); if (it != physical_pb_types_.end()) { - VTR_LOG_WARN("Override the annotation between operating pb_type '%s' and it physical pb_type '%s'!\n", - operating_pb_type->name, physical_pb_type->name); + VTR_LOG_WARN( + "Override the annotation between operating pb_type '%s' and it physical " + "pb_type '%s'!\n", + operating_pb_type->name, physical_pb_type->name); } physical_pb_types_[operating_pb_type] = physical_pb_type; @@ -418,28 +484,33 @@ void VprDeviceAnnotation::add_physical_pb_port(t_port* operating_pb_port, physical_pb_ports_[operating_pb_port].push_back(physical_pb_port); } -void VprDeviceAnnotation::add_physical_pb_port_range(t_port* operating_pb_port, - t_port* physical_pb_port, - const BasicPort& port_range) { +void VprDeviceAnnotation::add_physical_pb_port_range( + t_port* operating_pb_port, t_port* physical_pb_port, + const BasicPort& port_range) { /* The port range must satify the port width*/ VTR_ASSERT((size_t)operating_pb_port->num_pins >= port_range.get_width()); /* Warn any override attempt */ - std::map>::const_iterator it = physical_pb_port_ranges_.find(operating_pb_port); - if ( (it != physical_pb_port_ranges_.end()) - && (0 < physical_pb_port_ranges_[operating_pb_port].count(physical_pb_port)) ) { - VTR_LOG_WARN("Override the annotation between operating pb_port '%s' and it physical pb_port range '%s[%ld:%ld]'!\n", - operating_pb_port->name, - physical_pb_port->name, - port_range.get_lsb(), port_range.get_msb()); + std::map>::const_iterator it = + physical_pb_port_ranges_.find(operating_pb_port); + if ((it != physical_pb_port_ranges_.end()) && + (0 < + physical_pb_port_ranges_[operating_pb_port].count(physical_pb_port))) { + VTR_LOG_WARN( + "Override the annotation between operating pb_port '%s' and it physical " + "pb_port range '%s[%ld:%ld]'!\n", + operating_pb_port->name, physical_pb_port->name, port_range.get_lsb(), + port_range.get_msb()); } physical_pb_port_ranges_[operating_pb_port][physical_pb_port] = port_range; } -void VprDeviceAnnotation::add_pb_type_circuit_model(t_pb_type* physical_pb_type, const CircuitModelId& circuit_model) { +void VprDeviceAnnotation::add_pb_type_circuit_model( + t_pb_type* physical_pb_type, const CircuitModelId& circuit_model) { /* Warn any override attempt */ - std::map::const_iterator it = pb_type_circuit_models_.find(physical_pb_type); + std::map::const_iterator it = + pb_type_circuit_models_.find(physical_pb_type); if (it != pb_type_circuit_models_.end()) { VTR_LOG_WARN("Override the circuit model for physical pb_type '%s'!\n", physical_pb_type->name); @@ -448,9 +519,11 @@ void VprDeviceAnnotation::add_pb_type_circuit_model(t_pb_type* physical_pb_type, pb_type_circuit_models_[physical_pb_type] = circuit_model; } -void VprDeviceAnnotation::add_interconnect_circuit_model(t_interconnect* pb_interconnect, const CircuitModelId& circuit_model) { +void VprDeviceAnnotation::add_interconnect_circuit_model( + t_interconnect* pb_interconnect, const CircuitModelId& circuit_model) { /* Warn any override attempt */ - std::map::const_iterator it = interconnect_circuit_models_.find(pb_interconnect); + std::map::const_iterator it = + interconnect_circuit_models_.find(pb_interconnect); if (it != interconnect_circuit_models_.end()) { VTR_LOG_WARN("Override the circuit model for interconnect '%s'!\n", pb_interconnect->name); @@ -459,10 +532,11 @@ void VprDeviceAnnotation::add_interconnect_circuit_model(t_interconnect* pb_inte interconnect_circuit_models_[pb_interconnect] = circuit_model; } -void VprDeviceAnnotation::add_interconnect_physical_type(t_interconnect* pb_interconnect, - const e_interconnect& physical_type) { +void VprDeviceAnnotation::add_interconnect_physical_type( + t_interconnect* pb_interconnect, const e_interconnect& physical_type) { /* Warn any override attempt */ - std::map::const_iterator it = interconnect_physical_types_.find(pb_interconnect); + std::map::const_iterator it = + interconnect_physical_types_.find(pb_interconnect); if (it != interconnect_physical_types_.end()) { VTR_LOG_WARN("Override the physical interconnect for interconnect '%s'!\n", pb_interconnect->name); @@ -471,9 +545,11 @@ void VprDeviceAnnotation::add_interconnect_physical_type(t_interconnect* pb_inte interconnect_physical_types_[pb_interconnect] = physical_type; } -void VprDeviceAnnotation::add_pb_circuit_port(t_port* pb_port, const CircuitPortId& circuit_port) { +void VprDeviceAnnotation::add_pb_circuit_port( + t_port* pb_port, const CircuitPortId& circuit_port) { /* Warn any override attempt */ - std::map::const_iterator it = pb_circuit_ports_.find(pb_port); + std::map::const_iterator it = + pb_circuit_ports_.find(pb_port); if (it != pb_circuit_ports_.end()) { VTR_LOG_WARN("Override the circuit port mapping for pb_type port '%s'!\n", pb_port->name); @@ -482,9 +558,11 @@ void VprDeviceAnnotation::add_pb_circuit_port(t_port* pb_port, const CircuitPort pb_circuit_ports_[pb_port] = circuit_port; } -void VprDeviceAnnotation::add_pb_type_mode_bits(t_pb_type* pb_type, const std::vector& mode_bits) { +void VprDeviceAnnotation::add_pb_type_mode_bits( + t_pb_type* pb_type, const std::vector& mode_bits) { /* Warn any override attempt */ - std::map>::const_iterator it = pb_type_mode_bits_.find(pb_type); + std::map>::const_iterator it = + pb_type_mode_bits_.find(pb_type); if (it != pb_type_mode_bits_.end()) { VTR_LOG_WARN("Override the mode bits mapping for pb_type '%s'!\n", pb_type->name); @@ -493,92 +571,116 @@ void VprDeviceAnnotation::add_pb_type_mode_bits(t_pb_type* pb_type, const std::v pb_type_mode_bits_[pb_type] = mode_bits; } -void VprDeviceAnnotation::add_pb_graph_node_unique_index(t_pb_graph_node* pb_graph_node) { +void VprDeviceAnnotation::add_pb_graph_node_unique_index( + t_pb_graph_node* pb_graph_node) { pb_graph_node_unique_index_[pb_graph_node->pb_type].push_back(pb_graph_node); } -void VprDeviceAnnotation::add_physical_pb_graph_node(t_pb_graph_node* operating_pb_graph_node, - t_pb_graph_node* physical_pb_graph_node) { +void VprDeviceAnnotation::add_physical_pb_graph_node( + t_pb_graph_node* operating_pb_graph_node, + t_pb_graph_node* physical_pb_graph_node) { /* Warn any override attempt */ - std::map::const_iterator it = physical_pb_graph_nodes_.find(operating_pb_graph_node); + std::map::const_iterator it = + physical_pb_graph_nodes_.find(operating_pb_graph_node); if (it != physical_pb_graph_nodes_.end()) { - VTR_LOG_WARN("Override the annotation between operating pb_graph_node '%s[%d]' and it physical pb_graph_node '%s[%d]'!\n", - operating_pb_graph_node->pb_type->name, - operating_pb_graph_node->placement_index, - physical_pb_graph_node->pb_type->name, - physical_pb_graph_node->placement_index); + VTR_LOG_WARN( + "Override the annotation between operating pb_graph_node '%s[%d]' and it " + "physical pb_graph_node '%s[%d]'!\n", + operating_pb_graph_node->pb_type->name, + operating_pb_graph_node->placement_index, + physical_pb_graph_node->pb_type->name, + physical_pb_graph_node->placement_index); } physical_pb_graph_nodes_[operating_pb_graph_node] = physical_pb_graph_node; } -void VprDeviceAnnotation::add_physical_pb_type_index_factor(t_pb_type* pb_type, const float& factor) { +void VprDeviceAnnotation::add_physical_pb_type_index_factor( + t_pb_type* pb_type, const float& factor) { /* Warn any override attempt */ - std::map::const_iterator it = physical_pb_type_index_factors_.find(pb_type); + std::map::const_iterator it = + physical_pb_type_index_factors_.find(pb_type); if (it != physical_pb_type_index_factors_.end()) { - VTR_LOG_WARN("Override the annotation between operating pb_type '%s' and it physical pb_type index factor '%f'!\n", - pb_type->name, factor); + VTR_LOG_WARN( + "Override the annotation between operating pb_type '%s' and it physical " + "pb_type index factor '%f'!\n", + pb_type->name, factor); } physical_pb_type_index_factors_[pb_type] = factor; } -void VprDeviceAnnotation::add_physical_pb_type_index_offset(t_pb_type* pb_type, const int& offset) { +void VprDeviceAnnotation::add_physical_pb_type_index_offset(t_pb_type* pb_type, + const int& offset) { /* Warn any override attempt */ - std::map::const_iterator it = physical_pb_type_index_offsets_.find(pb_type); + std::map::const_iterator it = + physical_pb_type_index_offsets_.find(pb_type); if (it != physical_pb_type_index_offsets_.end()) { - VTR_LOG_WARN("Override the annotation between operating pb_type '%s' and it physical pb_type index offset '%d'!\n", - pb_type->name, offset); + VTR_LOG_WARN( + "Override the annotation between operating pb_type '%s' and it physical " + "pb_type index offset '%d'!\n", + pb_type->name, offset); } physical_pb_type_index_offsets_[pb_type] = offset; } -void VprDeviceAnnotation::add_physical_pb_pin_initial_offset(t_port* operating_pb_port, - t_port* physical_pb_port, - const int& offset) { +void VprDeviceAnnotation::add_physical_pb_pin_initial_offset( + t_port* operating_pb_port, t_port* physical_pb_port, const int& offset) { /* Warn any override attempt */ - std::map>::const_iterator it = physical_pb_pin_initial_offsets_.find(operating_pb_port); - if ( (it != physical_pb_pin_initial_offsets_.end()) - && (0 < physical_pb_pin_initial_offsets_[operating_pb_port].count(physical_pb_port)) ) { - VTR_LOG_WARN("Override the annotation between operating pb_port '%s' and it physical pb_port '%s' pin rotate offset '%d'!\n", - operating_pb_port->name, offset); + std::map>::const_iterator it = + physical_pb_pin_initial_offsets_.find(operating_pb_port); + if ((it != physical_pb_pin_initial_offsets_.end()) && + (0 < physical_pb_pin_initial_offsets_[operating_pb_port].count( + physical_pb_port))) { + VTR_LOG_WARN( + "Override the annotation between operating pb_port '%s' and it physical " + "pb_port '%s' pin rotate offset '%d'!\n", + operating_pb_port->name, offset); } - physical_pb_pin_initial_offsets_[operating_pb_port][physical_pb_port] = offset; + physical_pb_pin_initial_offsets_[operating_pb_port][physical_pb_port] = + offset; } -void VprDeviceAnnotation::add_physical_pb_port_rotate_offset(t_port* operating_pb_port, - t_port* physical_pb_port, - const int& offset) { +void VprDeviceAnnotation::add_physical_pb_port_rotate_offset( + t_port* operating_pb_port, t_port* physical_pb_port, const int& offset) { /* Warn any override attempt */ - std::map>::const_iterator it = physical_pb_port_rotate_offsets_.find(operating_pb_port); - if ( (it != physical_pb_port_rotate_offsets_.end()) - && (0 < physical_pb_port_rotate_offsets_[operating_pb_port].count(physical_pb_port)) ) { - VTR_LOG_WARN("Override the annotation between operating pb_port '%s' and it physical pb_port '%s' port rotate offset '%d'!\n", - operating_pb_port->name, offset); + std::map>::const_iterator it = + physical_pb_port_rotate_offsets_.find(operating_pb_port); + if ((it != physical_pb_port_rotate_offsets_.end()) && + (0 < physical_pb_port_rotate_offsets_[operating_pb_port].count( + physical_pb_port))) { + VTR_LOG_WARN( + "Override the annotation between operating pb_port '%s' and it physical " + "pb_port '%s' port rotate offset '%d'!\n", + operating_pb_port->name, offset); } - physical_pb_port_rotate_offsets_[operating_pb_port][physical_pb_port] = offset; + physical_pb_port_rotate_offsets_[operating_pb_port][physical_pb_port] = + offset; /* We initialize the accumulated offset to 0 */ physical_pb_port_offsets_[operating_pb_port][physical_pb_port] = 0; } - -void VprDeviceAnnotation::accumulate_physical_pb_port_rotate_offset(t_port* operating_pb_port, - t_port* physical_pb_port) { - physical_pb_port_offsets_[operating_pb_port][physical_pb_port] += physical_pb_port_rotate_offsets_[operating_pb_port][physical_pb_port]; +void VprDeviceAnnotation::accumulate_physical_pb_port_rotate_offset( + t_port* operating_pb_port, t_port* physical_pb_port) { + physical_pb_port_offsets_[operating_pb_port][physical_pb_port] += + physical_pb_port_rotate_offsets_[operating_pb_port][physical_pb_port]; } -void VprDeviceAnnotation::add_physical_pb_pin_rotate_offset(t_port* operating_pb_port, - t_port* physical_pb_port, - const int& offset) { +void VprDeviceAnnotation::add_physical_pb_pin_rotate_offset( + t_port* operating_pb_port, t_port* physical_pb_port, const int& offset) { /* Warn any override attempt */ - std::map>::const_iterator it = physical_pb_pin_rotate_offsets_.find(operating_pb_port); - if ( (it != physical_pb_pin_rotate_offsets_.end()) - && (0 < physical_pb_pin_rotate_offsets_[operating_pb_port].count(physical_pb_port)) ) { - VTR_LOG_WARN("Override the annotation between operating pb_port '%s' and it physical pb_port '%s' pin rotate offset '%d'!\n", - operating_pb_port->name, offset); + std::map>::const_iterator it = + physical_pb_pin_rotate_offsets_.find(operating_pb_port); + if ((it != physical_pb_pin_rotate_offsets_.end()) && + (0 < physical_pb_pin_rotate_offsets_[operating_pb_port].count( + physical_pb_port))) { + VTR_LOG_WARN( + "Override the annotation between operating pb_port '%s' and it physical " + "pb_port '%s' pin rotate offset '%d'!\n", + operating_pb_port->name, offset); } physical_pb_pin_rotate_offsets_[operating_pb_port][physical_pb_port] = offset; @@ -586,76 +688,98 @@ void VprDeviceAnnotation::add_physical_pb_pin_rotate_offset(t_port* operating_pb physical_pb_pin_offsets_[operating_pb_port][physical_pb_port] = 0; } -void VprDeviceAnnotation::add_physical_pb_graph_pin(const t_pb_graph_pin* operating_pb_graph_pin, - t_pb_graph_pin* physical_pb_graph_pin) { +void VprDeviceAnnotation::add_physical_pb_graph_pin( + const t_pb_graph_pin* operating_pb_graph_pin, + t_pb_graph_pin* physical_pb_graph_pin) { /* Warn any override attempt */ - std::map::const_iterator it = physical_pb_graph_pins_.find(operating_pb_graph_pin); + std::map::const_iterator it = + physical_pb_graph_pins_.find(operating_pb_graph_pin); if (it != physical_pb_graph_pins_.end()) { - VTR_LOG_WARN("Override the annotation between operating pb_graph_pin '%s' and it physical pb_graph_pin '%s'!\n", - operating_pb_graph_pin->port->name, physical_pb_graph_pin->port->name); + VTR_LOG_WARN( + "Override the annotation between operating pb_graph_pin '%s' and it " + "physical pb_graph_pin '%s'!\n", + operating_pb_graph_pin->port->name, physical_pb_graph_pin->port->name); } physical_pb_graph_pins_[operating_pb_graph_pin] = physical_pb_graph_pin; - /* Update the accumulated offsets for the operating port + /* Update the accumulated offsets for the operating port * Each time we pair two pins, we update the offset by the pin rotate offset - * When the accumulated offset exceeds the MSB of the port range of physical port - * we reset it to 0 - * operating port physical port - * LSB port_range.lsb() pin_number pin_number MSB - * | | | + * When the accumulated offset exceeds the MSB of the port range of physical + * port we reset it to 0 operating port physical port LSB + * port_range.lsb() pin_number pin_number MSB | | | * Operating port | | +------ | * | |<----offset--->| * Physical port | + + + * */ - if (0 == physical_pb_pin_rotate_offset(operating_pb_graph_pin->port, physical_pb_graph_pin->port)) { + if (0 == physical_pb_pin_rotate_offset(operating_pb_graph_pin->port, + physical_pb_graph_pin->port)) { return; } - physical_pb_pin_offsets_[operating_pb_graph_pin->port][physical_pb_graph_pin->port] += physical_pb_pin_rotate_offset(operating_pb_graph_pin->port, physical_pb_graph_pin->port); + physical_pb_pin_offsets_[operating_pb_graph_pin->port] + [physical_pb_graph_pin->port] += + physical_pb_pin_rotate_offset(operating_pb_graph_pin->port, + physical_pb_graph_pin->port); - if ((size_t)physical_pb_graph_pin->port->num_pins - 1 - < operating_pb_graph_pin->pin_number - + physical_pb_port_range(operating_pb_graph_pin->port, physical_pb_graph_pin->port).get_lsb() - + physical_pb_pin_offsets_[operating_pb_graph_pin->port][physical_pb_graph_pin->port]) { - physical_pb_pin_offsets_[operating_pb_graph_pin->port][physical_pb_graph_pin->port] = 0; + if ((size_t)physical_pb_graph_pin->port->num_pins - 1 < + operating_pb_graph_pin->pin_number + + physical_pb_port_range(operating_pb_graph_pin->port, + physical_pb_graph_pin->port) + .get_lsb() + + physical_pb_pin_offsets_[operating_pb_graph_pin->port] + [physical_pb_graph_pin->port]) { + physical_pb_pin_offsets_[operating_pb_graph_pin->port] + [physical_pb_graph_pin->port] = 0; } } -void VprDeviceAnnotation::add_rr_switch_circuit_model(const RRSwitchId& rr_switch, const CircuitModelId& circuit_model) { +void VprDeviceAnnotation::add_rr_switch_circuit_model( + const RRSwitchId& rr_switch, const CircuitModelId& circuit_model) { /* Warn any override attempt */ - std::map::const_iterator it = rr_switch_circuit_models_.find(rr_switch); + std::map::const_iterator it = + rr_switch_circuit_models_.find(rr_switch); if (it != rr_switch_circuit_models_.end()) { - VTR_LOG_WARN("Override the annotation between rr_switch '%ld' and its circuit_model '%ld'!\n", - size_t(rr_switch), size_t(circuit_model)); + VTR_LOG_WARN( + "Override the annotation between rr_switch '%ld' and its circuit_model " + "'%ld'!\n", + size_t(rr_switch), size_t(circuit_model)); } rr_switch_circuit_models_[rr_switch] = circuit_model; } -void VprDeviceAnnotation::add_rr_segment_circuit_model(const RRSegmentId& rr_segment, const CircuitModelId& circuit_model) { +void VprDeviceAnnotation::add_rr_segment_circuit_model( + const RRSegmentId& rr_segment, const CircuitModelId& circuit_model) { /* Warn any override attempt */ - std::map::const_iterator it = rr_segment_circuit_models_.find(rr_segment); + std::map::const_iterator it = + rr_segment_circuit_models_.find(rr_segment); if (it != rr_segment_circuit_models_.end()) { - VTR_LOG_WARN("Override the annotation between rr_segment '%ld' and its circuit_model '%ld'!\n", - size_t(rr_segment), size_t(circuit_model)); + VTR_LOG_WARN( + "Override the annotation between rr_segment '%ld' and its circuit_model " + "'%ld'!\n", + size_t(rr_segment), size_t(circuit_model)); } rr_segment_circuit_models_[rr_segment] = circuit_model; } -void VprDeviceAnnotation::add_direct_annotation(const size_t& direct, const ArchDirectId& arch_direct_id) { +void VprDeviceAnnotation::add_direct_annotation( + const size_t& direct, const ArchDirectId& arch_direct_id) { /* Warn any override attempt */ if (0 < direct_annotations_.count(direct)) { - VTR_LOG_WARN("Override the annotation between direct '%ld' and its annotation '%ld'!\n", - size_t(direct), size_t(arch_direct_id)); + VTR_LOG_WARN( + "Override the annotation between direct '%ld' and its annotation " + "'%ld'!\n", + size_t(direct), size_t(arch_direct_id)); } direct_annotations_[direct] = arch_direct_id; } -void VprDeviceAnnotation::add_physical_lb_rr_graph(t_pb_graph_node* pb_graph_head, const LbRRGraph& lb_rr_graph) { +void VprDeviceAnnotation::add_physical_lb_rr_graph( + t_pb_graph_node* pb_graph_head, const LbRRGraph& lb_rr_graph) { /* Warn any override attempt */ if (0 < physical_lb_rr_graphs_.count(pb_graph_head)) { VTR_LOG_WARN("Override the physical lb_rr_graph for pb_graph_head '%s'!\n", @@ -665,28 +789,29 @@ void VprDeviceAnnotation::add_physical_lb_rr_graph(t_pb_graph_node* pb_graph_hea physical_lb_rr_graphs_[pb_graph_head] = lb_rr_graph; } -void VprDeviceAnnotation::add_physical_tile_pin2port_info_pair(t_physical_tile_type_ptr physical_tile, - const int& pin_index, - const BasicPort& port) { +void VprDeviceAnnotation::add_physical_tile_pin2port_info_pair( + t_physical_tile_type_ptr physical_tile, const int& pin_index, + const BasicPort& port) { physical_tile_pin2port_info_map_[physical_tile][pin_index] = port; } -void VprDeviceAnnotation::add_physical_tile_pin_subtile_index(t_physical_tile_type_ptr physical_tile, - const int& pin_index, - const int& subtile_index) { +void VprDeviceAnnotation::add_physical_tile_pin_subtile_index( + t_physical_tile_type_ptr physical_tile, const int& pin_index, + const int& subtile_index) { physical_tile_pin_subtile_indices_[physical_tile][pin_index] = subtile_index; } -void VprDeviceAnnotation::add_physical_tile_z_to_subtile_index(t_physical_tile_type_ptr physical_tile, - const int& subtile_z, - const int& subtile_index) { +void VprDeviceAnnotation::add_physical_tile_z_to_subtile_index( + t_physical_tile_type_ptr physical_tile, const int& subtile_z, + const int& subtile_index) { physical_tile_z_to_subtile_indices_[physical_tile][subtile_z] = subtile_index; } -void VprDeviceAnnotation::add_physical_tile_z_to_start_pin_index(t_physical_tile_type_ptr physical_tile, - const int& subtile_z, - const int& start_pin_index) { - physical_tile_z_to_start_pin_indices_[physical_tile][subtile_z] = start_pin_index; +void VprDeviceAnnotation::add_physical_tile_z_to_start_pin_index( + t_physical_tile_type_ptr physical_tile, const int& subtile_z, + const int& start_pin_index) { + physical_tile_z_to_start_pin_indices_[physical_tile][subtile_z] = + start_pin_index; } } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/vpr_device_annotation.h b/openfpga/src/annotation/vpr_device_annotation.h index 5f591bf5f..d5330d737 100644 --- a/openfpga/src/annotation/vpr_device_annotation.h +++ b/openfpga/src/annotation/vpr_device_annotation.h @@ -4,7 +4,7 @@ /******************************************************************** * Include header files required by the data structure definition *******************************************************************/ -#include +#include /* Header from vtrutil library */ #include "vtr_strong_id.h" @@ -13,10 +13,10 @@ #include "physical_types.h" /* Header from openfpgautil library */ -#include "openfpga_port.h" -#include "circuit_library.h" #include "arch_direct.h" +#include "circuit_library.h" #include "lb_rr_graph.h" +#include "openfpga_port.h" /* Begin namespace openfpga */ namespace openfpga { @@ -36,210 +36,238 @@ typedef vtr::StrongId PbGraphNodeId; * 4. what is the mode pointer that represents the physical mode for a pb_type *******************************************************************/ class VprDeviceAnnotation { - public: /* Constructor */ - VprDeviceAnnotation(); - public: /* Public accessors */ - bool is_physical_pb_type(t_pb_type* pb_type) const; - t_mode* physical_mode(t_pb_type* pb_type) const; - t_pb_type* physical_pb_type(t_pb_type* pb_type) const; - std::vector physical_pb_port(t_port* pb_port) const; - BasicPort physical_pb_port_range(t_port* operating_pb_port, + public: /* Constructor */ + VprDeviceAnnotation(); + + public: /* Public accessors */ + bool is_physical_pb_type(t_pb_type* pb_type) const; + t_mode* physical_mode(t_pb_type* pb_type) const; + t_pb_type* physical_pb_type(t_pb_type* pb_type) const; + std::vector physical_pb_port(t_port* pb_port) const; + BasicPort physical_pb_port_range(t_port* operating_pb_port, + t_port* physical_pb_port) const; + CircuitModelId pb_type_circuit_model(t_pb_type* physical_pb_type) const; + CircuitModelId interconnect_circuit_model( + t_interconnect* pb_interconnect) const; + e_interconnect interconnect_physical_type( + t_interconnect* pb_interconnect) const; + CircuitPortId pb_circuit_port(t_port* pb_port) const; + std::vector pb_type_mode_bits(t_pb_type* pb_type) const; + /* Get the unique index of a pb_graph_node */ + PbGraphNodeId pb_graph_node_unique_index( + t_pb_graph_node* pb_graph_node) const; + /* Get the pointer to a pb_graph node using an unique index */ + t_pb_graph_node* pb_graph_node(t_pb_type* pb_type, + const PbGraphNodeId& unique_index) const; + t_pb_graph_node* physical_pb_graph_node(t_pb_graph_node* pb_graph_node) const; + float physical_pb_type_index_factor(t_pb_type* pb_type) const; + int physical_pb_type_index_offset(t_pb_type* pb_type) const; + + int physical_pb_pin_initial_offset(t_port* operating_pb_port, t_port* physical_pb_port) const; - CircuitModelId pb_type_circuit_model(t_pb_type* physical_pb_type) const; - CircuitModelId interconnect_circuit_model(t_interconnect* pb_interconnect) const; - e_interconnect interconnect_physical_type(t_interconnect* pb_interconnect) const; - CircuitPortId pb_circuit_port(t_port* pb_port) const; - std::vector pb_type_mode_bits(t_pb_type* pb_type) const; - /* Get the unique index of a pb_graph_node */ - PbGraphNodeId pb_graph_node_unique_index(t_pb_graph_node* pb_graph_node) const; - /* Get the pointer to a pb_graph node using an unique index */ - t_pb_graph_node* pb_graph_node(t_pb_type* pb_type, const PbGraphNodeId& unique_index) const; - t_pb_graph_node* physical_pb_graph_node(t_pb_graph_node* pb_graph_node) const; - float physical_pb_type_index_factor(t_pb_type* pb_type) const; - int physical_pb_type_index_offset(t_pb_type* pb_type) const; - int physical_pb_pin_initial_offset(t_port* operating_pb_port, - t_port* physical_pb_port) const; + int physical_pb_pin_rotate_offset(t_port* operating_pb_port, + t_port* physical_pb_port) const; - int physical_pb_pin_rotate_offset(t_port* operating_pb_port, - t_port* physical_pb_port) const; + int physical_pb_port_rotate_offset(t_port* operating_pb_port, + t_port* physical_pb_port) const; - int physical_pb_port_rotate_offset(t_port* operating_pb_port, - t_port* physical_pb_port) const; - - /**This function returns an accumulated offset. Note that the - * accumulated offset is NOT the pin rotate offset specified by users - * It is an aggregation of the offset during pin pairing - * Each time, we manage to pair two pins, the accumulated offset will be incremented - * by the pin rotate offset value - * The accumulated offset will be reset to 0 when it exceeds the msb() of the physical port - */ - int physical_pb_pin_offset(t_port* operating_pb_port, - t_port* physical_pb_port) const; - int physical_pb_port_offset(t_port* operating_pb_port, - t_port* physical_pb_port) const; - t_pb_graph_pin* physical_pb_graph_pin(const t_pb_graph_pin* pb_graph_pin) const; - CircuitModelId rr_switch_circuit_model(const RRSwitchId& rr_switch) const; - CircuitModelId rr_segment_circuit_model(const RRSegmentId& rr_segment) const; - ArchDirectId direct_annotation(const size_t& direct) const; - LbRRGraph physical_lb_rr_graph(t_pb_graph_node* pb_graph_head) const; - BasicPort physical_tile_pin_port_info(t_physical_tile_type_ptr physical_tile, - const int& pin_index) const; - int physical_tile_pin_subtile_index(t_physical_tile_type_ptr physical_tile, + /**This function returns an accumulated offset. Note that the + * accumulated offset is NOT the pin rotate offset specified by users + * It is an aggregation of the offset during pin pairing + * Each time, we manage to pair two pins, the accumulated offset will be + * incremented by the pin rotate offset value The accumulated offset will be + * reset to 0 when it exceeds the msb() of the physical port + */ + int physical_pb_pin_offset(t_port* operating_pb_port, + t_port* physical_pb_port) const; + int physical_pb_port_offset(t_port* operating_pb_port, + t_port* physical_pb_port) const; + t_pb_graph_pin* physical_pb_graph_pin( + const t_pb_graph_pin* pb_graph_pin) const; + CircuitModelId rr_switch_circuit_model(const RRSwitchId& rr_switch) const; + CircuitModelId rr_segment_circuit_model(const RRSegmentId& rr_segment) const; + ArchDirectId direct_annotation(const size_t& direct) const; + LbRRGraph physical_lb_rr_graph(t_pb_graph_node* pb_graph_head) const; + BasicPort physical_tile_pin_port_info(t_physical_tile_type_ptr physical_tile, const int& pin_index) const; - int physical_tile_z_to_subtile_index(t_physical_tile_type_ptr physical_tile, + int physical_tile_pin_subtile_index(t_physical_tile_type_ptr physical_tile, + const int& pin_index) const; + int physical_tile_z_to_subtile_index(t_physical_tile_type_ptr physical_tile, + const int& subtile_z) const; + int physical_tile_z_to_start_pin_index(t_physical_tile_type_ptr physical_tile, const int& subtile_z) const; - int physical_tile_z_to_start_pin_index(t_physical_tile_type_ptr physical_tile, - const int& subtile_z) const; - public: /* Public mutators */ - void add_pb_type_physical_mode(t_pb_type* pb_type, t_mode* physical_mode); - void add_physical_pb_type(t_pb_type* operating_pb_type, t_pb_type* physical_pb_type); - void add_physical_pb_port(t_port* operating_pb_port, - t_port* physical_pb_port); - void add_physical_pb_port_range(t_port* operating_pb_port, - t_port* physical_pb_port, - const BasicPort& port_range); - void add_pb_type_circuit_model(t_pb_type* physical_pb_type, const CircuitModelId& circuit_model); - void add_interconnect_circuit_model(t_interconnect* pb_interconnect, const CircuitModelId& circuit_model); - void add_interconnect_physical_type(t_interconnect* pb_interconnect, const e_interconnect& physical_type); - void add_pb_circuit_port(t_port* pb_port, const CircuitPortId& circuit_port); - void add_pb_type_mode_bits(t_pb_type* pb_type, const std::vector& mode_bits); - void add_pb_graph_node_unique_index(t_pb_graph_node* pb_graph_node); - void add_physical_pb_graph_node(t_pb_graph_node* operating_pb_graph_node, - t_pb_graph_node* physical_pb_graph_node); - void add_physical_pb_type_index_factor(t_pb_type* pb_type, const float& factor); - void add_physical_pb_type_index_offset(t_pb_type* pb_type, const int& offset); - void add_physical_pb_pin_initial_offset(t_port* operating_pb_port, - t_port* physical_pb_port, - const int& offset); - void add_physical_pb_port_rotate_offset(t_port* operating_pb_port, - t_port* physical_pb_port, - const int& offset); - void accumulate_physical_pb_port_rotate_offset(t_port* operating_pb_port, - t_port* physical_pb_port); - void add_physical_pb_pin_rotate_offset(t_port* operating_pb_port, - t_port* physical_pb_port, - const int& offset); - void add_physical_pb_graph_pin(const t_pb_graph_pin* operating_pb_graph_pin, t_pb_graph_pin* physical_pb_graph_pin); - void add_rr_switch_circuit_model(const RRSwitchId& rr_switch, const CircuitModelId& circuit_model); - void add_rr_segment_circuit_model(const RRSegmentId& rr_segment, const CircuitModelId& circuit_model); - void add_direct_annotation(const size_t& direct, const ArchDirectId& arch_direct_id); - void add_physical_lb_rr_graph(t_pb_graph_node* pb_graph_head, const LbRRGraph& lb_rr_graph); - void add_physical_tile_pin2port_info_pair(t_physical_tile_type_ptr physical_tile, - const int& pin_index, - const BasicPort& port); - void add_physical_tile_pin_subtile_index(t_physical_tile_type_ptr physical_tile, - const int& pin_index, - const int& subtile_index); - void add_physical_tile_z_to_subtile_index(t_physical_tile_type_ptr physical_tile, - const int& subtile_z, - const int& subtile_index); - void add_physical_tile_z_to_start_pin_index(t_physical_tile_type_ptr physical_tile, - const int& subtile_z, - const int& start_pin_index); - private: /* Internal data */ - /* Pair a regular pb_type to its physical pb_type */ - std::map physical_pb_types_; - std::map physical_pb_type_index_factors_; - std::map physical_pb_type_index_offsets_; - /* Pair a physical mode for a pb_type - * Note: - * - the physical mode MUST be a child mode of the pb_type - * - the pb_type MUST be a physical pb_type itself - */ - std::map physical_pb_modes_; + public: /* Public mutators */ + void add_pb_type_physical_mode(t_pb_type* pb_type, t_mode* physical_mode); + void add_physical_pb_type(t_pb_type* operating_pb_type, + t_pb_type* physical_pb_type); + void add_physical_pb_port(t_port* operating_pb_port, + t_port* physical_pb_port); + void add_physical_pb_port_range(t_port* operating_pb_port, + t_port* physical_pb_port, + const BasicPort& port_range); + void add_pb_type_circuit_model(t_pb_type* physical_pb_type, + const CircuitModelId& circuit_model); + void add_interconnect_circuit_model(t_interconnect* pb_interconnect, + const CircuitModelId& circuit_model); + void add_interconnect_physical_type(t_interconnect* pb_interconnect, + const e_interconnect& physical_type); + void add_pb_circuit_port(t_port* pb_port, const CircuitPortId& circuit_port); + void add_pb_type_mode_bits(t_pb_type* pb_type, + const std::vector& mode_bits); + void add_pb_graph_node_unique_index(t_pb_graph_node* pb_graph_node); + void add_physical_pb_graph_node(t_pb_graph_node* operating_pb_graph_node, + t_pb_graph_node* physical_pb_graph_node); + void add_physical_pb_type_index_factor(t_pb_type* pb_type, + const float& factor); + void add_physical_pb_type_index_offset(t_pb_type* pb_type, const int& offset); + void add_physical_pb_pin_initial_offset(t_port* operating_pb_port, + t_port* physical_pb_port, + const int& offset); + void add_physical_pb_port_rotate_offset(t_port* operating_pb_port, + t_port* physical_pb_port, + const int& offset); + void accumulate_physical_pb_port_rotate_offset(t_port* operating_pb_port, + t_port* physical_pb_port); + void add_physical_pb_pin_rotate_offset(t_port* operating_pb_port, + t_port* physical_pb_port, + const int& offset); + void add_physical_pb_graph_pin(const t_pb_graph_pin* operating_pb_graph_pin, + t_pb_graph_pin* physical_pb_graph_pin); + void add_rr_switch_circuit_model(const RRSwitchId& rr_switch, + const CircuitModelId& circuit_model); + void add_rr_segment_circuit_model(const RRSegmentId& rr_segment, + const CircuitModelId& circuit_model); + void add_direct_annotation(const size_t& direct, + const ArchDirectId& arch_direct_id); + void add_physical_lb_rr_graph(t_pb_graph_node* pb_graph_head, + const LbRRGraph& lb_rr_graph); + void add_physical_tile_pin2port_info_pair( + t_physical_tile_type_ptr physical_tile, const int& pin_index, + const BasicPort& port); + void add_physical_tile_pin_subtile_index( + t_physical_tile_type_ptr physical_tile, const int& pin_index, + const int& subtile_index); + void add_physical_tile_z_to_subtile_index( + t_physical_tile_type_ptr physical_tile, const int& subtile_z, + const int& subtile_index); + void add_physical_tile_z_to_start_pin_index( + t_physical_tile_type_ptr physical_tile, const int& subtile_z, + const int& start_pin_index); - /* Pair a physical pb_type to its circuit model - * Note: - * - the pb_type MUST be a physical pb_type itself - */ - std::map pb_type_circuit_models_; + private: /* Internal data */ + /* Pair a regular pb_type to its physical pb_type */ + std::map physical_pb_types_; + std::map physical_pb_type_index_factors_; + std::map physical_pb_type_index_offsets_; - /* Pair a interconnect of a physical pb_type to its circuit model - * Note: - * - the pb_type MUST be a physical pb_type itself - */ - std::map interconnect_circuit_models_; + /* Pair a physical mode for a pb_type + * Note: + * - the physical mode MUST be a child mode of the pb_type + * - the pb_type MUST be a physical pb_type itself + */ + std::map physical_pb_modes_; - /* Physical type of interconnect - * Note: - * - only applicable to an interconnect belongs to physical mode - */ - std::map interconnect_physical_types_; + /* Pair a physical pb_type to its circuit model + * Note: + * - the pb_type MUST be a physical pb_type itself + */ + std::map pb_type_circuit_models_; - /* Pair a pb_type to its mode selection bits - * - if the pb_type is a physical pb_type, the mode bits are the default mode - * where the physical pb_type will operate when used - * - if the pb_type is an operating pb_type, the mode bits will be applied - * when the operating pb_type is used by packer - */ - std::map> pb_type_mode_bits_; + /* Pair a interconnect of a physical pb_type to its circuit model + * Note: + * - the pb_type MUST be a physical pb_type itself + */ + std::map interconnect_circuit_models_; - /* Pair a pb_port to its physical pb_port - * Note: - * - the parent of physical pb_port MUST be a physical pb_type - */ - std::map> physical_pb_ports_; - std::map> physical_pb_pin_initial_offsets_; - std::map> physical_pb_pin_rotate_offsets_; - std::map> physical_pb_port_rotate_offsets_; + /* Physical type of interconnect + * Note: + * - only applicable to an interconnect belongs to physical mode + */ + std::map interconnect_physical_types_; - /* Accumulated offsets for a physical pb port, just for internal usage */ - std::map> physical_pb_port_offsets_; - /* Accumulated offsets for a physical pb_graph_pin, just for internal usage */ - std::map> physical_pb_pin_offsets_; + /* Pair a pb_type to its mode selection bits + * - if the pb_type is a physical pb_type, the mode bits are the default mode + * where the physical pb_type will operate when used + * - if the pb_type is an operating pb_type, the mode bits will be applied + * when the operating pb_type is used by packer + */ + std::map> pb_type_mode_bits_; - /* Pair a pb_port to its LSB and MSB of a physical pb_port - * Note: - * - the LSB and MSB MUST be in range of the physical pb_port - */ - std::map> physical_pb_port_ranges_; + /* Pair a pb_port to its physical pb_port + * Note: + * - the parent of physical pb_port MUST be a physical pb_type + */ + std::map> physical_pb_ports_; + std::map> physical_pb_pin_initial_offsets_; + std::map> physical_pb_pin_rotate_offsets_; + std::map> physical_pb_port_rotate_offsets_; - /* Pair a pb_port to a circuit port in circuit model - * Note: - * - the parent of physical pb_port MUST be a physical pb_type - */ - std::map pb_circuit_ports_; + /* Accumulated offsets for a physical pb port, just for internal usage */ + std::map> physical_pb_port_offsets_; + /* Accumulated offsets for a physical pb_graph_pin, just for internal usage */ + std::map> physical_pb_pin_offsets_; - /* Pair each pb_graph_node to an unique index in the graph - * The unique index if the index in the array of t_pb_graph_node* - */ - std::map> pb_graph_node_unique_index_; + /* Pair a pb_port to its LSB and MSB of a physical pb_port + * Note: + * - the LSB and MSB MUST be in range of the physical pb_port + */ + std::map> physical_pb_port_ranges_; - /* Pair a pb_graph_node to a physical pb_graph_node - * Note: - * - the pb_type of physical pb_graph_node must be a physical pb_type - */ - std::map physical_pb_graph_nodes_; + /* Pair a pb_port to a circuit port in circuit model + * Note: + * - the parent of physical pb_port MUST be a physical pb_type + */ + std::map pb_circuit_ports_; - /* Pair a pb_graph_pin to a physical pb_graph_pin */ - std::map physical_pb_graph_pins_; + /* Pair each pb_graph_node to an unique index in the graph + * The unique index if the index in the array of t_pb_graph_node* + */ + std::map> + pb_graph_node_unique_index_; - /* Pair a Routing Resource Switch (rr_switch) to a circuit model */ - std::map rr_switch_circuit_models_; + /* Pair a pb_graph_node to a physical pb_graph_node + * Note: + * - the pb_type of physical pb_graph_node must be a physical pb_type + */ + std::map physical_pb_graph_nodes_; - /* Pair a Routing Segment (rr_segment) to a circuit model */ - std::map rr_segment_circuit_models_; + /* Pair a pb_graph_pin to a physical pb_graph_pin */ + std::map physical_pb_graph_pins_; - /* Pair a direct connection (direct) to a annotation which contains circuit model id */ - std::map direct_annotations_; + /* Pair a Routing Resource Switch (rr_switch) to a circuit model */ + std::map rr_switch_circuit_models_; - /* Logical type routing resource graphs built from physical modes */ - std::map physical_lb_rr_graphs_; + /* Pair a Routing Segment (rr_segment) to a circuit model */ + std::map rr_segment_circuit_models_; - /* A fast look-up from pin index in physical tile to physical tile port */ - std::map> physical_tile_pin2port_info_map_; - /* A fast look-up from pin index in physical tile to sub tile index */ - std::map> physical_tile_pin_subtile_indices_; - /* A fast look-up from z (a valid instance index considering all the sub tiles in a given physical tile) to the index in sub tile array - * The instance index starts from 0 to the sum of the capacity of each sub tile - */ - std::map> physical_tile_z_to_subtile_indices_; - /* A fast look-up from z (a valid instance index considering all the sub tiles in a given physical tile) to the index of the first pin in a given physcial tile - * The instance index starts from 0 to the sum of the capacity of each sub tile - */ - std::map> physical_tile_z_to_start_pin_indices_; + /* Pair a direct connection (direct) to a annotation which contains circuit + * model id */ + std::map direct_annotations_; + + /* Logical type routing resource graphs built from physical modes */ + std::map physical_lb_rr_graphs_; + + /* A fast look-up from pin index in physical tile to physical tile port */ + std::map> + physical_tile_pin2port_info_map_; + /* A fast look-up from pin index in physical tile to sub tile index */ + std::map> + physical_tile_pin_subtile_indices_; + /* A fast look-up from z (a valid instance index considering all the sub tiles + * in a given physical tile) to the index in sub tile array The instance index + * starts from 0 to the sum of the capacity of each sub tile + */ + std::map> + physical_tile_z_to_subtile_indices_; + /* A fast look-up from z (a valid instance index considering all the sub tiles + * in a given physical tile) to the index of the first pin in a given physcial + * tile The instance index starts from 0 to the sum of the capacity of each + * sub tile + */ + std::map> + physical_tile_z_to_start_pin_indices_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/vpr_netlist_annotation.cpp b/openfpga/src/annotation/vpr_netlist_annotation.cpp index 0d9d5443d..11ee6d4ec 100644 --- a/openfpga/src/annotation/vpr_netlist_annotation.cpp +++ b/openfpga/src/annotation/vpr_netlist_annotation.cpp @@ -1,26 +1,26 @@ /************************************************************************ * Member functions for class VprNetlistAnnotation ***********************************************************************/ -#include "vtr_log.h" -#include "vtr_assert.h" #include "vpr_netlist_annotation.h" +#include "vtr_assert.h" +#include "vtr_log.h" + /* namespace openfpga begins */ namespace openfpga { /************************************************************************ * Constructors ***********************************************************************/ -VprNetlistAnnotation::VprNetlistAnnotation() { - return; -} +VprNetlistAnnotation::VprNetlistAnnotation() { return; } /************************************************************************ * Public accessors ***********************************************************************/ bool VprNetlistAnnotation::is_block_renamed(const AtomBlockId& block) const { /* Ensure that the pb_type is in the list */ - std::map::const_iterator it = block_names_.find(block); + std::map::const_iterator it = + block_names_.find(block); return it != block_names_.end(); } @@ -43,9 +43,11 @@ std::string VprNetlistAnnotation::net_name(const AtomNetId& net) const { /************************************************************************ * Public mutators ***********************************************************************/ -void VprNetlistAnnotation::rename_block(const AtomBlockId& block, const std::string& name) { +void VprNetlistAnnotation::rename_block(const AtomBlockId& block, + const std::string& name) { /* Warn any override attempt */ - std::map::const_iterator it = block_names_.find(block); + std::map::const_iterator it = + block_names_.find(block); if (it != block_names_.end()) { VTR_LOG_WARN("Override the block with name '%s' in netlist annotation!\n", name.c_str()); @@ -54,7 +56,8 @@ void VprNetlistAnnotation::rename_block(const AtomBlockId& block, const std::str block_names_[block] = name; } -void VprNetlistAnnotation::rename_net(const AtomNetId& net, const std::string& name) { +void VprNetlistAnnotation::rename_net(const AtomNetId& net, + const std::string& name) { /* Warn any override attempt */ std::map::const_iterator it = net_names_.find(net); if (it != net_names_.end()) { diff --git a/openfpga/src/annotation/vpr_netlist_annotation.h b/openfpga/src/annotation/vpr_netlist_annotation.h index 3b8bbd16f..454f1f122 100644 --- a/openfpga/src/annotation/vpr_netlist_annotation.h +++ b/openfpga/src/annotation/vpr_netlist_annotation.h @@ -4,7 +4,7 @@ /******************************************************************** * Include header files required by the data structure definition *******************************************************************/ -#include +#include /* Header from vpr library */ #include "atom_netlist.h" @@ -22,20 +22,23 @@ namespace openfpga { * 4. what is the mode pointer that represents the physical mode for a pb_type *******************************************************************/ class VprNetlistAnnotation { - public: /* Constructor */ - VprNetlistAnnotation(); - public: /* Public accessors */ - bool is_block_renamed(const AtomBlockId& block) const; - std::string block_name(const AtomBlockId& block) const; - bool is_net_renamed(const AtomNetId& net) const; - std::string net_name(const AtomNetId& net) const; - public: /* Public mutators */ - void rename_block(const AtomBlockId& block, const std::string& name); - void rename_net(const AtomNetId& net, const std::string& name); - private: /* Internal data */ - /* Pair a regular pb_type to its physical pb_type */ - std::map block_names_; - std::map net_names_; + public: /* Constructor */ + VprNetlistAnnotation(); + + public: /* Public accessors */ + bool is_block_renamed(const AtomBlockId& block) const; + std::string block_name(const AtomBlockId& block) const; + bool is_net_renamed(const AtomNetId& net) const; + std::string net_name(const AtomNetId& net) const; + + public: /* Public mutators */ + void rename_block(const AtomBlockId& block, const std::string& name); + void rename_net(const AtomNetId& net, const std::string& name); + + private: /* Internal data */ + /* Pair a regular pb_type to its physical pb_type */ + std::map block_names_; + std::map net_names_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/vpr_placement_annotation.cpp b/openfpga/src/annotation/vpr_placement_annotation.cpp index 779707250..9d7e73836 100644 --- a/openfpga/src/annotation/vpr_placement_annotation.cpp +++ b/openfpga/src/annotation/vpr_placement_annotation.cpp @@ -1,10 +1,11 @@ /************************************************************************ * Member functions for class VprPlacementAnnotation ***********************************************************************/ -#include "vtr_log.h" -#include "vtr_assert.h" #include "vpr_placement_annotation.h" +#include "vtr_assert.h" +#include "vtr_log.h" + /* namespace openfpga begins */ namespace openfpga { @@ -15,7 +16,8 @@ namespace openfpga { /************************************************************************ * Public accessors ***********************************************************************/ -std::vector VprPlacementAnnotation::grid_blocks(const vtr::Point& grid_coord) const { +std::vector VprPlacementAnnotation::grid_blocks( + const vtr::Point& grid_coord) const { return blocks_[grid_coord.x()][grid_coord.y()]; } @@ -30,18 +32,19 @@ void VprPlacementAnnotation::init_mapped_blocks(const DeviceGrid& grids) { for (size_t x = 0; x < grids.width(); ++x) { for (size_t y = 0; y < grids.height(); ++y) { /* Deposit invalid ids and we will fill later */ - blocks_[x][y].resize(grids[x][y].type->capacity, ClusterBlockId::INVALID()); + blocks_[x][y].resize(grids[x][y].type->capacity, + ClusterBlockId::INVALID()); } } } -void VprPlacementAnnotation::add_mapped_block(const vtr::Point& grid_coord, - const size_t& z, - const ClusterBlockId& mapped_block) { +void VprPlacementAnnotation::add_mapped_block( + const vtr::Point& grid_coord, const size_t& z, + const ClusterBlockId& mapped_block) { VTR_ASSERT(z < grid_blocks(grid_coord).size()); if (ClusterBlockId::INVALID() != blocks_[grid_coord.x()][grid_coord.y()][z]) { - VTR_LOG("Override mapped blocks at grid[%lu][%lu][%lu]!\n", - grid_coord.x(), grid_coord.y(), z); + VTR_LOG("Override mapped blocks at grid[%lu][%lu][%lu]!\n", grid_coord.x(), + grid_coord.y(), z); } blocks_[grid_coord.x()][grid_coord.y()][z] = mapped_block; } diff --git a/openfpga/src/annotation/vpr_placement_annotation.h b/openfpga/src/annotation/vpr_placement_annotation.h index 6a5e9c134..85a5194a2 100644 --- a/openfpga/src/annotation/vpr_placement_annotation.h +++ b/openfpga/src/annotation/vpr_placement_annotation.h @@ -4,14 +4,14 @@ /******************************************************************** * Include header files required by the data structure definition *******************************************************************/ -#include +#include /* Header from vtrutil library */ #include "vtr_geometry.h" /* Header from vpr library */ -#include "device_grid.h" #include "clustered_netlist.h" +#include "device_grid.h" /* Begin namespace openfpga */ namespace openfpga { @@ -21,26 +21,29 @@ namespace openfpga { * in VPR context *******************************************************************/ class VprPlacementAnnotation { - public: /* Public accessors */ - std::vector grid_blocks(const vtr::Point& grid_coord) const; - public: /* Public mutators */ - void init_mapped_blocks(const DeviceGrid& grids); - void add_mapped_block(const vtr::Point& grid_coord, - const size_t& z, const ClusterBlockId& mapped_block); - private: /* Internal data */ - /* A direct mapping show each mapped/unmapped blocks in grids - * The blocks_ array represents each grid on the FPGA fabric - * For example, block_[x][y] showed the mapped/unmapped blocks - * at grid[x][y]. The third coordinate 'z' is the index of the same - * type of blocks in the grids. This is mainly applied to I/O - * blocks where you may have >1 I/O in a grid - * - * Note that this is different from the grid blocks in PlacementContext - * VPR considers only mapped blocks while this annotation - * considers both unmapped and mapped blocks - * Unmapped blocks will be labelled as an invalid id in the vector - */ - vtr::Matrix> blocks_; + public: /* Public accessors */ + std::vector grid_blocks( + const vtr::Point& grid_coord) const; + + public: /* Public mutators */ + void init_mapped_blocks(const DeviceGrid& grids); + void add_mapped_block(const vtr::Point& grid_coord, const size_t& z, + const ClusterBlockId& mapped_block); + + private: /* Internal data */ + /* A direct mapping show each mapped/unmapped blocks in grids + * The blocks_ array represents each grid on the FPGA fabric + * For example, block_[x][y] showed the mapped/unmapped blocks + * at grid[x][y]. The third coordinate 'z' is the index of the same + * type of blocks in the grids. This is mainly applied to I/O + * blocks where you may have >1 I/O in a grid + * + * Note that this is different from the grid blocks in PlacementContext + * VPR considers only mapped blocks while this annotation + * considers both unmapped and mapped blocks + * Unmapped blocks will be labelled as an invalid id in the vector + */ + vtr::Matrix> blocks_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/vpr_routing_annotation.cpp b/openfpga/src/annotation/vpr_routing_annotation.cpp index 74ca95098..8af4263c8 100644 --- a/openfpga/src/annotation/vpr_routing_annotation.cpp +++ b/openfpga/src/annotation/vpr_routing_annotation.cpp @@ -1,19 +1,18 @@ /************************************************************************ * Member functions for class VprRoutingAnnotation ***********************************************************************/ -#include "vtr_log.h" -#include "vtr_assert.h" #include "vpr_routing_annotation.h" +#include "vtr_assert.h" +#include "vtr_log.h" + /* namespace openfpga begins */ namespace openfpga { /************************************************************************ * Constructors ***********************************************************************/ -VprRoutingAnnotation::VprRoutingAnnotation() { - return; -} +VprRoutingAnnotation::VprRoutingAnnotation() { return; } /************************************************************************ * Public accessors @@ -24,7 +23,8 @@ ClusterNetId VprRoutingAnnotation::rr_node_net(const RRNodeId& rr_node) const { return rr_node_nets_[rr_node]; } -RRNodeId VprRoutingAnnotation::rr_node_prev_node(const RRNodeId& rr_node) const { +RRNodeId VprRoutingAnnotation::rr_node_prev_node( + const RRNodeId& rr_node) const { /* Ensure that the node_id is in the list */ VTR_ASSERT(size_t(rr_node) < rr_node_nets_.size()); return rr_node_prev_nodes_[rr_node]; @@ -43,10 +43,12 @@ void VprRoutingAnnotation::set_rr_node_net(const RRNodeId& rr_node, /* Ensure that the node_id is in the list */ VTR_ASSERT(size_t(rr_node) < rr_node_nets_.size()); /* Warn any override attempt */ - if ( (ClusterNetId::INVALID() != rr_node_nets_[rr_node]) - && (net_id != rr_node_nets_[rr_node])) { - VTR_LOG_WARN("Override the net '%ld' by net '%ld' for node '%ld' with in routing context annotation!\n", - size_t(rr_node_nets_[rr_node]), size_t(net_id), size_t(rr_node)); + if ((ClusterNetId::INVALID() != rr_node_nets_[rr_node]) && + (net_id != rr_node_nets_[rr_node])) { + VTR_LOG_WARN( + "Override the net '%ld' by net '%ld' for node '%ld' with in routing " + "context annotation!\n", + size_t(rr_node_nets_[rr_node]), size_t(net_id), size_t(rr_node)); } rr_node_nets_[rr_node] = net_id; @@ -58,12 +60,14 @@ void VprRoutingAnnotation::set_rr_node_prev_node(const RRGraphView& rr_graph, /* Ensure that the node_id is in the list */ VTR_ASSERT(size_t(rr_node) < rr_node_nets_.size()); /* Warn any override attempt */ - if ( (RRNodeId::INVALID() != rr_node_prev_nodes_[rr_node]) - && (prev_node != rr_node_prev_nodes_[rr_node])) { - VTR_LOG_WARN("Override the previous node '%s' by previous node '%s' for node '%s' with in routing context annotation!\n", - rr_graph.node_coordinate_to_string(rr_node_prev_nodes_[rr_node]).c_str(), - rr_graph.node_coordinate_to_string(prev_node).c_str(), - rr_graph.node_coordinate_to_string(rr_node).c_str()); + if ((RRNodeId::INVALID() != rr_node_prev_nodes_[rr_node]) && + (prev_node != rr_node_prev_nodes_[rr_node])) { + VTR_LOG_WARN( + "Override the previous node '%s' by previous node '%s' for node '%s' " + "with in routing context annotation!\n", + rr_graph.node_coordinate_to_string(rr_node_prev_nodes_[rr_node]).c_str(), + rr_graph.node_coordinate_to_string(prev_node).c_str(), + rr_graph.node_coordinate_to_string(rr_node).c_str()); } rr_node_prev_nodes_[rr_node] = prev_node; diff --git a/openfpga/src/annotation/vpr_routing_annotation.h b/openfpga/src/annotation/vpr_routing_annotation.h index 5e0f4a2c1..47a470abd 100644 --- a/openfpga/src/annotation/vpr_routing_annotation.h +++ b/openfpga/src/annotation/vpr_routing_annotation.h @@ -4,12 +4,12 @@ /******************************************************************** * Include header files required by the data structure definition *******************************************************************/ -#include +#include /* Header from vpr library */ -#include "vtr_vector.h" #include "clustered_netlist_fwd.h" #include "rr_graph_view.h" +#include "vtr_vector.h" /* Begin namespace openfpga */ namespace openfpga { @@ -24,24 +24,26 @@ namespace openfpga { * 4. what is the mode pointer that represents the physical mode for a pb_type *******************************************************************/ class VprRoutingAnnotation { - public: /* Constructor */ - VprRoutingAnnotation(); - public: /* Public accessors */ - ClusterNetId rr_node_net(const RRNodeId& rr_node) const; - RRNodeId rr_node_prev_node(const RRNodeId& rr_node) const; - public: /* Public mutators */ - void init(const RRGraphView& rr_graph); - void set_rr_node_net(const RRNodeId& rr_node, - const ClusterNetId& net_id); - void set_rr_node_prev_node(const RRGraphView& rr_graph, - const RRNodeId& rr_node, - const RRNodeId& prev_node); - private: /* Internal data */ - /* Clustered net ids mapped to each rr_node */ - vtr::vector rr_node_nets_; + public: /* Constructor */ + VprRoutingAnnotation(); - /* Previous rr_node driving each rr_node */ - vtr::vector rr_node_prev_nodes_; + public: /* Public accessors */ + ClusterNetId rr_node_net(const RRNodeId& rr_node) const; + RRNodeId rr_node_prev_node(const RRNodeId& rr_node) const; + + public: /* Public mutators */ + void init(const RRGraphView& rr_graph); + void set_rr_node_net(const RRNodeId& rr_node, const ClusterNetId& net_id); + void set_rr_node_prev_node(const RRGraphView& rr_graph, + const RRNodeId& rr_node, + const RRNodeId& prev_node); + + private: /* Internal data */ + /* Clustered net ids mapped to each rr_node */ + vtr::vector rr_node_nets_; + + /* Previous rr_node driving each rr_node */ + vtr::vector rr_node_prev_nodes_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/write_xml_device_rr_gsb.cpp b/openfpga/src/annotation/write_xml_device_rr_gsb.cpp index d4cd060ca..89b31d9c6 100644 --- a/openfpga/src/annotation/write_xml_device_rr_gsb.cpp +++ b/openfpga/src/annotation/write_xml_device_rr_gsb.cpp @@ -1,33 +1,31 @@ /*************************************************************************************** - * Output internal structure of DeviceRRGSB to XML format + * Output internal structure of DeviceRRGSB to XML format ***************************************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_side_manager.h" +#include "build_routing_module_utils.h" #include "openfpga_digest.h" - #include "openfpga_naming.h" #include "openfpga_rr_graph_utils.h" - -#include "build_routing_module_utils.h" +#include "openfpga_side_manager.h" #include "write_xml_device_rr_gsb.h" /* begin namespace openfpga */ namespace openfpga { /*************************************************************************************** - * Output the input pin of Programmable Blocks, e.g., CLBs inside a GSB to XML format + * Output the input pin of Programmable Blocks, e.g., CLBs inside a GSB to XML + *format ***************************************************************************************/ -static -void write_rr_gsb_ipin_connection_to_xml(std::fstream& fp, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const enum e_side& gsb_side, - const bool& include_rr_info) { +static void write_rr_gsb_ipin_connection_to_xml(std::fstream& fp, + const RRGraphView& rr_graph, + const RRGSB& rr_gsb, + const enum e_side& gsb_side, + const bool& include_rr_info) { /* Validate the file stream */ valid_file_stream(fp); @@ -37,15 +35,13 @@ void write_rr_gsb_ipin_connection_to_xml(std::fstream& fp, const RRNodeId& cur_rr_node = rr_gsb.get_ipin_node(gsb_side, inode); /* General information of this IPIN */ fp << "\t<" << rr_node_typename[rr_graph.node_type(cur_rr_node)] - << " side=\"" << gsb_side_manager.to_string() - << "\" index=\"" << inode; + << " side=\"" << gsb_side_manager.to_string() << "\" index=\"" << inode; if (include_rr_info) { - fp << "\" node_id=\"" << size_t(cur_rr_node); + fp << "\" node_id=\"" << size_t(cur_rr_node); } - std::vector driver_rr_edges = rr_gsb.get_ipin_node_in_edges(rr_graph, gsb_side, inode); - fp << "\" mux_size=\"" << driver_rr_edges.size() - << "\">" - << std::endl; + std::vector driver_rr_edges = + rr_gsb.get_ipin_node_in_edges(rr_graph, gsb_side, inode); + fp << "\" mux_size=\"" << driver_rr_edges.size() << "\">" << std::endl; /* General information of each driving nodes */ for (const RREdgeId& edge : driver_rr_edges) { RRNodeId driver_node = rr_graph.edge_src_node(edge); @@ -57,43 +53,40 @@ void write_rr_gsb_ipin_connection_to_xml(std::fstream& fp, enum e_side chan_side = rr_gsb.get_cb_chan_side(gsb_side); SideManager chan_side_manager(chan_side); - /* For channel node, we do not know the node direction + /* For channel node, we do not know the node direction * But we are pretty sure it is either IN_PORT or OUT_PORT * So we just try and find what is valid */ - int driver_node_index = rr_gsb.get_chan_node_index(chan_side, driver_node); + int driver_node_index = + rr_gsb.get_chan_node_index(chan_side, driver_node); /* We must have a valide node index */ VTR_ASSERT(-1 != driver_node_index); - const RRSegmentId& des_segment_id = rr_gsb.get_chan_node_segment(chan_side, driver_node_index); + const RRSegmentId& des_segment_id = + rr_gsb.get_chan_node_segment(chan_side, driver_node_index); - fp << "\t\t" - << std::endl; + fp << "\" index=\"" << driver_node_index << "\" segment_id=\"" + << size_t(des_segment_id) << "\"/>" << std::endl; } - fp << "\t" - << std::endl; + fp << "\t" + << std::endl; } } /*************************************************************************************** - * Output the routing tracks connections inside a GSB to XML format + * Output the routing tracks connections inside a GSB to XML format ***************************************************************************************/ -static -void write_rr_gsb_chan_connection_to_xml(std::fstream& fp, - const DeviceGrid& vpr_device_grid, - const VprDeviceAnnotation& vpr_device_annotation, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const enum e_side& gsb_side, - const bool& include_rr_info) { +static void write_rr_gsb_chan_connection_to_xml( + std::fstream& fp, const DeviceGrid& vpr_device_grid, + const VprDeviceAnnotation& vpr_device_annotation, const RRGraphView& rr_graph, + const RRGSB& rr_gsb, const enum e_side& gsb_side, + const bool& include_rr_info) { /* Validate the file stream */ valid_file_stream(fp); @@ -107,111 +100,123 @@ void write_rr_gsb_chan_connection_to_xml(std::fstream& fp, } /* Output drivers */ const RRNodeId& cur_rr_node = rr_gsb.get_chan_node(gsb_side, inode); - std::vector driver_rr_edges = rr_gsb.get_chan_node_in_edges(rr_graph, gsb_side, inode); + std::vector driver_rr_edges = + rr_gsb.get_chan_node_in_edges(rr_graph, gsb_side, inode); /* Output node information: location, index, side */ - const RRSegmentId& src_segment_id = rr_gsb.get_chan_node_segment(gsb_side, inode); + const RRSegmentId& src_segment_id = + rr_gsb.get_chan_node_segment(gsb_side, inode); - /* Check if this node is directly connected to the node on the opposite side */ + /* Check if this node is directly connected to the node on the opposite side + */ if (true == rr_gsb.is_sb_node_passing_wire(rr_graph, gsb_side, inode)) { driver_rr_edges.clear(); } t_rr_type cur_node_type = rr_graph.node_type(cur_rr_node); - fp << "\t<" << rr_node_typename[cur_node_type] - << " side=\"" << gsb_side_manager.to_string() - << "\" index=\"" << inode; + fp << "\t<" << rr_node_typename[cur_node_type] << " side=\"" + << gsb_side_manager.to_string() << "\" index=\"" << inode; if (include_rr_info) { - fp << "\" node_id=\"" << size_t(cur_rr_node) - << "\" segment_id=\"" << size_t(src_segment_id) - << "\" segment_name=\"" << rr_graph.rr_segments(src_segment_id).name; + fp << "\" node_id=\"" << size_t(cur_rr_node) << "\" segment_id=\"" + << size_t(src_segment_id) << "\" segment_name=\"" + << rr_graph.rr_segments(src_segment_id).name; } fp << "\" mux_size=\"" << driver_rr_edges.size(); if (include_rr_info) { - fp << "\" sb_module_pin_name=\"" << generate_sb_module_track_port_name(cur_node_type, gsb_side, OUT_PORT); + fp << "\" sb_module_pin_name=\"" + << generate_sb_module_track_port_name(cur_node_type, gsb_side, + OUT_PORT); } - fp << "\">" - << std::endl; + fp << "\">" << std::endl; /* Direct connection: output the node on the opposite side */ if (0 == driver_rr_edges.size()) { - SideManager oppo_side = gsb_side_manager.get_opposite(); + SideManager oppo_side = gsb_side_manager.get_opposite(); fp << "\t\t" - << std::endl; + fp << "\"/>" << std::endl; } else { for (const RREdgeId& driver_rr_edge : driver_rr_edges) { const RRNodeId& driver_rr_node = rr_graph.edge_src_node(driver_rr_edge); e_side driver_node_side = NUM_SIDES; int driver_node_index = -1; - rr_gsb.get_node_side_and_index(rr_graph, driver_rr_node, IN_PORT, driver_node_side, driver_node_index); + rr_gsb.get_node_side_and_index(rr_graph, driver_rr_node, IN_PORT, + driver_node_side, driver_node_index); VTR_ASSERT(-1 != driver_node_index); SideManager driver_side(driver_node_side); if (OPIN == rr_graph.node_type(driver_rr_node)) { - SideManager grid_side(get_rr_graph_single_node_side(rr_graph, driver_rr_node)); + SideManager grid_side( + get_rr_graph_single_node_side(rr_graph, driver_rr_node)); fp << "\t\t" - << std::endl; + fp << "\"/>" << std::endl; } else { - const RRSegmentId& des_segment_id = rr_gsb.get_chan_node_segment(driver_node_side, driver_node_index); - fp << "\t\t" - << std::endl; + fp << "\"/>" << std::endl; } - } + } } - fp << "\t" - << std::endl; + fp << "\t" + << std::endl; } } /*************************************************************************************** - * Output internal structure (only the switch block part) of a RRGSB to XML format + * Output internal structure (only the switch block part) of a RRGSB to XML + *format ***************************************************************************************/ -static -void write_rr_switch_block_to_xml(const std::string fname_prefix, - const DeviceGrid& vpr_device_grid, - const VprDeviceAnnotation& vpr_device_annotation, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const RRGSBWriterOption& options) { - +static void write_rr_switch_block_to_xml( + const std::string fname_prefix, const DeviceGrid& vpr_device_grid, + const VprDeviceAnnotation& vpr_device_annotation, const RRGraphView& rr_graph, + const RRGSB& rr_gsb, const RRGSBWriterOption& options) { /* Prepare file name */ std::string fname(fname_prefix); vtr::Point sb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); std::string curr_sb_name = generate_switch_block_module_name(sb_coordinate); - fname += curr_sb_name; + fname += curr_sb_name; fname += ".xml"; /* If there is a list of gsb list, we skip those which are not in the list */ std::vector include_gsb_names = options.include_gsb_names(); - if (!include_gsb_names.empty() && include_gsb_names.end() == std::find(include_gsb_names.begin(), include_gsb_names.end(), curr_sb_name)) { + if (!include_gsb_names.empty() && + include_gsb_names.end() == std::find(include_gsb_names.begin(), + include_gsb_names.end(), + curr_sb_name)) { return; } @@ -231,41 +236,47 @@ void write_rr_switch_block_to_xml(const std::string fname_prefix, fp << "" << std::endl; - /* Output each side */ + /* Output each side */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager gsb_side_manager(side); enum e_side gsb_side = gsb_side_manager.get_side(); - + /* routing-track and related connections */ - write_rr_gsb_chan_connection_to_xml(fp, vpr_device_grid, vpr_device_annotation, rr_graph, rr_gsb, gsb_side, options.include_rr_info()); + write_rr_gsb_chan_connection_to_xml(fp, vpr_device_grid, + vpr_device_annotation, rr_graph, rr_gsb, + gsb_side, options.include_rr_info()); } - fp << "" - << std::endl; + fp << "" << std::endl; /* close a file */ fp.close(); } /*************************************************************************************** - * Output internal structure (only the connection block part) of a RRGSB to XML format + * Output internal structure (only the connection block part) of a RRGSB to XML + *format ***************************************************************************************/ -static -void write_rr_connection_block_to_xml(const std::string fname_prefix, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const t_rr_type& cb_type, - const RRGSBWriterOption& options) { +static void write_rr_connection_block_to_xml(const std::string fname_prefix, + const RRGraphView& rr_graph, + const RRGSB& rr_gsb, + const t_rr_type& cb_type, + const RRGSBWriterOption& options) { /* Prepare file name */ std::string fname(fname_prefix); - vtr::Point cb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); - std::string curr_cb_name = generate_connection_block_module_name(cb_type, cb_coordinate); - fname += curr_cb_name; + vtr::Point cb_coordinate(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); + std::string curr_cb_name = + generate_connection_block_module_name(cb_type, cb_coordinate); + fname += curr_cb_name; fname += ".xml"; /* If there is a list of gsb list, we skip those which are not in the list */ std::vector include_gsb_names = options.include_gsb_names(); - if (!include_gsb_names.empty() && include_gsb_names.end() == std::find(include_gsb_names.begin(), include_gsb_names.end(), curr_cb_name)) { + if (!include_gsb_names.empty() && + include_gsb_names.end() == std::find(include_gsb_names.begin(), + include_gsb_names.end(), + curr_cb_name)) { return; } @@ -282,17 +293,18 @@ void write_rr_connection_block_to_xml(const std::string fname_prefix, check_file_stream(fname.c_str(), fp); /* Output location of the Switch Block */ - fp << "" << std::endl; - /* Output each side */ + /* Output each side */ for (e_side side : rr_gsb.get_cb_ipin_sides(cb_type)) { /* IPIN nodes and related connections */ - write_rr_gsb_ipin_connection_to_xml(fp, rr_graph, rr_gsb, side, options.include_rr_info()); + write_rr_gsb_ipin_connection_to_xml(fp, rr_graph, rr_gsb, side, + options.include_rr_info()); } - fp << "" - << std::endl; + fp << "" << std::endl; /* close a file */ fp.close(); @@ -300,13 +312,12 @@ void write_rr_connection_block_to_xml(const std::string fname_prefix, /*************************************************************************************** * Output internal structure (only the switch block part) of all the RRGSBs - * in a DeviceRRGSB to XML format + * in a DeviceRRGSB to XML format ***************************************************************************************/ -void write_device_rr_gsb_to_xml(const DeviceGrid& vpr_device_grid, - const VprDeviceAnnotation& vpr_device_annotation, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, - const RRGSBWriterOption& options) { +void write_device_rr_gsb_to_xml( + const DeviceGrid& vpr_device_grid, + const VprDeviceAnnotation& vpr_device_annotation, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, const RRGSBWriterOption& options) { std::string xml_dir_name = format_dir_path(options.output_directory()); /* Create directories */ @@ -315,8 +326,9 @@ void write_device_rr_gsb_to_xml(const DeviceGrid& vpr_device_grid, vtr::Point sb_range = device_rr_gsb.get_gsb_range(); size_t sb_counter = 0; - std::map cb_counters = { {CHANX, 0}, {CHANY, 0} }; - std::map cb_names = { {CHANX, "X-direction"}, {CHANY, "Y-direction"} }; + std::map cb_counters = {{CHANX, 0}, {CHANY, 0}}; + std::map cb_names = {{CHANX, "X-direction"}, + {CHANY, "Y-direction"}}; std::vector include_gsb_names = options.include_gsb_names(); @@ -324,36 +336,45 @@ void write_device_rr_gsb_to_xml(const DeviceGrid& vpr_device_grid, if (options.unique_module_only()) { /* Only output unique GSB modules */ VTR_LOG("Only output unique GSB modules to XML\n"); - for (size_t igsb = 0; igsb < device_rr_gsb.get_num_sb_unique_module(); ++igsb) { + for (size_t igsb = 0; igsb < device_rr_gsb.get_num_sb_unique_module(); + ++igsb) { const RRGSB& rr_gsb = device_rr_gsb.get_sb_unique_module(igsb); /* Write CBx, CBy, SB on need */ if (options.include_sb_content()) { - write_rr_switch_block_to_xml(xml_dir_name, vpr_device_grid, vpr_device_annotation, rr_graph, rr_gsb, options); + write_rr_switch_block_to_xml(xml_dir_name, vpr_device_grid, + vpr_device_annotation, rr_graph, rr_gsb, + options); } sb_counter++; } for (t_rr_type cb_type : {CHANX, CHANY}) { - for (size_t igsb = 0; igsb < device_rr_gsb.get_num_cb_unique_module(cb_type); ++igsb) { + for (size_t igsb = 0; + igsb < device_rr_gsb.get_num_cb_unique_module(cb_type); ++igsb) { const RRGSB& rr_gsb = device_rr_gsb.get_cb_unique_module(cb_type, igsb); if (options.include_cb_content(cb_type)) { - write_rr_connection_block_to_xml(xml_dir_name, rr_graph, rr_gsb, cb_type, options); + write_rr_connection_block_to_xml(xml_dir_name, rr_graph, rr_gsb, + cb_type, options); cb_counters[cb_type]++; } } - } + } } else { - /* Output all GSB instances in the fabric (some instances may share the same module) */ + /* Output all GSB instances in the fabric (some instances may share the same + * module) */ for (size_t ix = 0; ix < sb_range.x(); ++ix) { for (size_t iy = 0; iy < sb_range.y(); ++iy) { const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); /* Write CBx, CBy, SB on need */ if (options.include_sb_content()) { - write_rr_switch_block_to_xml(xml_dir_name, vpr_device_grid, vpr_device_annotation, rr_graph, rr_gsb, options); + write_rr_switch_block_to_xml(xml_dir_name, vpr_device_grid, + vpr_device_annotation, rr_graph, rr_gsb, + options); sb_counter++; } for (t_rr_type cb_type : {CHANX, CHANY}) { if (options.include_cb_content(cb_type)) { - write_rr_connection_block_to_xml(xml_dir_name, rr_graph, rr_gsb, cb_type, options); + write_rr_connection_block_to_xml(xml_dir_name, rr_graph, rr_gsb, + cb_type, options); cb_counters[cb_type]++; } } @@ -362,13 +383,11 @@ void write_device_rr_gsb_to_xml(const DeviceGrid& vpr_device_grid, } VTR_LOG("Output %lu Switch blocks to XML files under directory '%s'\n", - sb_counter, - xml_dir_name.c_str()); + sb_counter, xml_dir_name.c_str()); for (t_rr_type cb_type : {CHANX, CHANY}) { - VTR_LOG("Output %lu %s Connection blocks to XML files under directory '%s'\n", - cb_counters[cb_type], - cb_names[cb_type].c_str(), - xml_dir_name.c_str()); + VTR_LOG( + "Output %lu %s Connection blocks to XML files under directory '%s'\n", + cb_counters[cb_type], cb_names[cb_type].c_str(), xml_dir_name.c_str()); } } diff --git a/openfpga/src/annotation/write_xml_device_rr_gsb.h b/openfpga/src/annotation/write_xml_device_rr_gsb.h index 1310b7dbb..baf2d1a3e 100644 --- a/openfpga/src/annotation/write_xml_device_rr_gsb.h +++ b/openfpga/src/annotation/write_xml_device_rr_gsb.h @@ -5,11 +5,12 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "device_grid.h" -#include "vpr_device_annotation.h" -#include "rr_graph_view.h" #include "device_rr_gsb.h" +#include "rr_graph_view.h" #include "rr_gsb_writer_option.h" +#include "vpr_device_annotation.h" /******************************************************************** * Function declaration @@ -18,11 +19,10 @@ /* begin namespace openfpga */ namespace openfpga { -void write_device_rr_gsb_to_xml(const DeviceGrid& vpr_device_grid, - const VprDeviceAnnotation& vpr_device_annotation, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, - const RRGSBWriterOption& options); +void write_device_rr_gsb_to_xml( + const DeviceGrid& vpr_device_grid, + const VprDeviceAnnotation& vpr_device_annotation, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, const RRGSBWriterOption& options); } /* end namespace openfpga */ diff --git a/openfpga/src/base/basic_command.cpp b/openfpga/src/base/basic_command.cpp index 7b0d8efc2..aa7f0d303 100644 --- a/openfpga/src/base/basic_command.cpp +++ b/openfpga/src/base/basic_command.cpp @@ -4,9 +4,10 @@ * - version * - help *******************************************************************/ -#include "openfpga_title.h" #include "basic_command.h" +#include "openfpga_title.h" + /* begin namespace openfpga */ namespace openfpga { @@ -15,23 +16,30 @@ void add_basic_commands(openfpga::Shell& shell) { ShellCommandClassId basic_cmd_class = shell.add_command_class("Basic"); Command shell_cmd_exit("exit"); - ShellCommandId shell_cmd_exit_id = shell.add_command(shell_cmd_exit, "Exit the shell"); + ShellCommandId shell_cmd_exit_id = + shell.add_command(shell_cmd_exit, "Exit the shell"); shell.set_command_class(shell_cmd_exit_id, basic_cmd_class); - shell.set_command_execute_function(shell_cmd_exit_id, [shell](){shell.exit();}); + shell.set_command_execute_function(shell_cmd_exit_id, + [shell]() { shell.exit(); }); /* Version */ Command shell_cmd_version("version"); - ShellCommandId shell_cmd_version_id = shell.add_command(shell_cmd_version, "Show version information"); + ShellCommandId shell_cmd_version_id = + shell.add_command(shell_cmd_version, "Show version information"); shell.set_command_class(shell_cmd_version_id, basic_cmd_class); - shell.set_command_execute_function(shell_cmd_version_id, print_openfpga_version_info); + shell.set_command_execute_function(shell_cmd_version_id, + print_openfpga_version_info); - /* Note: - * help MUST be the last to add because the linking to execute function will do a snapshot on the shell + /* Note: + * help MUST be the last to add because the linking to execute function will + * do a snapshot on the shell */ Command shell_cmd_help("help"); - ShellCommandId shell_cmd_help_id = shell.add_command(shell_cmd_help, "Launch help desk"); + ShellCommandId shell_cmd_help_id = + shell.add_command(shell_cmd_help, "Launch help desk"); shell.set_command_class(shell_cmd_help_id, basic_cmd_class); - shell.set_command_execute_function(shell_cmd_help_id, [shell](){shell.print_commands();}); -} + shell.set_command_execute_function(shell_cmd_help_id, + [shell]() { shell.print_commands(); }); +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/basic_command.h b/openfpga/src/base/basic_command.h index 8aaf9110a..b60247c21 100644 --- a/openfpga/src/base/basic_command.h +++ b/openfpga/src/base/basic_command.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "shell.h" #include "openfpga_context.h" +#include "shell.h" /******************************************************************** * Function declaration @@ -14,7 +14,7 @@ /* begin namespace openfpga */ namespace openfpga { -void add_basic_commands(openfpga::Shell& shell); +void add_basic_commands(openfpga::Shell& shell); } /* end namespace openfpga */ diff --git a/openfpga/src/base/io_map.cpp b/openfpga/src/base/io_map.cpp index 3012c4285..cfaf98b5d 100644 --- a/openfpga/src/base/io_map.cpp +++ b/openfpga/src/base/io_map.cpp @@ -1,10 +1,10 @@ /****************************************************************************** * Memember functions for data structure IoMap ******************************************************************************/ -#include "vtr_assert.h" - #include "io_map.h" +#include "vtr_assert.h" + /* begin namespace openfpga */ namespace openfpga { @@ -32,8 +32,7 @@ bool IoMap::is_io_input(IoMapId io_map_id) const { return IoMap::IO_MAP_DIR_INPUT == io_directionality_[io_map_id]; } -IoMapId IoMap::create_io_mapping(const BasicPort& port, - const BasicPort& net, +IoMapId IoMap::create_io_mapping(const BasicPort& port, const BasicPort& net, IoMap::e_direction dir) { /* Create a new id */ IoMapId io_map_id = IoMapId(io_map_ids_.size()); @@ -45,10 +44,11 @@ IoMapId IoMap::create_io_mapping(const BasicPort& port, io_directionality_.push_back(dir); return io_map_id; -} +} bool IoMap::valid_io_map_id(IoMapId io_map_id) const { - return (size_t(io_map_id) < io_map_ids_.size()) && (io_map_id == io_map_ids_[io_map_id]); + return (size_t(io_map_id) < io_map_ids_.size()) && + (io_map_id == io_map_ids_[io_map_id]); } } /* end namespace openfpga */ diff --git a/openfpga/src/base/io_map.h b/openfpga/src/base/io_map.h index 5bc378000..0dfa46128 100644 --- a/openfpga/src/base/io_map.h +++ b/openfpga/src/base/io_map.h @@ -4,54 +4,57 @@ /******************************************************************** * Include header files required by the data structure definition *******************************************************************/ -#include "vtr_vector.h" -#include "openfpga_port.h" #include "io_map_fwd.h" +#include "openfpga_port.h" +#include "vtr_vector.h" /* Begin namespace openfpga */ namespace openfpga { /******************************************************************** - * This is a data structure storing io mapping information + * This is a data structure storing io mapping information * - the net-to-I/O mapping * - each I/O directionality *******************************************************************/ class IoMap { - public: /* Types and ranges */ - enum e_direction { - IO_MAP_DIR_INPUT, - IO_MAP_DIR_OUTPUT, - NUM_IO_MAP_DIR_TYPES - }; - typedef vtr::vector::const_iterator io_map_iterator; - typedef vtr::Range io_map_range; - public: /* Public aggregators */ - /* Find all io mapping */ - io_map_range io_map() const; + public: /* Types and ranges */ + enum e_direction { + IO_MAP_DIR_INPUT, + IO_MAP_DIR_OUTPUT, + NUM_IO_MAP_DIR_TYPES + }; + typedef vtr::vector::const_iterator io_map_iterator; + typedef vtr::Range io_map_range; - /* Get the port of the io that is mapped */ - BasicPort io_port(IoMapId io_map_id) const; + public: /* Public aggregators */ + /* Find all io mapping */ + io_map_range io_map() const; - /* Get the net of the io that is mapped to */ - BasicPort io_net(IoMapId io_map_id) const; + /* Get the port of the io that is mapped */ + BasicPort io_port(IoMapId io_map_id) const; - /* Query on if an io is configured as an input */ - bool is_io_input(IoMapId io_map_id) const; + /* Get the net of the io that is mapped to */ + BasicPort io_net(IoMapId io_map_id) const; - /* Query on if an io is configured as an output */ - bool is_io_output(IoMapId io_map_id) const; - public: /* Public mutators */ - /* Create a new I/O mapping */ - IoMapId create_io_mapping(const BasicPort& port, - const BasicPort& net, - e_direction dir); - public: /* Public validators/invalidators */ - bool valid_io_map_id(IoMapId io_map_id) const; - private: /* Internal Data */ - vtr::vector io_map_ids_; - vtr::vector io_ports_; - vtr::vector mapped_nets_; - vtr::vector io_directionality_; + /* Query on if an io is configured as an input */ + bool is_io_input(IoMapId io_map_id) const; + + /* Query on if an io is configured as an output */ + bool is_io_output(IoMapId io_map_id) const; + + public: /* Public mutators */ + /* Create a new I/O mapping */ + IoMapId create_io_mapping(const BasicPort& port, const BasicPort& net, + e_direction dir); + + public: /* Public validators/invalidators */ + bool valid_io_map_id(IoMapId io_map_id) const; + + private: /* Internal Data */ + vtr::vector io_map_ids_; + vtr::vector io_ports_; + vtr::vector mapped_nets_; + vtr::vector io_directionality_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/base/io_map_fwd.h b/openfpga/src/base/io_map_fwd.h index 0de3e99c1..3518c7280 100644 --- a/openfpga/src/base/io_map_fwd.h +++ b/openfpga/src/base/io_map_fwd.h @@ -1,5 +1,5 @@ /************************************************** - * This file includes only declarations for + * This file includes only declarations for * the data structures for IoMap * Please refer to io_map.h for more details *************************************************/ @@ -20,4 +20,4 @@ class IoMap; } /* end namespace openfpga */ -#endif +#endif diff --git a/openfpga/src/base/netlist_manager.cpp b/openfpga/src/base/netlist_manager.cpp index 0b2e6ec45..23e1c40dd 100644 --- a/openfpga/src/base/netlist_manager.cpp +++ b/openfpga/src/base/netlist_manager.cpp @@ -1,10 +1,11 @@ /****************************************************************************** * This files includes memeber functions for data structure NetlistManager ******************************************************************************/ +#include "netlist_manager.h" + #include #include "vtr_assert.h" -#include "netlist_manager.h" /* begin namespace openfpga */ namespace openfpga { @@ -18,12 +19,12 @@ NetlistManager::netlist_range NetlistManager::netlists() const { } /* Find all the modules that are included in a netlist */ -std::vector NetlistManager::netlist_modules(const NetlistId& netlist) const { +std::vector NetlistManager::netlist_modules( + const NetlistId& netlist) const { VTR_ASSERT(true == valid_netlist_id(netlist)); return included_module_ids_[netlist]; } - /****************************************************************************** * Public accessors ******************************************************************************/ @@ -38,27 +39,29 @@ NetlistId NetlistManager::find_netlist(const std::string& netlist_name) const { if (name_id_map_.find(netlist_name) != name_id_map_.end()) { /* Found, return the id */ return name_id_map_.at(netlist_name); - } + } /* Not found, return an invalid id */ return NetlistId::INVALID(); } -NetlistManager::e_netlist_type NetlistManager::netlist_type(const NetlistId& netlist) const { +NetlistManager::e_netlist_type NetlistManager::netlist_type( + const NetlistId& netlist) const { VTR_ASSERT(true == valid_netlist_id(netlist)); return netlist_types_[netlist]; } /* Find if a module belongs to a netlist */ -bool NetlistManager::is_module_in_netlist(const NetlistId& netlist, const ModuleId& module) const { +bool NetlistManager::is_module_in_netlist(const NetlistId& netlist, + const ModuleId& module) const { VTR_ASSERT(true == valid_netlist_id(netlist)); for (const ModuleId& included_module : included_module_ids_[netlist]) { /* Already in the netlist, return true */ if (module == included_module) { - return true; + return true; } } - + /* Not in the netlist, return false */ return false; } @@ -67,14 +70,14 @@ bool NetlistManager::is_module_in_netlist(const NetlistId& netlist, const Module NetlistId NetlistManager::find_module_netlist(const ModuleId& module) const { /* Find if the module has been added to a netlist. If used, return false! */ /* Not found, return an invalid value */ - if ( module_netlist_map_.end() - != module_netlist_map_.find(module)) { + if (module_netlist_map_.end() != module_netlist_map_.find(module)) { return NetlistId::INVALID(); } return module_netlist_map_.at(module); } -std::vector NetlistManager::netlists_by_type(const NetlistManager::e_netlist_type& netlist_type) const { +std::vector NetlistManager::netlists_by_type( + const NetlistManager::e_netlist_type& netlist_type) const { std::vector nlists; for (const NetlistId& nlist_id : netlist_ids_) { @@ -87,12 +90,14 @@ std::vector NetlistManager::netlists_by_type(const NetlistManager::e_ } /* Find all the preprocessing flags that are included in a netlist */ -std::vector NetlistManager::netlist_preprocessing_flags(const NetlistId& netlist) const { +std::vector NetlistManager::netlist_preprocessing_flags( + const NetlistId& netlist) const { VTR_ASSERT(true == valid_netlist_id(netlist)); - std::vector flags; + std::vector flags; - for (const PreprocessingFlagId& flag_id : included_preprocessing_flag_ids_[netlist]) { + for (const PreprocessingFlagId& flag_id : + included_preprocessing_flag_ids_[netlist]) { VTR_ASSERT(true == valid_preprocessing_flag_id(flag_id)); flags.push_back(preprocessing_flag_names_[flag_id]); } @@ -107,7 +112,7 @@ std::vector NetlistManager::netlist_preprocessing_flags(const Netli NetlistId NetlistManager::add_netlist(const std::string& name) { /* Find if the name has been used. If used, return an invalid Id! */ std::map::iterator it = name_id_map_.find(name); - if (it != name_id_map_.end()) { + if (it != name_id_map_.end()) { return NetlistId::INVALID(); } @@ -122,10 +127,10 @@ NetlistId NetlistManager::add_netlist(const std::string& name) { included_preprocessing_flag_ids_.emplace_back(); /* Register in the name-to-id map */ - name_id_map_[name] = netlist; + name_id_map_[name] = netlist; return netlist; -} +} void NetlistManager::set_netlist_type(const NetlistId& netlist, const e_netlist_type& type) { @@ -134,18 +139,22 @@ void NetlistManager::set_netlist_type(const NetlistId& netlist, } /* Add a module to a netlist in the library */ -bool NetlistManager::add_netlist_module(const NetlistId& netlist, const ModuleId& module) { +bool NetlistManager::add_netlist_module(const NetlistId& netlist, + const ModuleId& module) { VTR_ASSERT(true == valid_netlist_id(netlist)); /* Find if the module already in the netlist */ - std::vector::iterator module_it = std::find(included_module_ids_[netlist].begin(), included_module_ids_[netlist].end(), module); + std::vector::iterator module_it = + std::find(included_module_ids_[netlist].begin(), + included_module_ids_[netlist].end(), module); if (module_it != included_module_ids_[netlist].end()) { /* Already in the netlist, nothing to do */ return true; } /* Try to register it in module-to-netlist map */ /* Find if the module has been added to a netlist. If used, return false! */ - std::map::iterator map_it = module_netlist_map_.find(module); + std::map::iterator map_it = + module_netlist_map_.find(module); if (map_it != module_netlist_map_.end()) { return false; } @@ -158,11 +167,13 @@ bool NetlistManager::add_netlist_module(const NetlistId& netlist, const ModuleId } /* Add a pre-processing flag to a netlist */ -void NetlistManager::add_netlist_preprocessing_flag(const NetlistId& netlist, const std::string& preprocessing_flag) { +void NetlistManager::add_netlist_preprocessing_flag( + const NetlistId& netlist, const std::string& preprocessing_flag) { VTR_ASSERT(true == valid_netlist_id(netlist)); - PreprocessingFlagId flag = PreprocessingFlagId(preprocessing_flag_ids_.size()); - + PreprocessingFlagId flag = + PreprocessingFlagId(preprocessing_flag_ids_.size()); + /* Find if the module already in the netlist */ for (const PreprocessingFlagId& id : preprocessing_flag_ids_) { if (0 != preprocessing_flag.compare(preprocessing_flag_names_[id])) { @@ -180,7 +191,9 @@ void NetlistManager::add_netlist_preprocessing_flag(const NetlistId& netlist, co } /* Check if the flag is already in the netlist */ - std::vector::iterator it = std::find(included_preprocessing_flag_ids_[netlist].begin(), included_preprocessing_flag_ids_[netlist].end(), flag); + std::vector::iterator it = + std::find(included_preprocessing_flag_ids_[netlist].begin(), + included_preprocessing_flag_ids_[netlist].end(), flag); if (it == included_preprocessing_flag_ids_[netlist].end()) { /* Not in the list, we add it */ included_preprocessing_flag_ids_[netlist].push_back(flag); @@ -191,19 +204,20 @@ void NetlistManager::add_netlist_preprocessing_flag(const NetlistId& netlist, co * Public validators/invalidators ******************************************************************************/ bool NetlistManager::valid_netlist_id(const NetlistId& netlist) const { - return (size_t(netlist) < netlist_ids_.size()) && (netlist == netlist_ids_[netlist]); + return (size_t(netlist) < netlist_ids_.size()) && + (netlist == netlist_ids_[netlist]); } /****************************************************************************** * Private validators/invalidators ******************************************************************************/ -bool NetlistManager::valid_preprocessing_flag_id(const PreprocessingFlagId& flag) const { - return (size_t(flag) < preprocessing_flag_ids_.size()) && (flag == preprocessing_flag_ids_[flag]); +bool NetlistManager::valid_preprocessing_flag_id( + const PreprocessingFlagId& flag) const { + return (size_t(flag) < preprocessing_flag_ids_.size()) && + (flag == preprocessing_flag_ids_[flag]); } -void NetlistManager::invalidate_name2id_map() { - name_id_map_.clear(); -} +void NetlistManager::invalidate_name2id_map() { name_id_map_.clear(); } void NetlistManager::invalidate_module2netlist_map() { module_netlist_map_.clear(); diff --git a/openfpga/src/base/netlist_manager.h b/openfpga/src/base/netlist_manager.h index df2283e77..3e895ff3e 100644 --- a/openfpga/src/base/netlist_manager.h +++ b/openfpga/src/base/netlist_manager.h @@ -1,109 +1,115 @@ /****************************************************************************** * This files includes data structures for netlist management. * It keeps a list of netlists that have been created - * Each netlist includes a list of ids of modules that are stored in ModuleManager + * Each netlist includes a list of ids of modules that are stored in + *ModuleManager * * When we want to dump out a netlist in Verilog/SPICE format, - * the netlist manager can generate the dependency on other netlists + * the netlist manager can generate the dependency on other netlists * This can help us tracking the dependency and generate `include` files easily * * Cross-reference: * - * +---------+ +---------+ + * +---------+ +---------+ * | | ModuleId | | * | Netlist |-------------->| Module | * | Manager | | Manager | * | | | | * +---------+ +---------+ - * + * ******************************************************************************/ #ifndef NETLIST_MANAGER_H #define NETLIST_MANAGER_H +#include #include #include -#include -#include "vtr_vector.h" -#include "netlist_manager_fwd.h" + #include "module_manager.h" +#include "netlist_manager_fwd.h" +#include "vtr_vector.h" /* begin namespace openfpga */ namespace openfpga { class NetlistManager { - public: /* Internal Types */ - /* Type of netlists */ - enum e_netlist_type { - SUBMODULE_NETLIST, - LOGIC_BLOCK_NETLIST, - ROUTING_MODULE_NETLIST, - TOP_MODULE_NETLIST, - TESTBENCH_NETLIST, - NUM_NETLIST_TYPES - }; - public: /* Types and ranges */ - typedef vtr::vector::const_iterator netlist_iterator; - typedef vtr::Range netlist_range; + public: /* Internal Types */ + /* Type of netlists */ + enum e_netlist_type { + SUBMODULE_NETLIST, + LOGIC_BLOCK_NETLIST, + ROUTING_MODULE_NETLIST, + TOP_MODULE_NETLIST, + TESTBENCH_NETLIST, + NUM_NETLIST_TYPES + }; - public: /* Public aggregators */ - /* Find all the netlists */ - netlist_range netlists() const; - /* Find all the modules that are included in a netlist */ - std::vector netlist_modules(const NetlistId& netlist) const; - /* Find all the preprocessing flags that are included in a netlist */ - std::vector netlist_preprocessing_flags(const NetlistId& netlist) const; + public: /* Types and ranges */ + typedef vtr::vector::const_iterator netlist_iterator; + typedef vtr::Range netlist_range; - public: /* Public accessors */ - /* Find the name of a netlist */ - std::string netlist_name(const NetlistId& netlist) const; - /* Find a netlist by its name */ - NetlistId find_netlist(const std::string& netlist_name) const; - /* Find all the netlist in a given type */ - std::vector netlists_by_type(const e_netlist_type& netlist_type) const; - /* Get the type of a netlist */ - e_netlist_type netlist_type(const NetlistId& netlist) const; - /* Find if a module belongs to a netlist */ - bool is_module_in_netlist(const NetlistId& netlist, const ModuleId& module) const; - /* Find the netlist that a module belongs to */ - NetlistId find_module_netlist(const ModuleId& module) const; + public: /* Public aggregators */ + /* Find all the netlists */ + netlist_range netlists() const; + /* Find all the modules that are included in a netlist */ + std::vector netlist_modules(const NetlistId& netlist) const; + /* Find all the preprocessing flags that are included in a netlist */ + std::vector netlist_preprocessing_flags( + const NetlistId& netlist) const; - public: /* Public mutators */ - /* Add a netlist to the library */ - NetlistId add_netlist(const std::string& name); - /* Set a netlist type */ - void set_netlist_type(const NetlistId& netlist, - const e_netlist_type& type); - /* Add a module to a netlist in the library */ - bool add_netlist_module(const NetlistId& netlist, const ModuleId& module); - /* Add a pre-processing flag to a netlist */ - void add_netlist_preprocessing_flag(const NetlistId& netlist, const std::string& preprocessing_flag); + public: /* Public accessors */ + /* Find the name of a netlist */ + std::string netlist_name(const NetlistId& netlist) const; + /* Find a netlist by its name */ + NetlistId find_netlist(const std::string& netlist_name) const; + /* Find all the netlist in a given type */ + std::vector netlists_by_type( + const e_netlist_type& netlist_type) const; + /* Get the type of a netlist */ + e_netlist_type netlist_type(const NetlistId& netlist) const; + /* Find if a module belongs to a netlist */ + bool is_module_in_netlist(const NetlistId& netlist, + const ModuleId& module) const; + /* Find the netlist that a module belongs to */ + NetlistId find_module_netlist(const ModuleId& module) const; - public: /* Public validators/invalidators */ - bool valid_netlist_id(const NetlistId& netlist) const; + public: /* Public mutators */ + /* Add a netlist to the library */ + NetlistId add_netlist(const std::string& name); + /* Set a netlist type */ + void set_netlist_type(const NetlistId& netlist, const e_netlist_type& type); + /* Add a module to a netlist in the library */ + bool add_netlist_module(const NetlistId& netlist, const ModuleId& module); + /* Add a pre-processing flag to a netlist */ + void add_netlist_preprocessing_flag(const NetlistId& netlist, + const std::string& preprocessing_flag); - private: /* Private validators/invalidators */ - bool valid_preprocessing_flag_id(const PreprocessingFlagId& flag) const; - void invalidate_name2id_map(); - void invalidate_module2netlist_map(); + public: /* Public validators/invalidators */ + bool valid_netlist_id(const NetlistId& netlist) const; - private: /* Internal data */ - vtr::vector netlist_ids_; - vtr::vector netlist_names_; - vtr::vector netlist_types_; + private: /* Private validators/invalidators */ + bool valid_preprocessing_flag_id(const PreprocessingFlagId& flag) const; + void invalidate_name2id_map(); + void invalidate_module2netlist_map(); - vtr::vector> included_module_ids_; - vtr::vector> included_preprocessing_flag_ids_; + private: /* Internal data */ + vtr::vector netlist_ids_; + vtr::vector netlist_names_; + vtr::vector netlist_types_; - vtr::vector preprocessing_flag_ids_; - vtr::vector preprocessing_flag_names_; + vtr::vector> included_module_ids_; + vtr::vector> + included_preprocessing_flag_ids_; - /* fast look-up for netlist */ - std::map name_id_map_; - /* fast look-up for modules in netlists */ - std::map module_netlist_map_; + vtr::vector preprocessing_flag_ids_; + vtr::vector preprocessing_flag_names_; + + /* fast look-up for netlist */ + std::map name_id_map_; + /* fast look-up for modules in netlists */ + std::map module_netlist_map_; }; } /* end namespace openfpga */ #endif - diff --git a/openfpga/src/base/netlist_manager_fwd.h b/openfpga/src/base/netlist_manager_fwd.h index 186e1792c..677420f32 100644 --- a/openfpga/src/base/netlist_manager_fwd.h +++ b/openfpga/src/base/netlist_manager_fwd.h @@ -1,5 +1,5 @@ /************************************************** - * This file includes only declarations for + * This file includes only declarations for * the data structures for netlist managers * Please refer to netlist_manager.h for more details *************************************************/ @@ -22,4 +22,4 @@ class NetlistManager; } /* end namespace openfpga */ -#endif +#endif diff --git a/openfpga/src/base/openfpga_bitstream.cpp b/openfpga/src/base/openfpga_bitstream.cpp index 91362f55c..c95a18c0f 100644 --- a/openfpga/src/base/openfpga_bitstream.cpp +++ b/openfpga/src/base/openfpga_bitstream.cpp @@ -2,8 +2,8 @@ * This file includes functions to build bitstream database *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgashell library */ #include "command_exit_codes.h" @@ -13,19 +13,17 @@ #include "openfpga_reserved_words.h" /* Headers from fpgabitstream library */ -#include "read_xml_arch_bitstream.h" -#include "write_xml_arch_bitstream.h" -#include "report_bitstream_distribution.h" - -#include "openfpga_naming.h" - #include "build_device_bitstream.h" -#include "write_text_fabric_bitstream.h" -#include "write_xml_fabric_bitstream.h" #include "build_fabric_bitstream.h" #include "build_io_mapping_info.h" -#include "write_xml_io_mapping.h" #include "openfpga_bitstream.h" +#include "openfpga_naming.h" +#include "read_xml_arch_bitstream.h" +#include "report_bitstream_distribution.h" +#include "write_text_fabric_bitstream.h" +#include "write_xml_arch_bitstream.h" +#include "write_xml_fabric_bitstream.h" +#include "write_xml_io_mapping.h" /* Include global variables of VPR */ #include "globals.h" @@ -36,31 +34,32 @@ namespace openfpga { /******************************************************************** * A wrapper function to call the build_device_bitstream() in FPGA bitstream *******************************************************************/ -int fpga_bitstream(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - +int fpga_bitstream(OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_verbose = cmd.option("verbose"); CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); CommandOptionId opt_write_file = cmd.option("write_file"); CommandOptionId opt_read_file = cmd.option("read_file"); if (true == cmd_context.option_enable(cmd, opt_read_file)) { - openfpga_ctx.mutable_bitstream_manager() = read_xml_architecture_bitstream(cmd_context.option_value(cmd, opt_read_file).c_str()); + openfpga_ctx.mutable_bitstream_manager() = read_xml_architecture_bitstream( + cmd_context.option_value(cmd, opt_read_file).c_str()); } else { - openfpga_ctx.mutable_bitstream_manager() = build_device_bitstream(g_vpr_ctx, - openfpga_ctx, - cmd_context.option_enable(cmd, opt_verbose)); + openfpga_ctx.mutable_bitstream_manager() = build_device_bitstream( + g_vpr_ctx, openfpga_ctx, cmd_context.option_enable(cmd, opt_verbose)); } if (true == cmd_context.option_enable(cmd, opt_write_file)) { - std::string src_dir_path = find_path_dir_name(cmd_context.option_value(cmd, opt_write_file)); + std::string src_dir_path = + find_path_dir_name(cmd_context.option_value(cmd, opt_write_file)); /* Create directories */ create_directory(src_dir_path); - write_xml_architecture_bitstream(openfpga_ctx.bitstream_manager(), - cmd_context.option_value(cmd, opt_write_file), - !cmd_context.option_enable(cmd, opt_no_time_stamp)); + write_xml_architecture_bitstream( + openfpga_ctx.bitstream_manager(), + cmd_context.option_value(cmd, opt_write_file), + !cmd_context.option_enable(cmd, opt_no_time_stamp)); } /* TODO: should identify the error code from internal function execution */ @@ -70,17 +69,15 @@ int fpga_bitstream(OpenfpgaContext& openfpga_ctx, /******************************************************************** * A wrapper function to call the build_fabric_bitstream() in FPGA bitstream *******************************************************************/ -int build_fabric_bitstream(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - +int build_fabric_bitstream(OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_verbose = cmd.option("verbose"); /* Build fabric bitstream here */ - openfpga_ctx.mutable_fabric_bitstream() = build_fabric_dependent_bitstream(openfpga_ctx.bitstream_manager(), - openfpga_ctx.module_graph(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.arch().config_protocol, - cmd_context.option_enable(cmd, opt_verbose)); + openfpga_ctx.mutable_fabric_bitstream() = build_fabric_dependent_bitstream( + openfpga_ctx.bitstream_manager(), openfpga_ctx.module_graph(), + openfpga_ctx.arch().circuit_lib, openfpga_ctx.arch().config_protocol, + cmd_context.option_enable(cmd, opt_verbose)); /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; @@ -90,8 +87,8 @@ int build_fabric_bitstream(OpenfpgaContext& openfpga_ctx, * A wrapper function to call the write_fabric_bitstream() in FPGA bitstream *******************************************************************/ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - + const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_verbose = cmd.option("verbose"); CommandOptionId opt_file = cmd.option("file"); CommandOptionId opt_file_format = cmd.option("format"); @@ -101,67 +98,70 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx, /* Write fabric bitstream if required */ int status = CMD_EXEC_SUCCESS; - + VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file)); - std::string src_dir_path = find_path_dir_name(cmd_context.option_value(cmd, opt_file)); + std::string src_dir_path = + find_path_dir_name(cmd_context.option_value(cmd, opt_file)); /* Create directories */ create_directory(src_dir_path); /* Check file format requirements */ - std::string file_format("plain_text"); + std::string file_format("plain_text"); if (true == cmd_context.option_enable(cmd, opt_file_format)) { file_format = cmd_context.option_value(cmd, opt_file_format); } if (std::string("xml") == file_format) { - status = write_fabric_bitstream_to_xml_file(openfpga_ctx.bitstream_manager(), - openfpga_ctx.fabric_bitstream(), - openfpga_ctx.arch().config_protocol, - cmd_context.option_value(cmd, opt_file), - !cmd_context.option_enable(cmd, opt_no_time_stamp), - cmd_context.option_enable(cmd, opt_verbose)); + status = write_fabric_bitstream_to_xml_file( + openfpga_ctx.bitstream_manager(), openfpga_ctx.fabric_bitstream(), + openfpga_ctx.arch().config_protocol, + cmd_context.option_value(cmd, opt_file), + !cmd_context.option_enable(cmd, opt_no_time_stamp), + cmd_context.option_enable(cmd, opt_verbose)); } else { /* By default, output in plain text format */ - status = write_fabric_bitstream_to_text_file(openfpga_ctx.bitstream_manager(), - openfpga_ctx.fabric_bitstream(), - openfpga_ctx.blwl_shift_register_banks(), - openfpga_ctx.arch().config_protocol, - openfpga_ctx.fabric_global_port_info(), - cmd_context.option_value(cmd, opt_file), - cmd_context.option_enable(cmd, opt_fast_config), - cmd_context.option_enable(cmd, opt_keep_dont_care_bits), - !cmd_context.option_enable(cmd, opt_no_time_stamp), - cmd_context.option_enable(cmd, opt_verbose)); + status = write_fabric_bitstream_to_text_file( + openfpga_ctx.bitstream_manager(), openfpga_ctx.fabric_bitstream(), + openfpga_ctx.blwl_shift_register_banks(), + openfpga_ctx.arch().config_protocol, + openfpga_ctx.fabric_global_port_info(), + cmd_context.option_value(cmd, opt_file), + cmd_context.option_enable(cmd, opt_fast_config), + cmd_context.option_enable(cmd, opt_keep_dont_care_bits), + !cmd_context.option_enable(cmd, opt_no_time_stamp), + cmd_context.option_enable(cmd, opt_verbose)); } - + return status; -} +} /******************************************************************** * A wrapper function to call the write_io_mapping() in FPGA bitstream *******************************************************************/ -int write_io_mapping(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - +int write_io_mapping(const OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_verbose = cmd.option("verbose"); CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); CommandOptionId opt_file = cmd.option("file"); /* Write fabric bitstream if required */ int status = CMD_EXEC_SUCCESS; - + VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file)); - std::string src_dir_path = find_path_dir_name(cmd_context.option_value(cmd, opt_file)); + std::string src_dir_path = + find_path_dir_name(cmd_context.option_value(cmd, opt_file)); /* Create directories */ create_directory(src_dir_path); - /* Create a module as the top-level fabric, and add it to the module manager */ + /* Create a module as the top-level fabric, and add it to the module manager + */ std::string top_module_name = generate_fpga_top_module_name(); - ModuleId top_module = openfpga_ctx.module_graph().find_module(top_module_name); + ModuleId top_module = + openfpga_ctx.module_graph().find_module(top_module_name); VTR_ASSERT(true == openfpga_ctx.module_graph().valid_module_id(top_module)); /* VPR added a prefix to the output ports, remove them here */ @@ -169,38 +169,36 @@ int write_io_mapping(const OpenfpgaContext& openfpga_ctx, prefix_to_remove.push_back(std::string(VPR_BENCHMARK_OUT_PORT_PREFIX)); prefix_to_remove.push_back(std::string(OPENFPGA_BENCHMARK_OUT_PORT_PREFIX)); - IoMap io_map = build_fpga_io_mapping_info(openfpga_ctx.module_graph(), - top_module, - g_vpr_ctx.atom(), - g_vpr_ctx.placement(), - openfpga_ctx.io_location_map(), - openfpga_ctx.vpr_netlist_annotation(), - std::string(), - std::string(), - prefix_to_remove); + IoMap io_map = build_fpga_io_mapping_info( + openfpga_ctx.module_graph(), top_module, g_vpr_ctx.atom(), + g_vpr_ctx.placement(), openfpga_ctx.io_location_map(), + openfpga_ctx.vpr_netlist_annotation(), std::string(), std::string(), + prefix_to_remove); + + status = write_io_mapping_to_xml_file( + io_map, cmd_context.option_value(cmd, opt_file), + !cmd_context.option_enable(cmd, opt_no_time_stamp), + cmd_context.option_enable(cmd, opt_verbose)); - status = write_io_mapping_to_xml_file(io_map, - cmd_context.option_value(cmd, opt_file), - !cmd_context.option_enable(cmd, opt_no_time_stamp), - cmd_context.option_enable(cmd, opt_verbose)); - return status; -} +} /******************************************************************** - * A wrapper function to call the report_arch_bitstream_distribution() in FPGA bitstream + * A wrapper function to call the report_arch_bitstream_distribution() in FPGA + *bitstream *******************************************************************/ int report_bitstream_distribution(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - + const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_file = cmd.option("file"); CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); int status = CMD_EXEC_SUCCESS; - + VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file)); - std::string src_dir_path = find_path_dir_name(cmd_context.option_value(cmd, opt_file)); + std::string src_dir_path = + find_path_dir_name(cmd_context.option_value(cmd, opt_file)); /* Create directories */ create_directory(src_dir_path); @@ -212,18 +210,17 @@ int report_bitstream_distribution(const OpenfpgaContext& openfpga_ctx, depth = std::atoi(cmd_context.option_value(cmd, opt_depth).c_str()); /* Error out if we have negative depth */ if (0 > depth) { - VTR_LOG_ERROR("Invalid depth '%d' which should be 0 or a positive number!\n", - depth); - return CMD_EXEC_FATAL_ERROR; + VTR_LOG_ERROR( + "Invalid depth '%d' which should be 0 or a positive number!\n", depth); + return CMD_EXEC_FATAL_ERROR; } } - status = report_bitstream_distribution(cmd_context.option_value(cmd, opt_file), - openfpga_ctx.bitstream_manager(), - openfpga_ctx.fabric_bitstream(), - !cmd_context.option_enable(cmd, opt_no_time_stamp), - depth); - + status = report_bitstream_distribution( + cmd_context.option_value(cmd, opt_file), openfpga_ctx.bitstream_manager(), + openfpga_ctx.fabric_bitstream(), + !cmd_context.option_enable(cmd, opt_no_time_stamp), depth); + return status; } diff --git a/openfpga/src/base/openfpga_bitstream.h b/openfpga/src/base/openfpga_bitstream.h index c04fb7656..8934aac77 100644 --- a/openfpga/src/base/openfpga_bitstream.h +++ b/openfpga/src/base/openfpga_bitstream.h @@ -15,20 +15,22 @@ /* begin namespace openfpga */ namespace openfpga { -int fpga_bitstream(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); +int fpga_bitstream(OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context); -int build_fabric_bitstream(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); +int build_fabric_bitstream(OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context); int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); + const Command& cmd, + const CommandContext& cmd_context); -int write_io_mapping(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); +int write_io_mapping(const OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context); int report_bitstream_distribution(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); + const Command& cmd, + const CommandContext& cmd_context); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_bitstream_command.cpp b/openfpga/src/base/openfpga_bitstream_command.cpp index e3bb98b94..796356731 100644 --- a/openfpga/src/base/openfpga_bitstream_command.cpp +++ b/openfpga/src/base/openfpga_bitstream_command.cpp @@ -1,40 +1,48 @@ /******************************************************************** - * Add commands to the OpenFPGA shell interface, + * Add commands to the OpenFPGA shell interface, * in purpose of generate Verilog netlists modeling the full FPGA fabric * This is one of the core engine of openfpga, including: - * - repack : create physical pbs and redo packing + * - repack : create physical pbs and redo packing *******************************************************************/ -#include "openfpga_repack.h" -#include "openfpga_bitstream.h" #include "openfpga_bitstream_command.h" +#include "openfpga_bitstream.h" +#include "openfpga_repack.h" + /* begin namespace openfpga */ namespace openfpga { /******************************************************************** * - Add a command to Shell environment: repack - * - Add associated options + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_repack_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_repack_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("repack"); /* Add an option '--design_constraints' */ - CommandOptionId opt_design_constraints = shell_cmd.add_option("design_constraints", false, "file path to the design constraints"); - shell_cmd.set_option_require_value(opt_design_constraints, openfpga::OPT_STRING); + CommandOptionId opt_design_constraints = shell_cmd.add_option( + "design_constraints", false, "file path to the design constraints"); + shell_cmd.set_option_require_value(opt_design_constraints, + openfpga::OPT_STRING); /* Add an option '--ignore_global_nets_on_pins' */ - CommandOptionId opt_ignore_global_nets = shell_cmd.add_option("ignore_global_nets_on_pins", false, "Specify the pins where global nets will be ignored. Routing traces are merged to other pins"); - shell_cmd.set_option_require_value(opt_ignore_global_nets, openfpga::OPT_STRING); + CommandOptionId opt_ignore_global_nets = + shell_cmd.add_option("ignore_global_nets_on_pins", false, + "Specify the pins where global nets will be ignored. " + "Routing traces are merged to other pins"); + shell_cmd.set_option_require_value(opt_ignore_global_nets, + openfpga::OPT_STRING); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); - + /* Add command 'repack' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Pack physical programmable logic blocks"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, "Pack physical programmable logic blocks"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, repack); @@ -46,31 +54,35 @@ ShellCommandId add_openfpga_repack_command(openfpga::Shell& she /******************************************************************** * - Add a command to Shell environment: build_architecture_bitstream - * - Add associated options + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_build_arch_bitstream_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_build_arch_bitstream_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("build_architecture_bitstream"); /* Add an option '--write_file' */ - CommandOptionId opt_write_file = shell_cmd.add_option("write_file", false, "file path to output the bitstream database"); + CommandOptionId opt_write_file = shell_cmd.add_option( + "write_file", false, "file path to output the bitstream database"); shell_cmd.set_option_require_value(opt_write_file, openfpga::OPT_STRING); /* Add an option '--read_file' */ - CommandOptionId opt_read_file = shell_cmd.add_option("read_file", false, "file path to read the bitstream database"); + CommandOptionId opt_read_file = shell_cmd.add_option( + "read_file", false, "file path to read the bitstream database"); shell_cmd.set_option_require_value(opt_read_file, openfpga::OPT_STRING); /* Add an option '--no_time_stamp' */ - shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files"); + shell_cmd.add_option("no_time_stamp", false, + "Do not print time stamp in output files"); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); - + /* Add command 'build_architecture_bitstream' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Build fabric-independent bitstream database"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, "Build fabric-independent bitstream database"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, fpga_bitstream); @@ -82,34 +94,40 @@ ShellCommandId add_openfpga_build_arch_bitstream_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_report_bitstream_distribution_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("report_bitstream_distribution"); /* Add an option '--file' */ - CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to output the bitstream distribution"); + CommandOptionId opt_file = shell_cmd.add_option( + "file", true, "file path to output the bitstream distribution"); shell_cmd.set_option_short_name(opt_file, "f"); shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); /* Add an option '--depth' */ - CommandOptionId opt_depth = shell_cmd.add_option("depth", false, "Specify the max. depth of blocks which will appear in report"); + CommandOptionId opt_depth = shell_cmd.add_option( + "depth", false, + "Specify the max. depth of blocks which will appear in report"); shell_cmd.set_option_require_value(opt_depth, openfpga::OPT_STRING); /* Add an option '--no_time_stamp' */ - shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files"); + shell_cmd.add_option("no_time_stamp", false, + "Do not print time stamp in output files"); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); - + /* Add command 'report_bitstream_distribution' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Report bitstream distribution"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, "Report bitstream distribution"); shell.set_command_class(shell_cmd_id, cmd_class_id); - shell.set_command_execute_function(shell_cmd_id, report_bitstream_distribution); + shell.set_command_execute_function(shell_cmd_id, + report_bitstream_distribution); /* Add command dependency to the Shell */ shell.set_command_dependency(shell_cmd_id, dependent_cmds); @@ -119,20 +137,23 @@ ShellCommandId add_openfpga_report_bitstream_distribution_command(openfpga::Shel /******************************************************************** * - Add a command to Shell environment: build_fabric_bitstream - * - Add associated options + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_build_fabric_bitstream_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_build_fabric_bitstream_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("build_fabric_bitstream"); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); /* Add command 'fabric_bitstream' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Reorganize the fabric-independent bitstream for the FPGA fabric created by FPGA-Verilog"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, + "Reorganize the fabric-independent bitstream for the " + "FPGA fabric created by FPGA-Verilog"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, build_fabric_bitstream); @@ -144,38 +165,48 @@ ShellCommandId add_openfpga_build_fabric_bitstream_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_fabric_bitstream_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_fabric_bitstream"); /* Add an option '--file' in short '-f'*/ - CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to output the fabric bitstream to plain text file"); + CommandOptionId opt_file = shell_cmd.add_option( + "file", true, + "file path to output the fabric bitstream to plain text file"); shell_cmd.set_option_short_name(opt_file, "f"); shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); /* Add an option '--file_format'*/ - CommandOptionId opt_file_format = shell_cmd.add_option("format", false, "file format of fabric bitstream [plain_text|xml]. Default: plain_text"); + CommandOptionId opt_file_format = shell_cmd.add_option( + "format", false, + "file format of fabric bitstream [plain_text|xml]. Default: plain_text"); shell_cmd.set_option_require_value(opt_file_format, openfpga::OPT_STRING); /* Add an option '--fast_configuration' */ - shell_cmd.add_option("fast_configuration", false, "Reduce the size of bitstream to be downloaded"); + shell_cmd.add_option("fast_configuration", false, + "Reduce the size of bitstream to be downloaded"); /* Add an option '--keep_dont_care_bit' */ - shell_cmd.add_option("keep_dont_care_bits", false, "Keep don't care bits in bitstream file; If not enabled, don't care bits are converted to logic '0' or '1'"); + shell_cmd.add_option( + "keep_dont_care_bits", false, + "Keep don't care bits in bitstream file; If not enabled, don't care bits " + "are converted to logic '0' or '1'"); /* Add an option '--no_time_stamp' */ - shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files"); + shell_cmd.add_option("no_time_stamp", false, + "Do not print time stamp in output files"); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); /* Add command 'fabric_bitstream' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Write the fabric-dependent bitstream to a file"); + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, "Write the fabric-dependent bitstream to a file"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, write_fabric_bitstream); @@ -187,28 +218,31 @@ ShellCommandId add_openfpga_write_fabric_bitstream_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_io_mapping_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_io_mapping"); /* Add an option '--file' in short '-f'*/ - CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to output the io mapping information"); + CommandOptionId opt_file = shell_cmd.add_option( + "file", true, "file path to output the io mapping information"); shell_cmd.set_option_short_name(opt_file, "f"); shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); /* Add an option '--no_time_stamp' */ - shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files"); + shell_cmd.add_option("no_time_stamp", false, + "Do not print time stamp in output files"); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); /* Add command 'fabric_bitstream' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Write the I/O mapping information to a file"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, "Write the I/O mapping information to a file"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, write_io_mapping); @@ -222,59 +256,80 @@ ShellCommandId add_openfpga_write_io_mapping_command(openfpga::Shell& shell) { - /* Get the unique id of 'build_fabric' command which is to be used in creating the dependency graph */ - const ShellCommandId& shell_cmd_build_fabric_id = shell.command(std::string("build_fabric")); + /* Get the unique id of 'build_fabric' command which is to be used in creating + * the dependency graph */ + const ShellCommandId& shell_cmd_build_fabric_id = + shell.command(std::string("build_fabric")); /* Add a new class of commands */ - ShellCommandClassId openfpga_bitstream_cmd_class = shell.add_command_class("FPGA-Bitstream"); + ShellCommandClassId openfpga_bitstream_cmd_class = + shell.add_command_class("FPGA-Bitstream"); - /******************************** - * Command 'repack' + /******************************** + * Command 'repack' */ /* The 'repack' command should NOT be executed before 'build_fabric' */ std::vector cmd_dependency_repack; cmd_dependency_repack.push_back(shell_cmd_build_fabric_id); - ShellCommandId shell_cmd_repack_id = add_openfpga_repack_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_repack); + ShellCommandId shell_cmd_repack_id = add_openfpga_repack_command( + shell, openfpga_bitstream_cmd_class, cmd_dependency_repack); - /******************************** - * Command 'build_architecture_bitstream' + /******************************** + * Command 'build_architecture_bitstream' */ - /* The 'build_architecture_bitstream' command should NOT be executed before 'repack' */ + /* The 'build_architecture_bitstream' command should NOT be executed before + * 'repack' */ std::vector cmd_dependency_build_arch_bitstream; cmd_dependency_build_arch_bitstream.push_back(shell_cmd_repack_id); - ShellCommandId shell_cmd_build_arch_bitstream_id = add_openfpga_build_arch_bitstream_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_build_arch_bitstream); + ShellCommandId shell_cmd_build_arch_bitstream_id = + add_openfpga_build_arch_bitstream_command( + shell, openfpga_bitstream_cmd_class, cmd_dependency_build_arch_bitstream); - /******************************** - * Command 'report_bitstream_distribution' + /******************************** + * Command 'report_bitstream_distribution' */ - /* The 'report_bitstream_distribution' command should NOT be executed before 'build_architecture_bitstream' */ + /* The 'report_bitstream_distribution' command should NOT be executed before + * 'build_architecture_bitstream' */ std::vector cmd_dependency_report_bitstream_distribution; - cmd_dependency_build_arch_bitstream.push_back(shell_cmd_build_arch_bitstream_id); - add_openfpga_report_bitstream_distribution_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_report_bitstream_distribution); + cmd_dependency_build_arch_bitstream.push_back( + shell_cmd_build_arch_bitstream_id); + add_openfpga_report_bitstream_distribution_command( + shell, openfpga_bitstream_cmd_class, + cmd_dependency_report_bitstream_distribution); - /******************************** - * Command 'build_fabric_bitstream' + /******************************** + * Command 'build_fabric_bitstream' */ - /* The 'build_fabric_bitstream' command should NOT be executed before 'build_architecture_bitstream' */ + /* The 'build_fabric_bitstream' command should NOT be executed before + * 'build_architecture_bitstream' */ std::vector cmd_dependency_build_fabric_bitstream; - cmd_dependency_build_fabric_bitstream.push_back(shell_cmd_build_arch_bitstream_id); - ShellCommandId shell_cmd_build_fabric_bitstream_id = add_openfpga_build_fabric_bitstream_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_build_fabric_bitstream); + cmd_dependency_build_fabric_bitstream.push_back( + shell_cmd_build_arch_bitstream_id); + ShellCommandId shell_cmd_build_fabric_bitstream_id = + add_openfpga_build_fabric_bitstream_command( + shell, openfpga_bitstream_cmd_class, + cmd_dependency_build_fabric_bitstream); - /******************************** - * Command 'write_fabric_bitstream' + /******************************** + * Command 'write_fabric_bitstream' */ - /* The 'write_fabric_bitstream' command should NOT be executed before 'build_fabric_bitstream' */ + /* The 'write_fabric_bitstream' command should NOT be executed before + * 'build_fabric_bitstream' */ std::vector cmd_dependency_write_fabric_bitstream; - cmd_dependency_write_fabric_bitstream.push_back(shell_cmd_build_fabric_bitstream_id); - add_openfpga_write_fabric_bitstream_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_write_fabric_bitstream); + cmd_dependency_write_fabric_bitstream.push_back( + shell_cmd_build_fabric_bitstream_id); + add_openfpga_write_fabric_bitstream_command( + shell, openfpga_bitstream_cmd_class, cmd_dependency_write_fabric_bitstream); - /******************************** - * Command 'write_io_mapping' + /******************************** + * Command 'write_io_mapping' + */ + /* The 'write_io_mapping' command should NOT be executed before 'build_fabric' */ - /* The 'write_io_mapping' command should NOT be executed before 'build_fabric' */ std::vector cmd_dependency_write_io_mapping; cmd_dependency_write_io_mapping.push_back(shell_cmd_build_fabric_id); - add_openfpga_write_io_mapping_command(shell, openfpga_bitstream_cmd_class, cmd_dependency_write_io_mapping); -} + add_openfpga_write_io_mapping_command(shell, openfpga_bitstream_cmd_class, + cmd_dependency_write_io_mapping); +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_bitstream_command.h b/openfpga/src/base/openfpga_bitstream_command.h index d58555dd8..073175f13 100644 --- a/openfpga/src/base/openfpga_bitstream_command.h +++ b/openfpga/src/base/openfpga_bitstream_command.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "shell.h" #include "openfpga_context.h" +#include "shell.h" /******************************************************************** * Function declaration @@ -14,7 +14,7 @@ /* begin namespace openfpga */ namespace openfpga { -void add_openfpga_bitstream_commands(openfpga::Shell& shell); +void add_openfpga_bitstream_commands(openfpga::Shell& shell); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_build_fabric.cpp b/openfpga/src/base/openfpga_build_fabric.cpp index 73611ff61..3c6194aab 100644 --- a/openfpga/src/base/openfpga_build_fabric.cpp +++ b/openfpga/src/base/openfpga_build_fabric.cpp @@ -2,23 +2,22 @@ * This file includes functions to compress the hierachy of routing architecture *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgashell library */ #include "command_exit_codes.h" /* Headers from fabrickey library */ -#include "read_xml_fabric_key.h" - +#include "build_device_module.h" +#include "build_fabric_global_port_info.h" +#include "build_fabric_io_location_map.h" #include "device_rr_gsb.h" #include "device_rr_gsb_utils.h" -#include "build_device_module.h" #include "fabric_hierarchy_writer.h" #include "fabric_key_writer.h" -#include "build_fabric_io_location_map.h" -#include "build_fabric_global_port_info.h" #include "openfpga_build_fabric.h" +#include "read_xml_fabric_key.h" /* Include global variables of VPR */ #include "globals.h" @@ -30,62 +29,86 @@ namespace openfpga { * Identify the unique GSBs from the Device RR GSB arrays * This function should only be called after the GSB builder is done *******************************************************************/ -static -void compress_routing_hierarchy(OpenfpgaContext& openfpga_ctx, - const bool& verbose_output) { - vtr::ScopedStartFinishTimer timer("Identify unique General Switch Blocks (GSBs)"); +static void compress_routing_hierarchy(OpenfpgaContext& openfpga_ctx, + const bool& verbose_output) { + vtr::ScopedStartFinishTimer timer( + "Identify unique General Switch Blocks (GSBs)"); /* Build unique module lists */ - openfpga_ctx.mutable_device_rr_gsb().build_unique_module(g_vpr_ctx.device().rr_graph); + openfpga_ctx.mutable_device_rr_gsb().build_unique_module( + g_vpr_ctx.device().rr_graph); /* Report the stats */ - VTR_LOGV(verbose_output, - "Detected %lu unique X-direction connection blocks from a total of %d (compression rate=%.2f%)\n", - openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANX), - find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), CHANX), - 100. * ((float)find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), CHANX) / (float)openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANX) - 1.)); + VTR_LOGV( + verbose_output, + "Detected %lu unique X-direction connection blocks from a total of %d " + "(compression rate=%.2f%)\n", + openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANX), + find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), CHANX), + 100. * + ((float)find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), + CHANX) / + (float)openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANX) - + 1.)); - VTR_LOGV(verbose_output, - "Detected %lu unique Y-direction connection blocks from a total of %d (compression rate=%.2f%)\n", - openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANY), - find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), CHANY), - 100. * ((float)find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), CHANY) / (float)openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANY) - 1.)); + VTR_LOGV( + verbose_output, + "Detected %lu unique Y-direction connection blocks from a total of %d " + "(compression rate=%.2f%)\n", + openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANY), + find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), CHANY), + 100. * + ((float)find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), + CHANY) / + (float)openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANY) - + 1.)); - VTR_LOGV(verbose_output, - "Detected %lu unique switch blocks from a total of %d (compression rate=%.2f%)\n", - openfpga_ctx.device_rr_gsb().get_num_sb_unique_module(), - find_device_rr_gsb_num_sb_modules(openfpga_ctx.device_rr_gsb()), - 100. * ((float)find_device_rr_gsb_num_sb_modules(openfpga_ctx.device_rr_gsb()) / (float)openfpga_ctx.device_rr_gsb().get_num_sb_unique_module() - 1.)); + VTR_LOGV( + verbose_output, + "Detected %lu unique switch blocks from a total of %d (compression " + "rate=%.2f%)\n", + openfpga_ctx.device_rr_gsb().get_num_sb_unique_module(), + find_device_rr_gsb_num_sb_modules(openfpga_ctx.device_rr_gsb()), + 100. * + ((float)find_device_rr_gsb_num_sb_modules(openfpga_ctx.device_rr_gsb()) / + (float)openfpga_ctx.device_rr_gsb().get_num_sb_unique_module() - + 1.)); - VTR_LOG("Detected %lu unique general switch blocks from a total of %d (compression rate=%.2f%)\n", - openfpga_ctx.device_rr_gsb().get_num_gsb_unique_module(), - find_device_rr_gsb_num_gsb_modules(openfpga_ctx.device_rr_gsb()), - 100. * ((float)find_device_rr_gsb_num_gsb_modules(openfpga_ctx.device_rr_gsb()) / (float)openfpga_ctx.device_rr_gsb().get_num_gsb_unique_module() - 1.)); + VTR_LOG( + "Detected %lu unique general switch blocks from a total of %d (compression " + "rate=%.2f%)\n", + openfpga_ctx.device_rr_gsb().get_num_gsb_unique_module(), + find_device_rr_gsb_num_gsb_modules(openfpga_ctx.device_rr_gsb()), + 100. * + ((float)find_device_rr_gsb_num_gsb_modules(openfpga_ctx.device_rr_gsb()) / + (float)openfpga_ctx.device_rr_gsb().get_num_gsb_unique_module() - + 1.)); } /******************************************************************** * Build the module graph for FPGA device *******************************************************************/ -int build_fabric(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - +int build_fabric(OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_frame_view = cmd.option("frame_view"); CommandOptionId opt_compress_routing = cmd.option("compress_routing"); CommandOptionId opt_duplicate_grid_pin = cmd.option("duplicate_grid_pin"); - CommandOptionId opt_gen_random_fabric_key = cmd.option("generate_random_fabric_key"); + CommandOptionId opt_gen_random_fabric_key = + cmd.option("generate_random_fabric_key"); CommandOptionId opt_write_fabric_key = cmd.option("write_fabric_key"); CommandOptionId opt_load_fabric_key = cmd.option("load_fabric_key"); CommandOptionId opt_verbose = cmd.option("verbose"); - + if (true == cmd_context.option_enable(cmd, opt_compress_routing)) { - compress_routing_hierarchy(openfpga_ctx, cmd_context.option_enable(cmd, opt_verbose)); + compress_routing_hierarchy(openfpga_ctx, + cmd_context.option_enable(cmd, opt_verbose)); /* Update flow manager to enable compress routing */ openfpga_ctx.mutable_flow_manager().set_compress_routing(true); } VTR_LOG("\n"); - /* Record the execution status in curr_status for each command + /* Record the execution status in curr_status for each command * and summarize them in the final status */ int curr_status = CMD_EXEC_SUCCESS; @@ -101,61 +124,63 @@ int build_fabric(OpenfpgaContext& openfpga_ctx, VTR_LOG("\n"); - curr_status = build_device_module_graph(openfpga_ctx.mutable_module_graph(), - openfpga_ctx.mutable_decoder_lib(), - openfpga_ctx.mutable_blwl_shift_register_banks(), - const_cast(openfpga_ctx), - g_vpr_ctx.device(), - cmd_context.option_enable(cmd, opt_frame_view), - cmd_context.option_enable(cmd, opt_compress_routing), - cmd_context.option_enable(cmd, opt_duplicate_grid_pin), - predefined_fabric_key, - cmd_context.option_enable(cmd, opt_gen_random_fabric_key), - cmd_context.option_enable(cmd, opt_verbose)); + curr_status = build_device_module_graph( + openfpga_ctx.mutable_module_graph(), openfpga_ctx.mutable_decoder_lib(), + openfpga_ctx.mutable_blwl_shift_register_banks(), + const_cast(openfpga_ctx), g_vpr_ctx.device(), + cmd_context.option_enable(cmd, opt_frame_view), + cmd_context.option_enable(cmd, opt_compress_routing), + cmd_context.option_enable(cmd, opt_duplicate_grid_pin), + predefined_fabric_key, + cmd_context.option_enable(cmd, opt_gen_random_fabric_key), + cmd_context.option_enable(cmd, opt_verbose)); - /* If there is any error, final status cannot be overwritten by a success flag */ + /* If there is any error, final status cannot be overwritten by a success flag + */ if (CMD_EXEC_SUCCESS != curr_status) { final_status = curr_status; } /* Build I/O location map */ - openfpga_ctx.mutable_io_location_map() = build_fabric_io_location_map(openfpga_ctx.module_graph(), - g_vpr_ctx.device().grid); + openfpga_ctx.mutable_io_location_map() = build_fabric_io_location_map( + openfpga_ctx.module_graph(), g_vpr_ctx.device().grid); /* Build fabric global port information */ - openfpga_ctx.mutable_fabric_global_port_info() = build_fabric_global_port_info(openfpga_ctx.module_graph(), - openfpga_ctx.arch().config_protocol, - openfpga_ctx.arch().tile_annotations, - openfpga_ctx.arch().circuit_lib); + openfpga_ctx.mutable_fabric_global_port_info() = + build_fabric_global_port_info( + openfpga_ctx.module_graph(), openfpga_ctx.arch().config_protocol, + openfpga_ctx.arch().tile_annotations, openfpga_ctx.arch().circuit_lib); /* Output fabric key if user requested */ if (true == cmd_context.option_enable(cmd, opt_write_fabric_key)) { - std::string fkey_fname = cmd_context.option_value(cmd, opt_write_fabric_key); + std::string fkey_fname = + cmd_context.option_value(cmd, opt_write_fabric_key); VTR_ASSERT(false == fkey_fname.empty()); - curr_status = write_fabric_key_to_xml_file(openfpga_ctx.module_graph(), - fkey_fname, - openfpga_ctx.arch().config_protocol, - openfpga_ctx.blwl_shift_register_banks(), - cmd_context.option_enable(cmd, opt_verbose)); - /* If there is any error, final status cannot be overwritten by a success flag */ + curr_status = + write_fabric_key_to_xml_file(openfpga_ctx.module_graph(), fkey_fname, + openfpga_ctx.arch().config_protocol, + openfpga_ctx.blwl_shift_register_banks(), + cmd_context.option_enable(cmd, opt_verbose)); + /* If there is any error, final status cannot be overwritten by a success + * flag */ if (CMD_EXEC_SUCCESS != curr_status) { final_status = curr_status; } } return final_status; -} +} /******************************************************************** * Write hierarchy of the module graph for FPGA device to a file *******************************************************************/ int write_fabric_hierarchy(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - + const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_verbose = cmd.option("verbose"); - /* Check the option '--file' is enabled or not - * Actually, it must be enabled as the shell interface will check + /* 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"); @@ -169,32 +194,31 @@ int write_fabric_hierarchy(const OpenfpgaContext& openfpga_ctx, depth = std::atoi(cmd_context.option_value(cmd, opt_depth).c_str()); /* Error out if we have negative depth */ if (0 > depth) { - VTR_LOG_ERROR("Invalid depth '%d' which should be 0 or a positive number!\n", - depth); - return CMD_EXEC_FATAL_ERROR; + VTR_LOG_ERROR( + "Invalid depth '%d' which should be 0 or a positive number!\n", depth); + return CMD_EXEC_FATAL_ERROR; } } std::string hie_file_name = cmd_context.option_value(cmd, opt_file); /* Write hierarchy to a file */ - return write_fabric_hierarchy_to_text_file(openfpga_ctx.module_graph(), - hie_file_name, - size_t(depth), - cmd_context.option_enable(cmd, opt_verbose)); + return write_fabric_hierarchy_to_text_file( + openfpga_ctx.module_graph(), hie_file_name, size_t(depth), + cmd_context.option_enable(cmd, opt_verbose)); } /******************************************************************** * Write the I/O information of module graph to a file *******************************************************************/ int write_fabric_io_info(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - + const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_verbose = cmd.option("verbose"); CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); - /* Check the option '--file' is enabled or not - * Actually, it must be enabled as the shell interface will check + /* 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"); @@ -204,10 +228,9 @@ int write_fabric_io_info(const OpenfpgaContext& openfpga_ctx, std::string file_name = cmd_context.option_value(cmd, opt_file); /* Write hierarchy to a file */ - return openfpga_ctx.io_location_map().write_to_xml_file(file_name, - !cmd_context.option_enable(cmd, opt_no_time_stamp), - cmd_context.option_enable(cmd, opt_verbose)); + return openfpga_ctx.io_location_map().write_to_xml_file( + file_name, !cmd_context.option_enable(cmd, opt_no_time_stamp), + cmd_context.option_enable(cmd, opt_verbose)); } - } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_build_fabric.h b/openfpga/src/base/openfpga_build_fabric.h index 4e5de082d..db295edaf 100644 --- a/openfpga/src/base/openfpga_build_fabric.h +++ b/openfpga/src/base/openfpga_build_fabric.h @@ -15,14 +15,15 @@ /* begin namespace openfpga */ namespace openfpga { -int build_fabric(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); +int build_fabric(OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context); int write_fabric_hierarchy(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); + const Command& cmd, + const CommandContext& cmd_context); int write_fabric_io_info(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); + const Command& cmd, const CommandContext& cmd_context); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_context.h b/openfpga/src/base/openfpga_context.h index 01d8b271a..bf247d950 100644 --- a/openfpga/src/base/openfpga_context.h +++ b/openfpga/src/base/openfpga_context.h @@ -2,33 +2,34 @@ #define OPENFPGA_CONTEXT_H #include -#include "vpr_context.h" -#include "openfpga_arch.h" -#include "simulation_setting.h" + +#include "bitstream_manager.h" #include "bitstream_setting.h" -#include "vpr_netlist_annotation.h" -#include "vpr_device_annotation.h" +#include "decoder_library.h" +#include "device_rr_gsb.h" +#include "fabric_bitstream.h" +#include "fabric_global_port_info.h" +#include "io_location_map.h" +#include "memory_bank_shift_register_banks.h" +#include "module_manager.h" +#include "mux_library.h" +#include "netlist_manager.h" +#include "openfpga_arch.h" +#include "openfpga_flow_manager.h" +#include "simulation_setting.h" +#include "tile_direct.h" +#include "vpr_bitstream_annotation.h" #include "vpr_clustering_annotation.h" +#include "vpr_context.h" +#include "vpr_device_annotation.h" +#include "vpr_netlist_annotation.h" #include "vpr_placement_annotation.h" #include "vpr_routing_annotation.h" -#include "vpr_bitstream_annotation.h" -#include "mux_library.h" -#include "decoder_library.h" -#include "tile_direct.h" -#include "module_manager.h" -#include "netlist_manager.h" -#include "openfpga_flow_manager.h" -#include "bitstream_manager.h" -#include "fabric_bitstream.h" -#include "device_rr_gsb.h" -#include "io_location_map.h" -#include "fabric_global_port_info.h" -#include "memory_bank_shift_register_banks.h" /******************************************************************** - * This file includes the declaration of the date structure - * OpenfpgaContext, which is used for data exchange between - * different modules in OpenFPGA shell environment + * This file includes the declaration of the date structure + * OpenfpgaContext, which is used for data exchange between + * different modules in OpenFPGA shell environment * * If a command of OpenFPGA needs to exchange data with other commands, * it must use this data structure to access/mutate. @@ -37,12 +38,11 @@ * Note: * Please respect to the following rules when using the OpenfpgaContext * 1. This data structure will be created only once in the main() function - * The data structure is design to be large and contain all the + * The data structure is design to be large and contain all the * data structure required by each module of OpenFPGA core engine. - * Do NOT create or duplicate in your own module! - * 2. Be clear in your mind if you want to access/mutate the data inside OpenfpgaContext - * Read-only data should be accessed by - * const OpenfpgaContext& + * Do NOT create or duplicate in your own module! + * 2. Be clear in your mind if you want to access/mutate the data inside + *OpenfpgaContext Read-only data should be accessed by const OpenfpgaContext& * Mutate should use reference * OpenfpgaContext& * 3. Please keep the definition of OpenfpgaContext short @@ -52,111 +52,172 @@ * This is due to that the data structures in the OpenFPGA context * are typically big in terms of memory *******************************************************************/ -class OpenfpgaContext : public Context { - public: /* Public accessors */ - const openfpga::Arch& arch() const { return arch_; } - const openfpga::SimulationSetting& simulation_setting() const { return sim_setting_; } - const openfpga::BitstreamSetting& bitstream_setting() const { return bitstream_setting_; } - const openfpga::VprDeviceAnnotation& vpr_device_annotation() const { return vpr_device_annotation_; } - const openfpga::VprNetlistAnnotation& vpr_netlist_annotation() const { return vpr_netlist_annotation_; } - const openfpga::VprClusteringAnnotation& vpr_clustering_annotation() const { return vpr_clustering_annotation_; } - const openfpga::VprPlacementAnnotation& vpr_placement_annotation() const { return vpr_placement_annotation_; } - const openfpga::VprRoutingAnnotation& vpr_routing_annotation() const { return vpr_routing_annotation_; } - const openfpga::VprBitstreamAnnotation& vpr_bitstream_annotation() const { return vpr_bitstream_annotation_; } - const openfpga::DeviceRRGSB& device_rr_gsb() const { return device_rr_gsb_; } - const openfpga::MuxLibrary& mux_lib() const { return mux_lib_; } - const openfpga::DecoderLibrary& decoder_lib() const { return decoder_lib_; } - const openfpga::MemoryBankShiftRegisterBanks& blwl_shift_register_banks() const { return blwl_sr_banks_; } - const openfpga::TileDirect& tile_direct() const { return tile_direct_; } - const openfpga::ModuleManager& module_graph() const { return module_graph_; } - const openfpga::FlowManager& flow_manager() const { return flow_manager_; } - const openfpga::BitstreamManager& bitstream_manager() const { return bitstream_manager_; } - const openfpga::FabricBitstream& fabric_bitstream() const { return fabric_bitstream_; } - const openfpga::IoLocationMap& io_location_map() const { return io_location_map_; } - const openfpga::FabricGlobalPortInfo& fabric_global_port_info() const { return fabric_global_port_info_; } - const openfpga::NetlistManager& verilog_netlists() const { return verilog_netlists_; } - const openfpga::NetlistManager& spice_netlists() const { return spice_netlists_; } - public: /* Public mutators */ - openfpga::Arch& mutable_arch() { return arch_; } - openfpga::SimulationSetting& mutable_simulation_setting() { return sim_setting_; } - openfpga::BitstreamSetting& mutable_bitstream_setting() { return bitstream_setting_; } - openfpga::VprDeviceAnnotation& mutable_vpr_device_annotation() { return vpr_device_annotation_; } - openfpga::VprNetlistAnnotation& mutable_vpr_netlist_annotation() { return vpr_netlist_annotation_; } - openfpga::VprClusteringAnnotation& mutable_vpr_clustering_annotation() { return vpr_clustering_annotation_; } - openfpga::VprPlacementAnnotation& mutable_vpr_placement_annotation() { return vpr_placement_annotation_; } - openfpga::VprRoutingAnnotation& mutable_vpr_routing_annotation() { return vpr_routing_annotation_; } - openfpga::VprBitstreamAnnotation& mutable_vpr_bitstream_annotation() { return vpr_bitstream_annotation_; } - openfpga::DeviceRRGSB& mutable_device_rr_gsb() { return device_rr_gsb_; } - openfpga::MuxLibrary& mutable_mux_lib() { return mux_lib_; } - openfpga::DecoderLibrary& mutable_decoder_lib() { return decoder_lib_; } - openfpga::MemoryBankShiftRegisterBanks& mutable_blwl_shift_register_banks() { return blwl_sr_banks_; } - openfpga::TileDirect& mutable_tile_direct() { return tile_direct_; } - openfpga::ModuleManager& mutable_module_graph() { return module_graph_; } - openfpga::FlowManager& mutable_flow_manager() { return flow_manager_; } - openfpga::BitstreamManager& mutable_bitstream_manager() { return bitstream_manager_; } - openfpga::FabricBitstream& mutable_fabric_bitstream() { return fabric_bitstream_; } - openfpga::IoLocationMap& mutable_io_location_map() { return io_location_map_; } - openfpga::FabricGlobalPortInfo& mutable_fabric_global_port_info() { return fabric_global_port_info_; } - openfpga::NetlistManager& mutable_verilog_netlists() { return verilog_netlists_; } - openfpga::NetlistManager& mutable_spice_netlists() { return spice_netlists_; } - private: /* Internal data */ - /* Data structure to store information from read_openfpga_arch library */ - openfpga::Arch arch_; - openfpga::SimulationSetting sim_setting_; - openfpga::BitstreamSetting bitstream_setting_; +class OpenfpgaContext : public Context { + public: /* Public accessors */ + const openfpga::Arch& arch() const { return arch_; } + const openfpga::SimulationSetting& simulation_setting() const { + return sim_setting_; + } + const openfpga::BitstreamSetting& bitstream_setting() const { + return bitstream_setting_; + } + const openfpga::VprDeviceAnnotation& vpr_device_annotation() const { + return vpr_device_annotation_; + } + const openfpga::VprNetlistAnnotation& vpr_netlist_annotation() const { + return vpr_netlist_annotation_; + } + const openfpga::VprClusteringAnnotation& vpr_clustering_annotation() const { + return vpr_clustering_annotation_; + } + const openfpga::VprPlacementAnnotation& vpr_placement_annotation() const { + return vpr_placement_annotation_; + } + const openfpga::VprRoutingAnnotation& vpr_routing_annotation() const { + return vpr_routing_annotation_; + } + const openfpga::VprBitstreamAnnotation& vpr_bitstream_annotation() const { + return vpr_bitstream_annotation_; + } + const openfpga::DeviceRRGSB& device_rr_gsb() const { return device_rr_gsb_; } + const openfpga::MuxLibrary& mux_lib() const { return mux_lib_; } + const openfpga::DecoderLibrary& decoder_lib() const { return decoder_lib_; } + const openfpga::MemoryBankShiftRegisterBanks& blwl_shift_register_banks() + const { + return blwl_sr_banks_; + } + const openfpga::TileDirect& tile_direct() const { return tile_direct_; } + const openfpga::ModuleManager& module_graph() const { return module_graph_; } + const openfpga::FlowManager& flow_manager() const { return flow_manager_; } + const openfpga::BitstreamManager& bitstream_manager() const { + return bitstream_manager_; + } + const openfpga::FabricBitstream& fabric_bitstream() const { + return fabric_bitstream_; + } + const openfpga::IoLocationMap& io_location_map() const { + return io_location_map_; + } + const openfpga::FabricGlobalPortInfo& fabric_global_port_info() const { + return fabric_global_port_info_; + } + const openfpga::NetlistManager& verilog_netlists() const { + return verilog_netlists_; + } + const openfpga::NetlistManager& spice_netlists() const { + return spice_netlists_; + } - /* Annotation to pb_type of VPR */ - openfpga::VprDeviceAnnotation vpr_device_annotation_; + public: /* Public mutators */ + openfpga::Arch& mutable_arch() { return arch_; } + openfpga::SimulationSetting& mutable_simulation_setting() { + return sim_setting_; + } + openfpga::BitstreamSetting& mutable_bitstream_setting() { + return bitstream_setting_; + } + openfpga::VprDeviceAnnotation& mutable_vpr_device_annotation() { + return vpr_device_annotation_; + } + openfpga::VprNetlistAnnotation& mutable_vpr_netlist_annotation() { + return vpr_netlist_annotation_; + } + openfpga::VprClusteringAnnotation& mutable_vpr_clustering_annotation() { + return vpr_clustering_annotation_; + } + openfpga::VprPlacementAnnotation& mutable_vpr_placement_annotation() { + return vpr_placement_annotation_; + } + openfpga::VprRoutingAnnotation& mutable_vpr_routing_annotation() { + return vpr_routing_annotation_; + } + openfpga::VprBitstreamAnnotation& mutable_vpr_bitstream_annotation() { + return vpr_bitstream_annotation_; + } + openfpga::DeviceRRGSB& mutable_device_rr_gsb() { return device_rr_gsb_; } + openfpga::MuxLibrary& mutable_mux_lib() { return mux_lib_; } + openfpga::DecoderLibrary& mutable_decoder_lib() { return decoder_lib_; } + openfpga::MemoryBankShiftRegisterBanks& mutable_blwl_shift_register_banks() { + return blwl_sr_banks_; + } + openfpga::TileDirect& mutable_tile_direct() { return tile_direct_; } + openfpga::ModuleManager& mutable_module_graph() { return module_graph_; } + openfpga::FlowManager& mutable_flow_manager() { return flow_manager_; } + openfpga::BitstreamManager& mutable_bitstream_manager() { + return bitstream_manager_; + } + openfpga::FabricBitstream& mutable_fabric_bitstream() { + return fabric_bitstream_; + } + openfpga::IoLocationMap& mutable_io_location_map() { + return io_location_map_; + } + openfpga::FabricGlobalPortInfo& mutable_fabric_global_port_info() { + return fabric_global_port_info_; + } + openfpga::NetlistManager& mutable_verilog_netlists() { + return verilog_netlists_; + } + openfpga::NetlistManager& mutable_spice_netlists() { return spice_netlists_; } - /* Naming fix to netlist */ - openfpga::VprNetlistAnnotation vpr_netlist_annotation_; + private: /* Internal data */ + /* Data structure to store information from read_openfpga_arch library */ + openfpga::Arch arch_; + openfpga::SimulationSetting sim_setting_; + openfpga::BitstreamSetting bitstream_setting_; - /* Pin net fix to cluster results */ - openfpga::VprClusteringAnnotation vpr_clustering_annotation_; + /* Annotation to pb_type of VPR */ + openfpga::VprDeviceAnnotation vpr_device_annotation_; - /* Placement results */ - openfpga::VprPlacementAnnotation vpr_placement_annotation_; + /* Naming fix to netlist */ + openfpga::VprNetlistAnnotation vpr_netlist_annotation_; - /* Routing results annotation */ - openfpga::VprRoutingAnnotation vpr_routing_annotation_; + /* Pin net fix to cluster results */ + openfpga::VprClusteringAnnotation vpr_clustering_annotation_; - /* Annotation to pb_type of VPR */ - openfpga::VprBitstreamAnnotation vpr_bitstream_annotation_; + /* Placement results */ + openfpga::VprPlacementAnnotation vpr_placement_annotation_; - /* Device-level annotation */ - openfpga::DeviceRRGSB device_rr_gsb_{vpr_device_annotation_}; - - /* Library of physical implmentation of routing multiplexers */ - openfpga::MuxLibrary mux_lib_; + /* Routing results annotation */ + openfpga::VprRoutingAnnotation vpr_routing_annotation_; - /* Library of physical implmentation of decoders */ - openfpga::DecoderLibrary decoder_lib_; + /* Annotation to pb_type of VPR */ + openfpga::VprBitstreamAnnotation vpr_bitstream_annotation_; - /* Inner/inter-column/row tile direct connections */ - openfpga::TileDirect tile_direct_; + /* Device-level annotation */ + openfpga::DeviceRRGSB device_rr_gsb_{vpr_device_annotation_}; - /* Library of shift register banks that control BLs and WLs - * @note Only used when memory bank is used as configuration protocol - */ - openfpga::MemoryBankShiftRegisterBanks blwl_sr_banks_; + /* Library of physical implmentation of routing multiplexers */ + openfpga::MuxLibrary mux_lib_; - /* Fabric module graph */ - openfpga::ModuleManager module_graph_; - openfpga::IoLocationMap io_location_map_; - openfpga::FabricGlobalPortInfo fabric_global_port_info_; + /* Library of physical implmentation of decoders */ + openfpga::DecoderLibrary decoder_lib_; - /* Bitstream database */ - openfpga::BitstreamManager bitstream_manager_; - openfpga::FabricBitstream fabric_bitstream_; + /* Inner/inter-column/row tile direct connections */ + openfpga::TileDirect tile_direct_; - /* Netlist database - * TODO: Each format should have an independent entry - */ - openfpga::NetlistManager verilog_netlists_; - openfpga::NetlistManager spice_netlists_; + /* Library of shift register banks that control BLs and WLs + * @note Only used when memory bank is used as configuration protocol + */ + openfpga::MemoryBankShiftRegisterBanks blwl_sr_banks_; - /* Flow status */ - openfpga::FlowManager flow_manager_; + /* Fabric module graph */ + openfpga::ModuleManager module_graph_; + openfpga::IoLocationMap io_location_map_; + openfpga::FabricGlobalPortInfo fabric_global_port_info_; + + /* Bitstream database */ + openfpga::BitstreamManager bitstream_manager_; + openfpga::FabricBitstream fabric_bitstream_; + + /* Netlist database + * TODO: Each format should have an independent entry + */ + openfpga::NetlistManager verilog_netlists_; + openfpga::NetlistManager spice_netlists_; + + /* Flow status */ + openfpga::FlowManager flow_manager_; }; #endif diff --git a/openfpga/src/base/openfpga_flow_manager.cpp b/openfpga/src/base/openfpga_flow_manager.cpp index 1a50524df..7bda8793a 100644 --- a/openfpga/src/base/openfpga_flow_manager.cpp +++ b/openfpga/src/base/openfpga_flow_manager.cpp @@ -1,10 +1,10 @@ /****************************************************************************** * Memember functions for data structure FlowManager ******************************************************************************/ -#include "vtr_assert.h" - #include "openfpga_flow_manager.h" +#include "vtr_assert.h" + /* begin namespace openfpga */ namespace openfpga { @@ -17,11 +17,9 @@ FlowManager::FlowManager() { } /************************************************** - * Public Accessors + * Public Accessors *************************************************/ -bool FlowManager::compress_routing() const { - return compress_routing_; -} +bool FlowManager::compress_routing() const { return compress_routing_; } /****************************************************************************** * Private Mutators @@ -30,5 +28,4 @@ void FlowManager::set_compress_routing(const bool& enabled) { compress_routing_ = enabled; } - } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_flow_manager.h b/openfpga/src/base/openfpga_flow_manager.h index e9f6f02c2..fc57afa81 100644 --- a/openfpga/src/base/openfpga_flow_manager.h +++ b/openfpga/src/base/openfpga_flow_manager.h @@ -15,14 +15,17 @@ namespace openfpga { * *******************************************************************/ class FlowManager { - public: /* Public constructor */ - FlowManager(); - public: /* Public accessors */ - bool compress_routing() const; - public: /* Public mutators */ - void set_compress_routing(const bool& enabled); - private: /* Internal Data */ - bool compress_routing_; + public: /* Public constructor */ + FlowManager(); + + public: /* Public accessors */ + bool compress_routing() const; + + public: /* Public mutators */ + void set_compress_routing(const bool& enabled); + + private: /* Internal Data */ + bool compress_routing_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/base/openfpga_interconnect_types.h b/openfpga/src/base/openfpga_interconnect_types.h index a402323f0..010da8823 100644 --- a/openfpga/src/base/openfpga_interconnect_types.h +++ b/openfpga/src/base/openfpga_interconnect_types.h @@ -14,7 +14,7 @@ enum e_circuit_pb_port_type { CIRCUIT_PB_PORT_INPUT, CIRCUIT_PB_PORT_OUTPUT, CIRCUIT_PB_PORT_CLOCK, - NUM_CIRCUIT_PB_PORT_TYPES + NUM_CIRCUIT_PB_PORT_TYPES }; } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_link_arch.cpp b/openfpga/src/base/openfpga_link_arch.cpp index eed364057..9c2b666b0 100644 --- a/openfpga/src/base/openfpga_link_arch.cpp +++ b/openfpga/src/base/openfpga_link_arch.cpp @@ -4,30 +4,29 @@ *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" #include "vtr_assert.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgashell library */ #include "command_exit_codes.h" /* Headers from vpr library */ -#include "read_activity.h" - -#include "vpr_device_annotation.h" -#include "pb_type_utils.h" -#include "annotate_physical_tiles.h" -#include "annotate_pb_types.h" +#include "annotate_bitstream_setting.h" +#include "annotate_clustering.h" #include "annotate_pb_graph.h" -#include "openfpga_annotate_routing.h" +#include "annotate_pb_types.h" +#include "annotate_physical_tiles.h" +#include "annotate_placement.h" #include "annotate_rr_graph.h" #include "annotate_simulation_setting.h" -#include "annotate_bitstream_setting.h" -#include "mux_library_builder.h" #include "build_tile_direct.h" -#include "annotate_clustering.h" -#include "annotate_placement.h" +#include "mux_library_builder.h" +#include "openfpga_annotate_routing.h" #include "openfpga_link_arch.h" +#include "pb_type_utils.h" +#include "read_activity.h" +#include "vpr_device_annotation.h" /* Include global variables of VPR */ #include "globals.h" @@ -41,24 +40,28 @@ namespace openfpga { * - Currently we only support uni-directional * It means every routing tracks must have a direction *******************************************************************/ -static -bool is_vpr_rr_graph_supported(const RRGraphView& rr_graph) { +static bool is_vpr_rr_graph_supported(const RRGraphView& rr_graph) { /* Check if the rr_graph is uni-directional*/ for (const RRNodeId& node : rr_graph.nodes()) { - if (CHANX != rr_graph.node_type(node) && CHANY != rr_graph.node_type(node)) { + if (CHANX != rr_graph.node_type(node) && + CHANY != rr_graph.node_type(node)) { continue; } if (Direction::BIDIR == rr_graph.node_direction(node)) { - VTR_LOG_ERROR("Routing resource graph is bi-directional. OpenFPGA currently supports uni-directional routing architecture only.\n"); + VTR_LOG_ERROR( + "Routing resource graph is bi-directional. OpenFPGA currently supports " + "uni-directional routing architecture only.\n"); return false; } if (Direction::NONE == rr_graph.node_direction(node)) { - VTR_LOG_ERROR("Routing resource graph contains routing tracks which has not specific direction. OpenFPGA currently supports uni-directional routing architecture only.\n"); + VTR_LOG_ERROR( + "Routing resource graph contains routing tracks which has not specific " + "direction. OpenFPGA currently supports uni-directional routing " + "architecture only.\n"); return false; } - } - + return true; } @@ -70,18 +73,18 @@ bool is_vpr_rr_graph_supported(const RRGraphView& rr_graph) { * - physical pb_graph nodes and pb_graph pins * - circuit models for global routing architecture *******************************************************************/ -int link_arch(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - - vtr::ScopedStartFinishTimer timer("Link OpenFPGA architecture to VPR architecture"); +int link_arch(OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { + vtr::ScopedStartFinishTimer timer( + "Link OpenFPGA architecture to VPR architecture"); CommandOptionId opt_activity_file = cmd.option("activity_file"); CommandOptionId opt_sort_edge = cmd.option("sort_gsb_chan_node_in_edges"); CommandOptionId opt_verbose = cmd.option("verbose"); /* Build fast look-up between physical tile pin index and port information */ - build_physical_tile_pin2port_info(g_vpr_ctx.device(), - openfpga_ctx.mutable_vpr_device_annotation()); + build_physical_tile_pin2port_info( + g_vpr_ctx.device(), openfpga_ctx.mutable_vpr_device_annotation()); /* Annotate pb_type graphs * - physical pb_type @@ -95,36 +98,38 @@ int link_arch(OpenfpgaContext& openfpga_ctx, /* Annotate pb_graph_nodes * - Give unique index to each node in the same type * - Bind operating pb_graph_node to their physical pb_graph_node - * - Bind pins from operating pb_graph_node to their physical pb_graph_node pins + * - Bind pins from operating pb_graph_node to their physical pb_graph_node + * pins */ annotate_pb_graph(g_vpr_ctx.device(), openfpga_ctx.mutable_vpr_device_annotation(), cmd_context.option_enable(cmd, opt_verbose)); /* Annotate routing architecture to circuit library */ - annotate_rr_graph_circuit_models(g_vpr_ctx.device(), - openfpga_ctx.arch(), + annotate_rr_graph_circuit_models(g_vpr_ctx.device(), openfpga_ctx.arch(), openfpga_ctx.mutable_vpr_device_annotation(), cmd_context.option_enable(cmd, opt_verbose)); /* Annotate routing results: - * - net mapping to each rr_node - * - previous nodes driving each rr_node + * - net mapping to each rr_node + * - previous nodes driving each rr_node */ - openfpga_ctx.mutable_vpr_routing_annotation().init(g_vpr_ctx.device().rr_graph); + openfpga_ctx.mutable_vpr_routing_annotation().init( + g_vpr_ctx.device().rr_graph); - annotate_vpr_rr_node_nets(g_vpr_ctx.device(), g_vpr_ctx.clustering(), g_vpr_ctx.routing(), + annotate_vpr_rr_node_nets(g_vpr_ctx.device(), g_vpr_ctx.clustering(), + g_vpr_ctx.routing(), openfpga_ctx.mutable_vpr_routing_annotation(), cmd_context.option_enable(cmd, opt_verbose)); - annotate_rr_node_previous_nodes(g_vpr_ctx.device(), g_vpr_ctx.clustering(), g_vpr_ctx.routing(), + annotate_rr_node_previous_nodes(g_vpr_ctx.device(), g_vpr_ctx.clustering(), + g_vpr_ctx.routing(), openfpga_ctx.mutable_vpr_routing_annotation(), cmd_context.option_enable(cmd, opt_verbose)); - /* Build the routing graph annotation * - RRGSB - * - DeviceRRGSB + * - DeviceRRGSB */ if (false == is_vpr_rr_graph_supported(g_vpr_ctx.device().rr_graph)) { return CMD_EXEC_FATAL_ERROR; @@ -132,82 +137,83 @@ int link_arch(OpenfpgaContext& openfpga_ctx, /* Build incoming edges as VPR only builds fan-out edges for each node */ g_vpr_ctx.mutable_device().rr_graph_builder.build_in_edges(); - VTR_LOG("Built %ld incoming edges for routing resource graph\n", g_vpr_ctx.device().rr_graph.in_edges_count()); + 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(), 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(g_vpr_ctx.device().rr_graph, - openfpga_ctx.mutable_device_rr_gsb(), - cmd_context.option_enable(cmd, opt_verbose)); - sort_device_rr_gsb_ipin_node_in_edges(g_vpr_ctx.device().rr_graph, - openfpga_ctx.mutable_device_rr_gsb(), - cmd_context.option_enable(cmd, opt_verbose)); - } + sort_device_rr_gsb_chan_node_in_edges( + g_vpr_ctx.device().rr_graph, openfpga_ctx.mutable_device_rr_gsb(), + cmd_context.option_enable(cmd, opt_verbose)); + sort_device_rr_gsb_ipin_node_in_edges( + g_vpr_ctx.device().rr_graph, openfpga_ctx.mutable_device_rr_gsb(), + cmd_context.option_enable(cmd, opt_verbose)); + } /* Build multiplexer library */ - openfpga_ctx.mutable_mux_lib() = build_device_mux_library(g_vpr_ctx.device(), - const_cast(openfpga_ctx)); + openfpga_ctx.mutable_mux_lib() = build_device_mux_library( + g_vpr_ctx.device(), const_cast(openfpga_ctx)); /* Build tile direct annotation */ - openfpga_ctx.mutable_tile_direct() = build_device_tile_direct(g_vpr_ctx.device(), - openfpga_ctx.arch().arch_direct, - cmd_context.option_enable(cmd, opt_verbose)); + openfpga_ctx.mutable_tile_direct() = build_device_tile_direct( + g_vpr_ctx.device(), openfpga_ctx.arch().arch_direct, + cmd_context.option_enable(cmd, opt_verbose)); /* Annotate clustering results */ - if (CMD_EXEC_FATAL_ERROR == annotate_post_routing_cluster_sync_results(g_vpr_ctx.device(), - g_vpr_ctx.clustering(), - openfpga_ctx.mutable_vpr_clustering_annotation())) { - + if (CMD_EXEC_FATAL_ERROR == + annotate_post_routing_cluster_sync_results( + g_vpr_ctx.device(), g_vpr_ctx.clustering(), + openfpga_ctx.mutable_vpr_clustering_annotation())) { return CMD_EXEC_FATAL_ERROR; } /* Annotate placement results */ - annotate_mapped_blocks(g_vpr_ctx.device(), - g_vpr_ctx.clustering(), + annotate_mapped_blocks(g_vpr_ctx.device(), g_vpr_ctx.clustering(), g_vpr_ctx.placement(), openfpga_ctx.mutable_vpr_placement_annotation()); /* Read activity file is manadatory in the following flow-run settings - * - When users specify that number of clock cycles + * - When users specify that number of clock cycles * should be inferred from FPGA implmentation * - When FPGA-SPICE is enabled */ std::unordered_map net_activity; if (true == cmd_context.option_enable(cmd, opt_activity_file)) { - net_activity = read_activity(g_vpr_ctx.atom().nlist, - cmd_context.option_value(cmd, opt_activity_file).c_str()); + net_activity = + read_activity(g_vpr_ctx.atom().nlist, + cmd_context.option_value(cmd, opt_activity_file).c_str()); } - /* TODO: Annotate the number of clock cycles and clock frequency by following VPR results - * We SHOULD create a new simulation setting for OpenFPGA use only + /* TODO: Annotate the number of clock cycles and clock frequency by following + * VPR results We SHOULD create a new simulation setting for OpenFPGA use only * Avoid overwrite the raw data achieved when parsing!!! */ /* OVERWRITE the simulation setting in openfpga context from the arch - * TODO: This will be removed when openfpga flow is updated + * TODO: This will be removed when openfpga flow is updated */ - //openfpga_ctx.mutable_simulation_setting() = openfpga_ctx.mutable_arch().sim_setting; - if (CMD_EXEC_FATAL_ERROR == annotate_simulation_setting(g_vpr_ctx.atom(), - g_vpr_ctx.clustering(), - net_activity, - openfpga_ctx.mutable_simulation_setting())) { + // openfpga_ctx.mutable_simulation_setting() = + // openfpga_ctx.mutable_arch().sim_setting; + if (CMD_EXEC_FATAL_ERROR == + annotate_simulation_setting(g_vpr_ctx.atom(), g_vpr_ctx.clustering(), + net_activity, + openfpga_ctx.mutable_simulation_setting())) { return CMD_EXEC_FATAL_ERROR; } /* Build bitstream annotation based on bitstream settings */ - if (CMD_EXEC_FATAL_ERROR == annotate_bitstream_setting(openfpga_ctx.bitstream_setting(), - g_vpr_ctx.device(), - openfpga_ctx.vpr_device_annotation(), - openfpga_ctx.mutable_vpr_bitstream_annotation())) { - + if (CMD_EXEC_FATAL_ERROR == + annotate_bitstream_setting( + openfpga_ctx.bitstream_setting(), g_vpr_ctx.device(), + openfpga_ctx.vpr_device_annotation(), + openfpga_ctx.mutable_vpr_bitstream_annotation())) { return CMD_EXEC_FATAL_ERROR; } - /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; -} +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_link_arch.h b/openfpga/src/base/openfpga_link_arch.h index 8eba64386..f2f66f941 100644 --- a/openfpga/src/base/openfpga_link_arch.h +++ b/openfpga/src/base/openfpga_link_arch.h @@ -15,8 +15,8 @@ /* begin namespace openfpga */ namespace openfpga { -int link_arch(OpenfpgaContext& openfpga_context, - const Command& cmd, const CommandContext& cmd_context); +int link_arch(OpenfpgaContext& openfpga_context, const Command& cmd, + const CommandContext& cmd_context); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_lut_truth_table_fixup.cpp b/openfpga/src/base/openfpga_lut_truth_table_fixup.cpp index 396842dcd..2f846e592 100644 --- a/openfpga/src/base/openfpga_lut_truth_table_fixup.cpp +++ b/openfpga/src/base/openfpga_lut_truth_table_fixup.cpp @@ -1,21 +1,20 @@ /******************************************************************** - * This file includes functions to fix up the pb pin mapping results + * This file includes functions to fix up the pb pin mapping results * after routing optimization *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" #include "vtr_assert.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgashell library */ #include "command_exit_codes.h" /* Headers from vpr library */ -#include "vpr_utils.h" - -#include "pb_type_utils.h" #include "lut_utils.h" #include "openfpga_lut_truth_table_fixup.h" +#include "pb_type_utils.h" +#include "vpr_utils.h" /* Include global variables of VPR */ #include "globals.h" @@ -27,15 +26,12 @@ namespace openfpga { * Apply the fix-up to truth table of LUT according to its pin * rotation status by packer * - * Note: + * Note: * - pb must represents a LUT pb in the graph and it should be primitive *******************************************************************/ -static -void fix_up_lut_atom_block_truth_table(const AtomContext& atom_ctx, - t_pb* pb, - const t_pb_routes& pb_route, - VprClusteringAnnotation& vpr_clustering_annotation, - const bool& verbose) { +static void fix_up_lut_atom_block_truth_table( + const AtomContext& atom_ctx, t_pb* pb, const t_pb_routes& pb_route, + VprClusteringAnnotation& vpr_clustering_annotation, const bool& verbose) { t_pb_graph_node* pb_graph_node = pb->pb_graph_node; t_pb_type* pb_type = pb->pb_graph_node->pb_type; @@ -43,7 +39,8 @@ void fix_up_lut_atom_block_truth_table(const AtomContext& atom_ctx, for (int iport = 0; iport < pb_type->num_ports; ++iport) { /* We only care about input ports whose pins are equivalent */ - if (IN_PORT != pb_type->ports[iport].type || true == pb_type->ports[iport].is_clock) { + if (IN_PORT != pb_type->ports[iport].type || + true == pb_type->ports[iport].is_clock) { continue; } if (pb_type->ports[iport].equivalent == PortEquivalence::NONE) { @@ -53,26 +50,30 @@ void fix_up_lut_atom_block_truth_table(const AtomContext& atom_ctx, AtomBlockId atom_blk = atom_ctx.nlist.find_block(pb->name); VTR_ASSERT(atom_blk); - /* Port exists (some LUTs may have no input and hence no port in the atom netlist) */ - AtomPortId atom_port = atom_ctx.nlist.find_atom_port(atom_blk, pb_type->ports[iport].model_port); - if (!atom_port) { + /* Port exists (some LUTs may have no input and hence no port in the atom + * netlist) */ + AtomPortId atom_port = + atom_ctx.nlist.find_atom_port(atom_blk, pb_type->ports[iport].model_port); + if (!atom_port) { continue; } /* Find the pin rotation status and record it , - * Note that some LUT inputs may not be used, we set them to be open by default + * Note that some LUT inputs may not be used, we set them to be open by + * default */ std::vector rotated_pin_map(pb_type->ports[iport].num_pins, -1); for (int ipin = 0; ipin < pb_type->ports[iport].num_pins; ++ipin) { - int node_index = pb_graph_node->input_pins[iport][ipin].pin_count_in_cluster; + int node_index = + pb_graph_node->input_pins[iport][ipin].pin_count_in_cluster; if (pb_route.count(node_index)) { - /* The pin is mapped to a net, find the original pin in the atom netlist */ + /* The pin is mapped to a net, find the original pin in the atom netlist + */ AtomNetId atom_net = pb_route[node_index].atom_net_id; VTR_ASSERT(atom_net); for (AtomPinId atom_pin : atom_ctx.nlist.port_pins(atom_port)) { - AtomNetId atom_pin_net = atom_ctx.nlist.pin_net(atom_pin); if (atom_pin_net == atom_net) { @@ -85,10 +86,13 @@ void fix_up_lut_atom_block_truth_table(const AtomContext& atom_ctx, /* We can apply truth table adaption now * For unused inputs : insert dont care - * For used inputs : find the bit in the truth table rows and move it by the given mapping + * For used inputs : find the bit in the truth table rows and move it by the + * given mapping */ - const AtomNetlist::TruthTable& orig_tt = atom_ctx.nlist.block_truth_table(atom_blk); - const AtomNetlist::TruthTable& adapt_tt = lut_truth_table_adaption(orig_tt, rotated_pin_map); + const AtomNetlist::TruthTable& orig_tt = + atom_ctx.nlist.block_truth_table(atom_blk); + const AtomNetlist::TruthTable& adapt_tt = + lut_truth_table_adaption(orig_tt, rotated_pin_map); vpr_clustering_annotation.adapt_truth_table(pb, adapt_tt); /* Print info is in the verbose mode */ @@ -126,30 +130,28 @@ void fix_up_lut_atom_block_truth_table(const AtomContext& atom_ctx, } /******************************************************************** - * This function recursively visits the pb graph until we reach a - * LUT pb_type (primitive node in the pb_graph with a class type + * This function recursively visits the pb graph until we reach a + * LUT pb_type (primitive node in the pb_graph with a class type * of LUT_CLASS * Once we find a LUT node, we will apply the fix-up *******************************************************************/ -static -void rec_adapt_lut_pb_tt(const AtomContext& atom_ctx, - t_pb* pb, - const t_pb_routes& pb_route, - VprClusteringAnnotation& vpr_clustering_annotation, - const bool& verbose) { - t_pb_graph_node* pb_graph_node = pb->pb_graph_node; +static void rec_adapt_lut_pb_tt( + const AtomContext& atom_ctx, t_pb* pb, const t_pb_routes& pb_route, + VprClusteringAnnotation& vpr_clustering_annotation, const bool& verbose) { + t_pb_graph_node* pb_graph_node = pb->pb_graph_node; /* If we reach a primitive pb_graph node, we return */ if (true == is_primitive_pb_type(pb_graph_node->pb_type)) { if (LUT_CLASS == pb_graph_node->pb_type->class_type) { /* Do fix-up here. - * Note that LUTs have two modes, + * Note that LUTs have two modes, * For wire modes, we should skip the truth table adaption * mode 0 is reserved for wire, see read_xml_arch_file.cpp * mode 1 is the regular mode */ if (1 == pb->mode) { - fix_up_lut_atom_block_truth_table(atom_ctx, pb->child_pbs[0], pb_route, vpr_clustering_annotation, verbose); + fix_up_lut_atom_block_truth_table(atom_ctx, pb->child_pbs[0], pb_route, + vpr_clustering_annotation, verbose); } } return; @@ -161,8 +163,10 @@ void rec_adapt_lut_pb_tt(const AtomContext& atom_ctx, /* Each child may exist multiple times in the hierarchy*/ for (int jpb = 0; jpb < mapped_mode->pb_type_children[ipb].num_pb; ++jpb) { /* See if we still have any pb children to walk through */ - if ((pb->child_pbs[ipb] != nullptr) && (pb->child_pbs[ipb][jpb].name != nullptr)) { - rec_adapt_lut_pb_tt(atom_ctx, &(pb->child_pbs[ipb][jpb]), pb_route, vpr_clustering_annotation, verbose); + if ((pb->child_pbs[ipb] != nullptr) && + (pb->child_pbs[ipb][jpb].name != nullptr)) { + rec_adapt_lut_pb_tt(atom_ctx, &(pb->child_pbs[ipb][jpb]), pb_route, + vpr_clustering_annotation, verbose); } } } @@ -172,45 +176,42 @@ void rec_adapt_lut_pb_tt(const AtomContext& atom_ctx, * Main function to fix up truth table for each LUT used in FPGA * This function will walk through each clustered block *******************************************************************/ -static -void update_lut_tt_with_post_packing_results(const AtomContext& atom_ctx, - const ClusteringContext& clustering_ctx, - VprClusteringAnnotation& vpr_clustering_annotation, - const bool& verbose) { +static void update_lut_tt_with_post_packing_results( + const AtomContext& atom_ctx, const ClusteringContext& clustering_ctx, + VprClusteringAnnotation& vpr_clustering_annotation, const bool& verbose) { for (auto blk_id : clustering_ctx.clb_nlist.blocks()) { - rec_adapt_lut_pb_tt(atom_ctx, - clustering_ctx.clb_nlist.block_pb(blk_id), + rec_adapt_lut_pb_tt(atom_ctx, clustering_ctx.clb_nlist.block_pb(blk_id), clustering_ctx.clb_nlist.block_pb(blk_id)->pb_route, vpr_clustering_annotation, verbose); } } /******************************************************************** - * Top-level function to fix up the lut truth table results after packing is done - * The problem comes from a mismatch between the packing results and + * Top-level function to fix up the lut truth table results after packing is + *done The problem comes from a mismatch between the packing results and * original truth tables in users' BLIF file * As LUT inputs are equivalent in nature, the router of packer will try - * to swap the net mapping among these pins so as to achieve best + * to swap the net mapping among these pins so as to achieve best * routing optimization. - * However, it will cause the original truth table out-of-date when packing is done. - * This function aims to fix the mess after packing so that the truth table + * However, it will cause the original truth table out-of-date when packing is + *done. This function aims to fix the mess after packing so that the truth table * can be synchronized *******************************************************************/ -int lut_truth_table_fixup(OpenfpgaContext& openfpga_context, - const Command& cmd, const CommandContext& cmd_context) { - - vtr::ScopedStartFinishTimer timer("Fix up LUT truth tables after packing optimization"); +int lut_truth_table_fixup(OpenfpgaContext& openfpga_context, const Command& cmd, + const CommandContext& cmd_context) { + vtr::ScopedStartFinishTimer timer( + "Fix up LUT truth tables after packing optimization"); CommandOptionId opt_verbose = cmd.option("verbose"); /* Apply fix-up to each packed block */ - update_lut_tt_with_post_packing_results(g_vpr_ctx.atom(), - g_vpr_ctx.clustering(), - openfpga_context.mutable_vpr_clustering_annotation(), - cmd_context.option_enable(cmd, opt_verbose)); + update_lut_tt_with_post_packing_results( + g_vpr_ctx.atom(), g_vpr_ctx.clustering(), + openfpga_context.mutable_vpr_clustering_annotation(), + cmd_context.option_enable(cmd, opt_verbose)); /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; -} +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_lut_truth_table_fixup.h b/openfpga/src/base/openfpga_lut_truth_table_fixup.h index d685a4b44..3914fb3ca 100644 --- a/openfpga/src/base/openfpga_lut_truth_table_fixup.h +++ b/openfpga/src/base/openfpga_lut_truth_table_fixup.h @@ -15,8 +15,8 @@ /* begin namespace openfpga */ namespace openfpga { -int lut_truth_table_fixup(OpenfpgaContext& openfpga_context, - const Command& cmd, const CommandContext& cmd_context); +int lut_truth_table_fixup(OpenfpgaContext& openfpga_context, const Command& cmd, + const CommandContext& cmd_context); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index 403ce4907..38dabf0e8 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -1,18 +1,18 @@ /******************************************************************** - * This file includes functions to generate module/port names for - * Verilog and SPICE netlists + * This file includes functions to generate module/port names for + * Verilog and SPICE netlists * - * IMPORTANT: keep all the naming functions in this file to be - * generic for both Verilog and SPICE generators + * IMPORTANT: keep all the naming functions in this file to be + * generic for both Verilog and SPICE generators ********************************************************************/ -#include "vtr_assert.h" -#include "vtr_log.h" +#include "openfpga_naming.h" -#include "openfpga_side_manager.h" -#include "pb_type_utils.h" #include "circuit_library_utils.h" #include "openfpga_reserved_words.h" -#include "openfpga_naming.h" +#include "openfpga_side_manager.h" +#include "pb_type_utils.h" +#include "vtr_assert.h" +#include "vtr_log.h" /* begin namespace openfpga */ namespace openfpga { @@ -27,7 +27,8 @@ namespace openfpga { ***********************************************/ std::string generate_instance_name(const std::string& instance_name, const size_t& instance_id) { - return instance_name + std::string("_") + std::to_string(instance_id) + std::string("_"); + return instance_name + std::string("_") + std::to_string(instance_id) + + std::string("_"); } /************************************************ @@ -43,21 +44,20 @@ std::string generate_instance_wildcard_name(const std::string& instance_name, return instance_name + std::string("_") + wildcard_str + std::string("_"); } - /************************************************ - * Generate the node name for a multiplexing structure + * Generate the node name for a multiplexing structure * Case 1 : If there is an intermediate buffer followed by, * the node name will be mux_l_in_buf * Case 1 : If there is NO intermediate buffer followed by, * the node name will be mux_l_in ***********************************************/ -std::string generate_mux_node_name(const size_t& node_level, +std::string generate_mux_node_name(const size_t& node_level, const bool& add_buffer_postfix) { /* Generate the basic node_name */ std::string node_name = "mux_l" + std::to_string(node_level) + "_in"; /* Add a postfix upon requests */ - if (true == add_buffer_postfix) { + if (true == add_buffer_postfix) { /* '1' indicates that the location is needed */ node_name += "_buf"; } @@ -65,35 +65,36 @@ std::string generate_mux_node_name(const size_t& node_level, return node_name; } - /************************************************ - * Generate the instance name for a branch circuit in multiplexing structure +/************************************************ + * Generate the instance name for a branch circuit in multiplexing structure * Case 1 : If there is an intermediate buffer followed by, * the node name will be mux_l_in_buf * Case 1 : If there is NO intermediate buffer followed by, * the node name will be mux_l_in ***********************************************/ -std::string generate_mux_branch_instance_name(const size_t& node_level, +std::string generate_mux_branch_instance_name(const size_t& node_level, const size_t& node_index_at_level, const bool& add_buffer_postfix) { - return std::string(generate_mux_node_name(node_level, add_buffer_postfix) + "_" + std::to_string(node_index_at_level) + "_"); + return std::string(generate_mux_node_name(node_level, add_buffer_postfix) + + "_" + std::to_string(node_index_at_level) + "_"); } /************************************************ * Generate the module name for a multiplexer in Verilog format - * Different circuit model requires different names: + * Different circuit model requires different names: * 1. LUTs are named as _mux * 2. MUXes are named as _size ***********************************************/ -std::string generate_mux_subckt_name(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const size_t& mux_size, +std::string generate_mux_subckt_name(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const size_t& mux_size, const std::string& postfix) { - std::string module_name = circuit_lib.model_name(circuit_model); + std::string module_name = circuit_lib.model_name(circuit_model); /* Check the model type and give different names */ if (CIRCUIT_MODEL_MUX == circuit_lib.model_type(circuit_model)) { module_name += "_size"; module_name += std::to_string(mux_size); - } else { + } else { VTR_ASSERT(CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)); module_name += "_mux"; } @@ -110,34 +111,36 @@ std::string generate_mux_subckt_name(const CircuitLibrary& circuit_lib, * Generate the module name of a branch for a * multiplexer in Verilog format ***********************************************/ -std::string generate_mux_branch_subckt_name(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const size_t& branch_mux_size, - const size_t& branch_mem_size, +std::string generate_mux_branch_subckt_name(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const size_t& branch_mux_size, + const size_t& branch_mem_size, const std::string& postfix) { /* If the tgate circuit model of this MUX is a MUX2 standard cell, * the mux_subckt name will be the name of the standard cell */ - CircuitModelId subckt_model = circuit_lib.pass_gate_logic_model(circuit_model); + CircuitModelId subckt_model = + circuit_lib.pass_gate_logic_model(circuit_model); if (CIRCUIT_MODEL_GATE == circuit_lib.model_type(subckt_model)) { - VTR_ASSERT (CIRCUIT_MODEL_GATE_MUX2 == circuit_lib.gate_type(subckt_model)); + VTR_ASSERT(CIRCUIT_MODEL_GATE_MUX2 == circuit_lib.gate_type(subckt_model)); return circuit_lib.model_name(subckt_model); } /* Include memory size as a second unique signature for the branch module - * This is due to some branch modules have the same input sizes but different memory sizes + * This is due to some branch modules have the same input sizes but different + * memory sizes */ - std::string branch_postfix = postfix - + "_input" + std::to_string(branch_mux_size) - + "_mem" + std::to_string(branch_mem_size); + std::string branch_postfix = postfix + "_input" + + std::to_string(branch_mux_size) + "_mem" + + std::to_string(branch_mem_size); - std::string module_name = circuit_lib.model_name(circuit_model); + std::string module_name = circuit_lib.model_name(circuit_model); if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)) { module_name += "_mux"; - } else { + } else { VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(circuit_model)); } - module_name += branch_postfix; + module_name += branch_postfix; return module_name; } @@ -146,7 +149,7 @@ std::string generate_mux_branch_subckt_name(const CircuitLibrary& circuit_lib, * Generate the module name of a local decoder * for multiplexer ***********************************************/ -std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size, +std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size, const size_t& data_size) { std::string subckt_name = "local_encoder"; subckt_name += std::to_string(addr_size); @@ -154,13 +157,13 @@ std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size, subckt_name += std::to_string(data_size); return subckt_name; -} +} /************************************************ * Generate the module name of a decoder * for frame-based memories ***********************************************/ -std::string generate_memory_decoder_subckt_name(const size_t& addr_size, +std::string generate_memory_decoder_subckt_name(const size_t& addr_size, const size_t& data_size) { std::string subckt_name = "decoder"; subckt_name += std::to_string(addr_size); @@ -168,36 +171,37 @@ std::string generate_memory_decoder_subckt_name(const size_t& addr_size, subckt_name += std::to_string(data_size); return subckt_name; -} +} /************************************************ * Generate the module name of a word-line decoder * for memories ***********************************************/ -std::string generate_memory_decoder_with_data_in_subckt_name(const size_t& addr_size, - const size_t& data_size) { +std::string generate_memory_decoder_with_data_in_subckt_name( + const size_t& addr_size, const size_t& data_size) { std::string subckt_name = "decoder_with_data_in_"; subckt_name += std::to_string(addr_size); subckt_name += "to"; subckt_name += std::to_string(data_size); return subckt_name; -} +} /************************************************ * Generate the module name of a routing track wire ***********************************************/ -std::string generate_segment_wire_subckt_name(const std::string& wire_model_name, - const size_t& segment_id) { - std::string segment_wire_subckt_name = wire_model_name + "_seg" + std::to_string(segment_id); +std::string generate_segment_wire_subckt_name( + const std::string& wire_model_name, const size_t& segment_id) { + std::string segment_wire_subckt_name = + wire_model_name + "_seg" + std::to_string(segment_id); return segment_wire_subckt_name; -} +} /********************************************************************* * Generate the port name for the mid-output of a routing track wire * Mid-output is the output that is wired to a Connection block multiplexer. - * + * * | CLB | * +------------+ * ^ @@ -213,65 +217,69 @@ std::string generate_segment_wire_subckt_name(const std::string& wire_model_name * +-------------- * ********************************************************************/ -std::string generate_segment_wire_mid_output_name(const std::string& regular_output_name) { +std::string generate_segment_wire_mid_output_name( + const std::string& regular_output_name) { /* TODO: maybe have a postfix? */ return std::string("mid_" + regular_output_name); -} - -/********************************************************************* - * Generate the module name for a memory sub-circuit - ********************************************************************/ -std::string generate_memory_module_name(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const CircuitModelId& sram_model, - const std::string& postfix) { - return std::string( circuit_lib.model_name(circuit_model) + "_" + circuit_lib.model_name(sram_model) + postfix ); } /********************************************************************* - * Generate the netlist name for a unique routing block - * It could be + * Generate the module name for a memory sub-circuit + ********************************************************************/ +std::string generate_memory_module_name(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const CircuitModelId& sram_model, + const std::string& postfix) { + return std::string(circuit_lib.model_name(circuit_model) + "_" + + circuit_lib.model_name(sram_model) + postfix); +} + +/********************************************************************* + * Generate the netlist name for a unique routing block + * It could be * 1. Routing channel * 2. Connection block * 3. Switch block * A unique block id should be given *********************************************************************/ -std::string generate_routing_block_netlist_name(const std::string& prefix, +std::string generate_routing_block_netlist_name(const std::string& prefix, const size_t& block_id, const std::string& postfix) { - return std::string( prefix + std::to_string(block_id) + postfix ); + return std::string(prefix + std::to_string(block_id) + postfix); } /********************************************************************* * Generate the netlist name for a routing block with a given coordinate - * It could be + * It could be * 1. Routing channel * 2. Connection block * 3. Switch block *********************************************************************/ -std::string generate_routing_block_netlist_name(const std::string& prefix, - const vtr::Point& coordinate, - const std::string& postfix) { - return std::string( prefix + std::to_string(coordinate.x()) + std::string("__") + std::to_string(coordinate.y()) + std::string("_") + postfix ); +std::string generate_routing_block_netlist_name( + const std::string& prefix, const vtr::Point& coordinate, + const std::string& postfix) { + return std::string(prefix + std::to_string(coordinate.x()) + + std::string("__") + std::to_string(coordinate.y()) + + std::string("_") + postfix); } /********************************************************************* * Generate the netlist name for a connection block with a given coordinate *********************************************************************/ -std::string generate_connection_block_netlist_name(const t_rr_type& cb_type, - const vtr::Point& coordinate, - const std::string& postfix) { +std::string generate_connection_block_netlist_name( + const t_rr_type& cb_type, const vtr::Point& coordinate, + const std::string& postfix) { std::string prefix("cb"); switch (cb_type) { - case CHANX: - prefix += std::string("x_"); - break; - case CHANY: - prefix += std::string("y_"); - break; - default: - VTR_LOG_ERROR("Invalid type of connection block!\n"); - exit(1); + case CHANX: + prefix += std::string("x_"); + break; + case CHANY: + prefix += std::string("y_"); + break; + default: + VTR_LOG_ERROR("Invalid type of connection block!\n"); + exit(1); } return generate_routing_block_netlist_name(prefix, coordinate, postfix); @@ -280,10 +288,10 @@ std::string generate_connection_block_netlist_name(const t_rr_type& cb_type, /********************************************************************* * Generate the module name for a unique routing channel *********************************************************************/ -std::string generate_routing_channel_module_name(const t_rr_type& chan_type, +std::string generate_routing_channel_module_name(const t_rr_type& chan_type, const size_t& block_id) { /* Channel must be either CHANX or CHANY */ - VTR_ASSERT( (CHANX == chan_type) || (CHANY == chan_type) ); + VTR_ASSERT((CHANX == chan_type) || (CHANY == chan_type)); /* Create a map between chan_type and module_prefix */ std::map module_prefix_map; @@ -291,16 +299,17 @@ std::string generate_routing_channel_module_name(const t_rr_type& chan_type, module_prefix_map[CHANX] = std::string("chanx"); module_prefix_map[CHANY] = std::string("chany"); - return std::string( module_prefix_map[chan_type] + std::string("_") + std::to_string(block_id) + std::string("_") ); + return std::string(module_prefix_map[chan_type] + std::string("_") + + std::to_string(block_id) + std::string("_")); } /********************************************************************* * Generate the module name for a routing channel with a given coordinate *********************************************************************/ -std::string generate_routing_channel_module_name(const t_rr_type& chan_type, - const vtr::Point& coordinate) { +std::string generate_routing_channel_module_name( + const t_rr_type& chan_type, const vtr::Point& coordinate) { /* Channel must be either CHANX or CHANY */ - VTR_ASSERT( (CHANX == chan_type) || (CHANY == chan_type) ); + VTR_ASSERT((CHANX == chan_type) || (CHANY == chan_type)); /* Create a map between chan_type and module_prefix */ std::map module_prefix_map; @@ -308,21 +317,23 @@ std::string generate_routing_channel_module_name(const t_rr_type& chan_type, module_prefix_map[CHANX] = std::string("chanx"); module_prefix_map[CHANY] = std::string("chany"); - return std::string( module_prefix_map[chan_type] + std::to_string(coordinate.x()) + std::string("_") + std::to_string(coordinate.y()) + std::string("_") ); + return std::string(module_prefix_map[chan_type] + + std::to_string(coordinate.x()) + std::string("_") + + std::to_string(coordinate.y()) + std::string("_")); } /********************************************************************* * Generate the port name for a routing track with a given coordinate * and port direction - * This function is mainly used in naming routing tracks in the top-level netlists - * where we do need unique names (with coordinates) for each routing tracks + * This function is mainly used in naming routing tracks in the top-level + *netlists where we do need unique names (with coordinates) for each routing + *tracks *********************************************************************/ -std::string generate_routing_track_port_name(const t_rr_type& chan_type, - const vtr::Point& coordinate, - const size_t& track_id, - const PORTS& port_direction) { +std::string generate_routing_track_port_name( + const t_rr_type& chan_type, const vtr::Point& coordinate, + const size_t& track_id, const PORTS& port_direction) { /* Channel must be either CHANX or CHANY */ - VTR_ASSERT( (CHANX == chan_type) || (CHANY == chan_type) ); + VTR_ASSERT((CHANX == chan_type) || (CHANY == chan_type)); /* Create a map between chan_type and module_prefix */ std::map module_prefix_map; @@ -330,19 +341,21 @@ std::string generate_routing_track_port_name(const t_rr_type& chan_type, module_prefix_map[CHANX] = std::string("chanx"); module_prefix_map[CHANY] = std::string("chany"); - std::string port_name = module_prefix_map[chan_type]; - port_name += std::string("_" + std::to_string(coordinate.x()) + std::string("__") + std::to_string(coordinate.y()) + std::string("__")); + std::string port_name = module_prefix_map[chan_type]; + port_name += + std::string("_" + std::to_string(coordinate.x()) + std::string("__") + + std::to_string(coordinate.y()) + std::string("__")); switch (port_direction) { - case OUT_PORT: - port_name += std::string("out_"); - break; - case IN_PORT: - port_name += std::string("in_"); - break; - default: - VTR_LOG_ERROR("Invalid direction of chan_rr_node!\n"); - exit(1); + case OUT_PORT: + port_name += std::string("out_"); + break; + case IN_PORT: + port_name += std::string("in_"); + break; + default: + VTR_LOG_ERROR("Invalid direction of chan_rr_node!\n"); + exit(1); } /* Add the track id to the port name */ @@ -356,15 +369,15 @@ std::string generate_routing_track_port_name(const t_rr_type& chan_type, * This function is created to ease the PnR for each unique routing module * So it is mainly used when creating non-top-level modules! * Note that this function does not include any port coordinate - * Instead, we use the relative location of the pins in the context of routing modules - * so that each module can be instanciated across the fabric - * Even though, port direction must be provided! + * Instead, we use the relative location of the pins in the context of routing + *modules so that each module can be instanciated across the fabric Even though, + *port direction must be provided! *********************************************************************/ -std::string generate_sb_module_track_port_name(const t_rr_type& chan_type, +std::string generate_sb_module_track_port_name(const t_rr_type& chan_type, const e_side& module_side, const PORTS& port_direction) { /* Channel must be either CHANX or CHANY */ - VTR_ASSERT( (CHANX == chan_type) || (CHANY == chan_type) ); + VTR_ASSERT((CHANX == chan_type) || (CHANY == chan_type)); /* Create a map between chan_type and module_prefix */ std::map module_prefix_map; @@ -372,7 +385,7 @@ std::string generate_sb_module_track_port_name(const t_rr_type& chan_type, module_prefix_map[CHANX] = std::string("chanx"); module_prefix_map[CHANY] = std::string("chany"); - std::string port_name = module_prefix_map[chan_type]; + std::string port_name = module_prefix_map[chan_type]; port_name += std::string("_"); SideManager side_manager(module_side); @@ -380,15 +393,15 @@ std::string generate_sb_module_track_port_name(const t_rr_type& chan_type, port_name += std::string("_"); switch (port_direction) { - case OUT_PORT: - port_name += std::string("out"); - break; - case IN_PORT: - port_name += std::string("in"); - break; - default: - VTR_LOG_ERROR("Invalid direction of chan_rr_node!\n"); - exit(1); + case OUT_PORT: + port_name += std::string("out"); + break; + case IN_PORT: + port_name += std::string("in"); + break; + default: + VTR_LOG_ERROR("Invalid direction of chan_rr_node!\n"); + exit(1); } return port_name; @@ -399,25 +412,25 @@ std::string generate_sb_module_track_port_name(const t_rr_type& chan_type, * This function is created to ease the PnR for each unique routing module * So it is mainly used when creating non-top-level modules! * Note that this function does not include any port coordinate - * Instead, we use the relative location of the pins in the context of routing modules - * so that each module can be instanciated across the fabric - * Even though, port direction must be provided! + * Instead, we use the relative location of the pins in the context of routing + *modules so that each module can be instanciated across the fabric Even though, + *port direction must be provided! * * Upper_location: specify if an upper/lower prefix to be added. * The location indicates where the bus port should be * placed on the perimeter of the connection block - * - For X-directional CB: + * - For X-directional CB: * - upper is the left side * - lower is the right side - * - For Y-directional CB: + * - For Y-directional CB: * - upper is the bottom side * - lower is the top side *********************************************************************/ -std::string generate_cb_module_track_port_name(const t_rr_type& chan_type, +std::string generate_cb_module_track_port_name(const t_rr_type& chan_type, const PORTS& port_direction, const bool& upper_location) { /* Channel must be either CHANX or CHANY */ - VTR_ASSERT( (CHANX == chan_type) || (CHANY == chan_type) ); + VTR_ASSERT((CHANX == chan_type) || (CHANY == chan_type)); /* Create a map between chan_type and module_prefix */ std::map> module_prefix_map; @@ -431,29 +444,29 @@ std::string generate_cb_module_track_port_name(const t_rr_type& chan_type, port_name += std::string("_"); switch (port_direction) { - case OUT_PORT: - port_name += std::string("out"); - break; - case IN_PORT: - port_name += std::string("in"); - break; - default: - VTR_LOG_ERROR("Invalid direction of chan_rr_node!\n"); - exit(1); + case OUT_PORT: + port_name += std::string("out"); + break; + case IN_PORT: + port_name += std::string("in"); + break; + default: + VTR_LOG_ERROR("Invalid direction of chan_rr_node!\n"); + exit(1); } return port_name; } /********************************************************************* - * Generate the middle output port name for a routing track + * Generate the middle output port name for a routing track * with a given coordinate *********************************************************************/ -std::string generate_routing_track_middle_output_port_name(const t_rr_type& chan_type, - const vtr::Point& coordinate, - const size_t& track_id) { +std::string generate_routing_track_middle_output_port_name( + const t_rr_type& chan_type, const vtr::Point& coordinate, + const size_t& track_id) { /* Channel must be either CHANX or CHANY */ - VTR_ASSERT( (CHANX == chan_type) || (CHANY == chan_type) ); + VTR_ASSERT((CHANX == chan_type) || (CHANY == chan_type)); /* Create a map between chan_type and module_prefix */ std::map module_prefix_map; @@ -461,10 +474,12 @@ std::string generate_routing_track_middle_output_port_name(const t_rr_type& chan module_prefix_map[CHANX] = std::string("chanx"); module_prefix_map[CHANY] = std::string("chany"); - std::string port_name = module_prefix_map[chan_type]; - port_name += std::string("_" + std::to_string(coordinate.x()) + std::string("__") + std::to_string(coordinate.y()) + std::string("__")); + std::string port_name = module_prefix_map[chan_type]; + port_name += + std::string("_" + std::to_string(coordinate.x()) + std::string("__") + + std::to_string(coordinate.y()) + std::string("__")); - port_name += std::string("midout_"); + port_name += std::string("midout_"); /* Add the track id to the port name */ port_name += std::to_string(track_id) + std::string("_"); @@ -475,40 +490,44 @@ std::string generate_routing_track_middle_output_port_name(const t_rr_type& chan /********************************************************************* * Generate the module name for a switch block with a given coordinate *********************************************************************/ -std::string generate_switch_block_module_name(const vtr::Point& coordinate) { - return std::string( "sb_" + std::to_string(coordinate.x()) + std::string("__") + std::to_string(coordinate.y()) + std::string("_") ); +std::string generate_switch_block_module_name( + const vtr::Point& coordinate) { + return std::string("sb_" + std::to_string(coordinate.x()) + + std::string("__") + std::to_string(coordinate.y()) + + std::string("_")); } /********************************************************************* * Generate the module name for a connection block with a given coordinate *********************************************************************/ -std::string generate_connection_block_module_name(const t_rr_type& cb_type, - const vtr::Point& coordinate) { +std::string generate_connection_block_module_name( + const t_rr_type& cb_type, const vtr::Point& coordinate) { std::string prefix("cb"); switch (cb_type) { - case CHANX: - prefix += std::string("x_"); - break; - case CHANY: - prefix += std::string("y_"); - break; - default: - VTR_LOG_ERROR("Invalid type of connection block!\n"); - exit(1); + case CHANX: + prefix += std::string("x_"); + break; + case CHANY: + prefix += std::string("y_"); + break; + default: + VTR_LOG_ERROR("Invalid type of connection block!\n"); + exit(1); } - return std::string( prefix + std::to_string(coordinate.x()) + std::string("__") + std::to_string(coordinate.y()) + std::string("_") ); + return std::string(prefix + std::to_string(coordinate.x()) + + std::string("__") + std::to_string(coordinate.y()) + + std::string("_")); } /********************************************************************* - * Generate the port name for a grid in top-level netlists, i.e., full FPGA fabric - * This function will generate a full port name including coordinates - * so that each pin in top-level netlists is unique! + * Generate the port name for a grid in top-level netlists, i.e., full FPGA + *fabric This function will generate a full port name including coordinates so + *that each pin in top-level netlists is unique! *********************************************************************/ -std::string generate_grid_port_name(const size_t& width, - const size_t& height, - const int& subtile_index, - const e_side& side, +std::string generate_grid_port_name(const size_t& width, const size_t& height, + const int& subtile_index, + const e_side& side, const BasicPort& pin_info) { /* Ensure that the pin is 1-bit ONLY !!! */ VTR_ASSERT(1 == pin_info.get_width()); @@ -530,17 +549,14 @@ std::string generate_grid_port_name(const size_t& width, } /********************************************************************* - * Generate the port name for a grid with duplication + * Generate the port name for a grid with duplication * This function will generate two types of port names. * One with a postfix of "upper" * The other with a postfix of "lower" *********************************************************************/ -std::string generate_grid_duplicated_port_name(const size_t& width, - const size_t& height, - const int& subtile_index, - const e_side& side, - const BasicPort& pin_info, - const bool& upper_port) { +std::string generate_grid_duplicated_port_name( + const size_t& width, const size_t& height, const int& subtile_index, + const e_side& side, const BasicPort& pin_info, const bool& upper_port) { /* Ensure that the pin is 1-bit ONLY !!! */ VTR_ASSERT(1 == pin_info.get_width()); @@ -563,38 +579,42 @@ std::string generate_grid_duplicated_port_name(const size_t& width, } else { VTR_ASSERT_SAFE(false == upper_port); port_name += std::string("lower"); - } + } return port_name; } /********************************************************************* * Generate the port name for a grid in the context of a routing module - * To keep a short and simple name, this function will not + * To keep a short and simple name, this function will not * include any grid coorindate information! **********************************************************************/ -std::string generate_routing_module_grid_port_name(const size_t& width, - const size_t& height, - const int& subtile_index, - const e_side& side, +std::string generate_routing_module_grid_port_name(const size_t& width, + const size_t& height, + const int& subtile_index, + const e_side& side, const BasicPort& pin_info) { /* For non-top netlist */ std::string port_name = std::string("grid_"); - return port_name + generate_grid_port_name(width, height, subtile_index, side, pin_info); + return port_name + + generate_grid_port_name(width, height, subtile_index, side, pin_info); } /********************************************************************* * Generate the port name for a reserved sram port, i.e., BLB/WL port - * When port_type is BLB, a string denoting to the reserved BLB port is generated - * When port_type is WL, a string denoting to the reserved WL port is generated + * When port_type is BLB, a string denoting to the reserved BLB port is + *generated When port_type is WL, a string denoting to the reserved WL port is + *generated * * DO NOT put any SRAM organization check codes HERE!!! - * Even though the reserved BLB/WL ports are used by RRAM-based FPGA only, - * try to keep this function does simple job. - * Check codes should be added outside, when print the ports to files!!! + * Even though the reserved BLB/WL ports are used by RRAM-based FPGA only, + * try to keep this function does simple job. + * Check codes should be added outside, when print the ports to files!!! *********************************************************************/ -std::string generate_reserved_sram_port_name(const e_circuit_model_port_type& port_type) { - VTR_ASSERT( (port_type == CIRCUIT_MODEL_PORT_BLB) || (port_type == CIRCUIT_MODEL_PORT_WL) ); +std::string generate_reserved_sram_port_name( + const e_circuit_model_port_type& port_type) { + VTR_ASSERT((port_type == CIRCUIT_MODEL_PORT_BLB) || + (port_type == CIRCUIT_MODEL_PORT_WL)); if (CIRCUIT_MODEL_PORT_BLB == port_type) { return std::string("reserved_blb"); @@ -606,9 +626,10 @@ std::string generate_reserved_sram_port_name(const e_circuit_model_port_type& po * Generate the port name for a sram port, used for formal verification * The port name is named after the cell name of SRAM in circuit library *********************************************************************/ -std::string generate_formal_verification_sram_port_name(const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model) { - std::string port_name = circuit_lib.model_name(sram_model) + std::string("_out_fm"); +std::string generate_formal_verification_sram_port_name( + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model) { + std::string port_name = + circuit_lib.model_name(sram_model) + std::string("_out_fm"); return port_name; } @@ -682,68 +703,70 @@ std::string generate_local_config_bus_port_name() { * port list of a module * The port name is named after the cell name of SRAM in circuit library *********************************************************************/ -std::string generate_sram_port_name(const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& port_type) { +std::string generate_sram_port_name( + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& port_type) { std::string port_name; switch (sram_orgz_type) { - case CONFIG_MEM_SCAN_CHAIN: - /* Two types of ports are available: - * (1) Head of a chain of Configuration-chain Flip-Flops (CCFFs), enabled by port type of INPUT - * (2) Tail of a chian of Configuration-chain Flip-flops (CCFFs), enabled by port type of OUTPUT - * +------+ +------+ +------+ - * Head --->| CCFF |--->| CCFF |--->| CCFF |---> Tail - * +------+ +------+ +------+ - */ - if (CIRCUIT_MODEL_PORT_INPUT == port_type) { - port_name = std::string("ccff_head"); - } else { - VTR_ASSERT( CIRCUIT_MODEL_PORT_OUTPUT == port_type ); - port_name = std::string("ccff_tail"); - } - break; - case CONFIG_MEM_STANDALONE: - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: - /* Two types of ports are available: - * (1) Bit Lines (BLs) of a SRAM cell, enabled by port type of BL - * (2) Word Lines (WLs) of a SRAM cell, enabled by port type of WL - * - * BL WL BL WL BL WL - * [0] [0] [1] [1] [i] [i] - * ^ ^ ^ ^ ^ ^ - * | | | | | | - * +----------+ +----------+ +----------+ - * | SRAM | | SRAM | ... | SRAM | - * +----------+ +----------+ +----------+ - */ - if (CIRCUIT_MODEL_PORT_BL == port_type) { - port_name = std::string(MEMORY_BL_PORT_NAME); - } else if (CIRCUIT_MODEL_PORT_WL == port_type) { - port_name = std::string(MEMORY_WL_PORT_NAME); - } else { - VTR_ASSERT( CIRCUIT_MODEL_PORT_WLR == port_type ); - port_name = std::string(MEMORY_WLR_PORT_NAME); - } - break; - case CONFIG_MEM_FRAME_BASED: - /* Only one input port is required, which is the address port - * - * EN ADDR DATA_IN - * | | | - * v v v - * +---------------------------------+ - * | Frame decoder | - * +---------------------------------+ - * - */ - VTR_ASSERT(port_type == CIRCUIT_MODEL_PORT_INPUT); - port_name = std::string(DECODER_ADDRESS_PORT_NAME); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization !\n"); - exit(1); + case CONFIG_MEM_SCAN_CHAIN: + /* Two types of ports are available: + * (1) Head of a chain of Configuration-chain Flip-Flops (CCFFs), enabled + * by port type of INPUT (2) Tail of a chian of Configuration-chain + * Flip-flops (CCFFs), enabled by port type of OUTPUT + * +------+ +------+ +------+ + * Head --->| CCFF |--->| CCFF |--->| CCFF |---> Tail + * +------+ +------+ +------+ + */ + if (CIRCUIT_MODEL_PORT_INPUT == port_type) { + port_name = std::string("ccff_head"); + } else { + VTR_ASSERT(CIRCUIT_MODEL_PORT_OUTPUT == port_type); + port_name = std::string("ccff_tail"); + } + break; + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: + /* Two types of ports are available: + * (1) Bit Lines (BLs) of a SRAM cell, enabled by port type of BL + * (2) Word Lines (WLs) of a SRAM cell, enabled by port type of WL + * + * BL WL BL WL BL WL + * [0] [0] [1] [1] [i] [i] + * ^ ^ ^ ^ ^ ^ + * | | | | | | + * +----------+ +----------+ +----------+ + * | SRAM | | SRAM | ... | SRAM | + * +----------+ +----------+ +----------+ + */ + if (CIRCUIT_MODEL_PORT_BL == port_type) { + port_name = std::string(MEMORY_BL_PORT_NAME); + } else if (CIRCUIT_MODEL_PORT_WL == port_type) { + port_name = std::string(MEMORY_WL_PORT_NAME); + } else { + VTR_ASSERT(CIRCUIT_MODEL_PORT_WLR == port_type); + port_name = std::string(MEMORY_WLR_PORT_NAME); + } + break; + case CONFIG_MEM_FRAME_BASED: + /* Only one input port is required, which is the address port + * + * EN ADDR DATA_IN + * | | | + * v v v + * +---------------------------------+ + * | Frame decoder | + * +---------------------------------+ + * + */ + VTR_ASSERT(port_type == CIRCUIT_MODEL_PORT_INPUT); + port_name = std::string(DECODER_ADDRESS_PORT_NAME); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization !\n"); + exit(1); } return port_name; @@ -754,60 +777,62 @@ std::string generate_sram_port_name(const e_config_protocol_type& sram_orgz_type * wire of a module * The port name is named after the cell name of SRAM in circuit library *********************************************************************/ -std::string generate_sram_local_port_name(const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& port_type) { +std::string generate_sram_local_port_name( + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& port_type) { std::string port_name = circuit_lib.model_name(sram_model) + std::string("_"); switch (sram_orgz_type) { - case CONFIG_MEM_STANDALONE: { - /* Two types of ports are available: - * (1) Regular output of a SRAM, enabled by port type of INPUT - * (2) Inverted output of a SRAM, enabled by port type of OUTPUT - */ - if (CIRCUIT_MODEL_PORT_INPUT == port_type) { - port_name += std::string("out_local_bus"); - } else { - VTR_ASSERT( CIRCUIT_MODEL_PORT_OUTPUT == port_type ); - port_name += std::string("outb_local_bus"); + case CONFIG_MEM_STANDALONE: { + /* Two types of ports are available: + * (1) Regular output of a SRAM, enabled by port type of INPUT + * (2) Inverted output of a SRAM, enabled by port type of OUTPUT + */ + if (CIRCUIT_MODEL_PORT_INPUT == port_type) { + port_name += std::string("out_local_bus"); + } else { + VTR_ASSERT(CIRCUIT_MODEL_PORT_OUTPUT == port_type); + port_name += std::string("outb_local_bus"); + } + break; } - break; - } - case CONFIG_MEM_SCAN_CHAIN: - /* Three types of ports are available: - * (1) Input of Configuration-chain Flip-Flops (CCFFs), enabled by port type of INPUT - * (2) Output of a chian of Configuration-chain Flip-flops (CCFFs), enabled by port type of OUTPUT - * (2) Inverted output of a chian of Configuration-chain Flip-flops (CCFFs), enabled by port type of INOUT - * +------+ +------+ +------+ - * Head --->| CCFF |--->| CCFF |--->| CCFF |---> Tail - * +------+ +------+ +------+ - */ - if (CIRCUIT_MODEL_PORT_INPUT == port_type) { - port_name += std::string("ccff_in_local_bus"); - } else if ( CIRCUIT_MODEL_PORT_OUTPUT == port_type ) { - port_name += std::string("ccff_out_local_bus"); - } else { - VTR_ASSERT( CIRCUIT_MODEL_PORT_INOUT == port_type ); - port_name += std::string("ccff_outb_local_bus"); + case CONFIG_MEM_SCAN_CHAIN: + /* Three types of ports are available: + * (1) Input of Configuration-chain Flip-Flops (CCFFs), enabled by port + * type of INPUT (2) Output of a chian of Configuration-chain Flip-flops + * (CCFFs), enabled by port type of OUTPUT (2) Inverted output of a chian + * of Configuration-chain Flip-flops (CCFFs), enabled by port type of + * INOUT + * +------+ +------+ +------+ + * Head --->| CCFF |--->| CCFF |--->| CCFF |---> Tail + * +------+ +------+ +------+ + */ + if (CIRCUIT_MODEL_PORT_INPUT == port_type) { + port_name += std::string("ccff_in_local_bus"); + } else if (CIRCUIT_MODEL_PORT_OUTPUT == port_type) { + port_name += std::string("ccff_out_local_bus"); + } else { + VTR_ASSERT(CIRCUIT_MODEL_PORT_INOUT == port_type); + port_name += std::string("ccff_outb_local_bus"); + } + break; + case CONFIG_MEM_MEMORY_BANK: { + /* Two types of ports are available: + * (1) Regular output of a SRAM, enabled by port type of INPUT + * (2) Inverted output of a SRAM, enabled by port type of OUTPUT + */ + if (CIRCUIT_MODEL_PORT_INPUT == port_type) { + port_name += std::string("out_local_bus"); + } else { + VTR_ASSERT(CIRCUIT_MODEL_PORT_OUTPUT == port_type); + port_name += std::string("outb_local_bus"); + } + break; } - break; - case CONFIG_MEM_MEMORY_BANK: { - /* Two types of ports are available: - * (1) Regular output of a SRAM, enabled by port type of INPUT - * (2) Inverted output of a SRAM, enabled by port type of OUTPUT - */ - if (CIRCUIT_MODEL_PORT_INPUT == port_type) { - port_name += std::string("out_local_bus"); - } else { - VTR_ASSERT( CIRCUIT_MODEL_PORT_OUTPUT == port_type ); - port_name += std::string("outb_local_bus"); - } - break; - } - default: - VTR_LOG_ERROR("Invalid type of SRAM organization !\n"); - exit(1); + default: + VTR_LOG_ERROR("Invalid type of SRAM organization !\n"); + exit(1); } return port_name; @@ -817,34 +842,36 @@ std::string generate_sram_local_port_name(const CircuitLibrary& circuit_lib, * Generate the BL/WL port names for the top-level module of an FPGA fabric * Each BL/WL bus drive a specific configuration region has an unique name *********************************************************************/ -std::string generate_regional_blwl_port_name(const std::string& blwl_port_prefix, - const ConfigRegionId& region_id) { - return blwl_port_prefix + std::string("_config_region_") + std::to_string(size_t(region_id)); +std::string generate_regional_blwl_port_name( + const std::string& blwl_port_prefix, const ConfigRegionId& region_id) { + return blwl_port_prefix + std::string("_config_region_") + + std::to_string(size_t(region_id)); } /********************************************************************* * Generate the module name for a shift register chain which configures BLs *********************************************************************/ -std::string generate_bl_shift_register_module_name(const std::string& memory_model_name, - const size_t& shift_register_size) { - return std::string("bl_shift_register_") + memory_model_name + std::string("_size") + std::to_string(shift_register_size); +std::string generate_bl_shift_register_module_name( + const std::string& memory_model_name, const size_t& shift_register_size) { + return std::string("bl_shift_register_") + memory_model_name + + std::string("_size") + std::to_string(shift_register_size); } /********************************************************************* * Generate the module name for a shift register chain which configures WLs *********************************************************************/ -std::string generate_wl_shift_register_module_name(const std::string& memory_model_name, - const size_t& shift_register_size) { - return std::string("wl_shift_register_") + memory_model_name + std::string("_size") + std::to_string(shift_register_size); +std::string generate_wl_shift_register_module_name( + const std::string& memory_model_name, const size_t& shift_register_size) { + return std::string("wl_shift_register_") + memory_model_name + + std::string("_size") + std::to_string(shift_register_size); } - /********************************************************************* * Generate the port name for the input bus of a routing multiplexer - * This is very useful in Verilog code generation where the inputs of - * a routing multiplexer may come from different ports. + * This is very useful in Verilog code generation where the inputs of + * a routing multiplexer may come from different ports. * On the other side, the datapath input of a routing multiplexer - * is defined as a bus port. + * is defined as a bus port. * Therefore, to interface, a bus port is required, and this function * give a name to the bus port * To keep the bus port name unique to each multiplexer we will instance, @@ -852,26 +879,27 @@ std::string generate_wl_shift_register_module_name(const std::string& memory_mod *********************************************************************/ std::string generate_mux_input_bus_port_name(const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, - const size_t& mux_size, + const size_t& mux_size, const size_t& mux_instance_id) { - std::string postfix = std::string("_") + std::to_string(mux_instance_id) + std::string("_inbus"); + std::string postfix = + std::string("_") + std::to_string(mux_instance_id) + std::string("_inbus"); return generate_mux_subckt_name(circuit_lib, mux_model, mux_size, postfix); } /********************************************************************* * Generate the name of a bus port which is wired to the configuration * ports of a routing multiplexer - * This port is supposed to be used locally inside a Verilog/SPICE module + * This port is supposed to be used locally inside a Verilog/SPICE module *********************************************************************/ std::string generate_mux_config_bus_port_name(const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, - const size_t& mux_size, + const size_t& mux_size, const size_t& bus_id, const bool& inverted) { std::string postfix = std::string("_configbus") + std::to_string(bus_id); /* Add a bar to the end of the name for inverted bus ports */ if (true == inverted) { - postfix += std::string("_b"); + postfix += std::string("_b"); } return generate_mux_subckt_name(circuit_lib, mux_model, mux_size, postfix); @@ -884,16 +912,17 @@ std::string generate_mux_config_bus_port_name(const CircuitLibrary& circuit_lib, * Note that the SRAM ports share the same naming * convention regardless of their configuration style *********************************************************************/ -std::string generate_local_sram_port_name(const std::string& port_prefix, - const size_t& instance_id, - const e_circuit_model_port_type& port_type) { - std::string port_name = port_prefix + std::string("_") + std::to_string(instance_id) + std::string("_"); +std::string generate_local_sram_port_name( + const std::string& port_prefix, const size_t& instance_id, + const e_circuit_model_port_type& port_type) { + std::string port_name = port_prefix + std::string("_") + + std::to_string(instance_id) + std::string("_"); if (CIRCUIT_MODEL_PORT_INPUT == port_type) { - port_name += std::string("out"); + port_name += std::string("out"); } else { - VTR_ASSERT( CIRCUIT_MODEL_PORT_OUTPUT == port_type ); - port_name += std::string("outb"); + VTR_ASSERT(CIRCUIT_MODEL_PORT_OUTPUT == port_type); + port_name += std::string("outb"); } return port_name; @@ -906,23 +935,24 @@ std::string generate_local_sram_port_name(const std::string& port_prefix, * Note that the SRAM ports of routing multiplexers share the same naming * convention regardless of their configuration style **********************************************************************/ -std::string generate_mux_sram_port_name(const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const size_t& mux_size, - const size_t& mux_instance_id, - const e_circuit_model_port_type& port_type) { - std::string prefix = generate_mux_subckt_name(circuit_lib, mux_model, mux_size, std::string()); +std::string generate_mux_sram_port_name( + const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, + const size_t& mux_size, const size_t& mux_instance_id, + const e_circuit_model_port_type& port_type) { + std::string prefix = + generate_mux_subckt_name(circuit_lib, mux_model, mux_size, std::string()); return generate_local_sram_port_name(prefix, mux_instance_id, port_type); } /********************************************************************* * Generate the netlist name of a logical tile **********************************************************************/ -std::string generate_logical_tile_netlist_name(const std::string& prefix, - const t_pb_graph_node* pb_graph_head, - const std::string& postfix) { +std::string generate_logical_tile_netlist_name( + const std::string& prefix, const t_pb_graph_node* pb_graph_head, + const std::string& postfix) { /* Add the name of physical block */ - std::string module_name = prefix + generate_physical_block_module_name(pb_graph_head->pb_type); + std::string module_name = + prefix + generate_physical_block_module_name(pb_graph_head->pb_type); module_name += postfix; @@ -931,7 +961,7 @@ std::string generate_logical_tile_netlist_name(const std::string& prefix, /********************************************************************* * Generate the prefix for naming a grid block netlist or a grid module - * This function will consider the io side and add it to the prefix + * This function will consider the io side and add it to the prefix **********************************************************************/ std::string generate_grid_block_prefix(const std::string& prefix, const e_side& io_side) { @@ -942,7 +972,7 @@ std::string generate_grid_block_prefix(const std::string& prefix, block_prefix += std::string(side_manager.to_string()); block_prefix += std::string("_"); } - + return block_prefix; } @@ -976,21 +1006,22 @@ std::string generate_grid_block_module_name(const std::string& prefix, const e_side& io_side) { std::string module_name(prefix); - module_name += generate_grid_block_netlist_name(block_name, is_block_io, io_side, std::string()); + module_name += generate_grid_block_netlist_name(block_name, is_block_io, + io_side, std::string()); return module_name; } /********************************************************************* - * Generate the instance name for a programmable routing multiplexer module + * Generate the instance name for a programmable routing multiplexer module * in a Switch Block - * To keep a unique name in each module and also consider unique routing modules, - * please do NOT include any coordinates in the naming!!! - * Consider only relative coordinate, such as side! + * To keep a unique name in each module and also consider unique routing + *modules, please do NOT include any coordinates in the naming!!! Consider only + *relative coordinate, such as side! ********************************************************************/ std::string generate_sb_mux_instance_name(const std::string& prefix, - const e_side& sb_side, - const size_t& track_id, + const e_side& sb_side, + const size_t& track_id, const std::string& postfix) { std::string instance_name(prefix); instance_name += SideManager(sb_side).to_string(); @@ -1002,13 +1033,13 @@ std::string generate_sb_mux_instance_name(const std::string& prefix, /********************************************************************* * Generate the instance name for a configurable memory module in a Switch Block - * To keep a unique name in each module and also consider unique routing modules, - * please do NOT include any coordinates in the naming!!! - * Consider only relative coordinate, such as side! + * To keep a unique name in each module and also consider unique routing + *modules, please do NOT include any coordinates in the naming!!! Consider only + *relative coordinate, such as side! ********************************************************************/ std::string generate_sb_memory_instance_name(const std::string& prefix, - const e_side& sb_side, - const size_t& track_id, + const e_side& sb_side, + const size_t& track_id, const std::string& postfix) { std::string instance_name(prefix); instance_name += SideManager(sb_side).to_string(); @@ -1019,15 +1050,15 @@ std::string generate_sb_memory_instance_name(const std::string& prefix, } /********************************************************************* - * Generate the instance name for a programmable routing multiplexer module + * Generate the instance name for a programmable routing multiplexer module * in a Connection Block - * To keep a unique name in each module and also consider unique routing modules, - * please do NOT include any coordinates in the naming!!! - * Consider only relative coordinate, such as side! + * To keep a unique name in each module and also consider unique routing + *modules, please do NOT include any coordinates in the naming!!! Consider only + *relative coordinate, such as side! ********************************************************************/ std::string generate_cb_mux_instance_name(const std::string& prefix, - const e_side& cb_side, - const size_t& pin_id, + const e_side& cb_side, + const size_t& pin_id, const std::string& postfix) { std::string instance_name(prefix); @@ -1039,14 +1070,14 @@ std::string generate_cb_mux_instance_name(const std::string& prefix, } /********************************************************************* - * Generate the instance name for a configurable memory module in a Connection Block - * To keep a unique name in each module and also consider unique routing modules, - * please do NOT include any coordinates in the naming!!! - * Consider only relative coordinate, such as side! + * Generate the instance name for a configurable memory module in a Connection + *Block To keep a unique name in each module and also consider unique routing + *modules, please do NOT include any coordinates in the naming!!! Consider only + *relative coordinate, such as side! ********************************************************************/ std::string generate_cb_memory_instance_name(const std::string& prefix, - const e_side& cb_side, - const size_t& pin_id, + const e_side& cb_side, + const size_t& pin_id, const std::string& postfix) { std::string instance_name(prefix); @@ -1064,13 +1095,13 @@ std::string generate_cb_memory_instance_name(const std::string& prefix, * the instance name includes the index of parent node * as well as the port name and pin index of this pin * - * Exceptions: - * For OUTPUT ports, due to hierarchical module organization, + * Exceptions: + * For OUTPUT ports, due to hierarchical module organization, * their parent nodes will be uniquified * So, we should not add any index here ********************************************************************/ std::string generate_pb_mux_instance_name(const std::string& prefix, - t_pb_graph_pin* pb_graph_pin, + t_pb_graph_pin* pb_graph_pin, const std::string& postfix) { std::string instance_name(prefix); instance_name += std::string(pb_graph_pin->parent_node->pb_type->name); @@ -1090,19 +1121,19 @@ std::string generate_pb_mux_instance_name(const std::string& prefix, } /********************************************************************* - * Generate the instance name for a configurable memory module in a + * Generate the instance name for a configurable memory module in a * physical block of a grid * To guarentee a unique name for pb_graph pin, * the instance name includes the index of parent node * as well as the port name and pin index of this pin * - * Exceptions: - * For OUTPUT ports, due to hierarchical module organization, + * Exceptions: + * For OUTPUT ports, due to hierarchical module organization, * their parent nodes will be uniquified * So, we should not add any index here ********************************************************************/ std::string generate_pb_memory_instance_name(const std::string& prefix, - t_pb_graph_pin* pb_graph_pin, + t_pb_graph_pin* pb_graph_pin, const std::string& postfix) { std::string instance_name(prefix); instance_name += std::string(pb_graph_pin->parent_node->pb_type->name); @@ -1124,14 +1155,14 @@ std::string generate_pb_memory_instance_name(const std::string& prefix, /********************************************************************* * Generate the instance name of a grid block **********************************************************************/ -std::string generate_grid_block_instance_name(const std::string& prefix, - const std::string& block_name, - const bool& is_block_io, - const e_side& io_side, - const vtr::Point& grid_coord) { +std::string generate_grid_block_instance_name( + const std::string& prefix, const std::string& block_name, + const bool& is_block_io, const e_side& io_side, + const vtr::Point& grid_coord) { std::string module_name(prefix); - module_name += generate_grid_block_netlist_name(block_name, is_block_io, io_side, std::string()); + module_name += generate_grid_block_netlist_name(block_name, is_block_io, + io_side, std::string()); module_name += std::string("_"); module_name += std::to_string(grid_coord.x()); module_name += std::string("__"); @@ -1145,14 +1176,15 @@ std::string generate_grid_block_instance_name(const std::string& prefix, * Generate the module name of a logical block type (pb_type) * Since the logical block does not carry any physical attributes, * this logical block will have a common prefix 'logical_type' - * To ensure a unique name for each physical block inside the graph of complex blocks - * (pb_graph_nodes), this function trace backward to the top-level node - * in the graph and add the name of these parents - * The final name will be in the following format: - * __ ... + * To ensure a unique name for each physical block inside the graph of complex + *blocks (pb_graph_nodes), this function trace backward to the top-level node in + *the graph and add the name of these parents The final name will be in the + *following format: + * __ ... + * * * TODO: to make sure the length of this name does not exceed the size of - * chars in a line of a file!!! + * chars in a line of a file!!! **********************************************************************/ std::string generate_physical_block_module_name(t_pb_type* physical_pb_type) { std::string module_name(physical_pb_type->name); @@ -1161,33 +1193,39 @@ std::string generate_physical_block_module_name(t_pb_type* physical_pb_type) { /* Backward trace until we meet the top-level pb_type */ while (1) { - /* If there is no parent mode, this is a top-level pb_type, quit the loop here */ + /* If there is no parent mode, this is a top-level pb_type, quit the loop + * here */ t_mode* parent_mode = parent_pb_type->parent_mode; if (NULL == parent_mode) { break; } - + /* Add the mode name to the module name */ - module_name = std::string("mode_") + std::string(parent_mode->name) + std::string("__") + module_name; + module_name = std::string("mode_") + std::string(parent_mode->name) + + std::string("__") + module_name; /* Backtrace to the upper level */ parent_pb_type = parent_mode->parent_pb_type; - /* If there is no parent pb_type, this is a top-level pb_type, quit the loop here */ + /* If there is no parent pb_type, this is a top-level pb_type, quit the loop + * here */ if (NULL == parent_pb_type) { break; } /* Add the current pb_type name to the module name */ - module_name = std::string(parent_pb_type->name) + std::string("_") + module_name; + module_name = + std::string(parent_pb_type->name) + std::string("_") + module_name; } - /* Exception for top-level pb_type: add an virtual mode name (same name as the pb_type) - * This is to follow the naming convention as non top-level pb_types - * In addition, the name can be really unique, being different than the grid blocks + /* Exception for top-level pb_type: add an virtual mode name (same name as the + * pb_type) This is to follow the naming convention as non top-level pb_types + * In addition, the name can be really unique, being different than the grid + * blocks */ if (NULL == physical_pb_type->parent_mode) { - module_name += std::string("_mode_") + std::string(physical_pb_type->name) + std::string("_"); + module_name += std::string("_mode_") + std::string(physical_pb_type->name) + + std::string("_"); } /* Add the prefix */ @@ -1197,7 +1235,7 @@ std::string generate_physical_block_module_name(t_pb_type* physical_pb_type) { } /********************************************************************* - * Generate the instance name for physical block with a given index + * Generate the instance name for physical block with a given index **********************************************************************/ std::string generate_physical_block_instance_name(t_pb_type* pb_type, const size_t& index) { @@ -1210,10 +1248,10 @@ std::string generate_physical_block_instance_name(t_pb_type* pb_type, } /******************************************************************** - * This function try to infer if a grid locates at the border of a + * This function try to infer if a grid locates at the border of a * FPGA fabric, i.e., TOP/RIGHT/BOTTOM/LEFT sides * 1. if this grid is on the border, it will return the side it locates, - * 2. if this grid is in the center, it will return an valid value NUM_SIDES + * 2. if this grid is in the center, it will return an valid value NUM_SIDES * * In this function, we assume that the corner grids are actually empty! * @@ -1262,7 +1300,7 @@ e_side find_grid_border_side(const vtr::Point& device_size, * This function try to infer if a grid locates at the border of the * core FPGA fabric, i.e., TOP/RIGHT/BOTTOM/LEFT sides * 1. if this grid is on the border and it matches the given side, return true, - * 2. if this grid is in the center, return false + * 2. if this grid is in the center, return false * * In this function, we assume that the corner grids are actually empty! * @@ -1290,50 +1328,45 @@ e_side find_grid_border_side(const vtr::Point& device_size, * Note: for the blocks on the four corners of the core grids * Please refer to the figure above to infer its border_side *******************************************************************/ -bool is_core_grid_on_given_border_side(const vtr::Point& device_size, - const vtr::Point& grid_coordinate, - const e_side& border_side) { - - if ( (device_size.y() - 2 == grid_coordinate.y()) - && (TOP == border_side) ) { +bool is_core_grid_on_given_border_side( + const vtr::Point& device_size, + const vtr::Point& grid_coordinate, const e_side& border_side) { + if ((device_size.y() - 2 == grid_coordinate.y()) && (TOP == border_side)) { return true; } - if ( (device_size.x() - 2 == grid_coordinate.x()) - && (RIGHT == border_side) ) { + if ((device_size.x() - 2 == grid_coordinate.x()) && (RIGHT == border_side)) { return true; } - if ( (1 == grid_coordinate.y()) - && (BOTTOM == border_side) ) { + if ((1 == grid_coordinate.y()) && (BOTTOM == border_side)) { return true; } - if ( (1 == grid_coordinate.x()) - && (LEFT == border_side) ) { + if ((1 == grid_coordinate.x()) && (LEFT == border_side)) { return true; } return false; } - /********************************************************************* * Generate the port name of a Verilog module describing a pb_type - * The name convention is + * The name convention is * _ ********************************************************************/ std::string generate_pb_type_port_name(t_pb_type* pb_type, t_port* pb_type_port) { std::string port_name; - - port_name = std::string(pb_type->name) + std::string("_") + std::string(pb_type_port->name); - + + port_name = std::string(pb_type->name) + std::string("_") + + std::string(pb_type_port->name); + return port_name; } /********************************************************************* * Generate the port name of a Verilog module describing a pb_type - * The name convention is + * The name convention is * _ - * + * * This is a wrapper on the generate_pb_type_port_name() function * which can infer the parent_pb_type ********************************************************************/ @@ -1341,26 +1374,24 @@ std::string generate_pb_type_port_name(t_port* pb_type_port) { return generate_pb_type_port_name(pb_type_port->parent_pb_type, pb_type_port); } - /********************************************************************* * Generate the global I/O port name of a Verilog module * This is mainly used by I/O circuit models ********************************************************************/ -std::string generate_fpga_global_io_port_name(const std::string& prefix, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const CircuitPortId& circuit_port) { +std::string generate_fpga_global_io_port_name( + const std::string& prefix, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, const CircuitPortId& circuit_port) { std::string port_name(prefix); - + port_name += circuit_lib.model_name(circuit_model); port_name += std::string("_"); port_name += circuit_lib.port_prefix(circuit_port); - + return port_name; } /********************************************************************* - * Generate the module name for the top-level module + * Generate the module name for the top-level module * The top-level module is actually the FPGA fabric * We give a fixed name here, because it is independent from benchmark file ********************************************************************/ @@ -1369,7 +1400,7 @@ std::string generate_fpga_top_module_name() { } /********************************************************************* - * Generate the netlist name for the top-level module + * Generate the netlist name for the top-level module * The top-level module is actually the FPGA fabric * We give a fixed name here, because it is independent from benchmark file ********************************************************************/ @@ -1386,7 +1417,7 @@ std::string generate_const_value_module_name(const size_t& const_val) { return std::string("const0"); } - VTR_ASSERT (1 == const_val); + VTR_ASSERT(1 == const_val); return std::string("const1"); } @@ -1394,7 +1425,8 @@ std::string generate_const_value_module_name(const size_t& const_val) { * Generate the output port name for a constant generator module * either VDD or GND, depending on the input argument ********************************************************************/ -std::string generate_const_value_module_output_port_name(const size_t& const_val) { +std::string generate_const_value_module_output_port_name( + const size_t& const_val) { return generate_const_value_module_name(const_val); } @@ -1403,8 +1435,8 @@ std::string generate_const_value_module_output_port_name(const size_t& const_val * The format is * _ ********************************************************************/ -std::string generate_analysis_sdc_file_name(const std::string& circuit_name, - const std::string& file_name_postfix) { +std::string generate_analysis_sdc_file_name( + const std::string& circuit_name, const std::string& file_name_postfix) { return circuit_name + "_" + file_name_postfix; } diff --git a/openfpga/src/base/openfpga_naming.h b/openfpga/src/base/openfpga_naming.h index e62358fcc..8e6fb631a 100644 --- a/openfpga/src/base/openfpga_naming.h +++ b/openfpga/src/base/openfpga_naming.h @@ -1,7 +1,7 @@ /************************************************ * Header file for fpga_x2p_naming.cpp * Include functions to generate module/port names - * for Verilog and SPICE netlists + * for Verilog and SPICE netlists ***********************************************/ #ifndef OPENFPGA_NAMING_H @@ -12,12 +12,12 @@ *******************************************************************/ #include -#include "vtr_geometry.h" #include "circuit_library.h" #include "device_grid.h" -#include "openfpga_port.h" #include "module_manager_fwd.h" +#include "openfpga_port.h" #include "rr_node_types.h" +#include "vtr_geometry.h" /******************************************************************** * Function declaration @@ -32,134 +32,132 @@ std::string generate_instance_name(const std::string& instance_name, std::string generate_instance_wildcard_name(const std::string& instance_name, const std::string& wildcard_str); -std::string generate_mux_node_name(const size_t& node_level, +std::string generate_mux_node_name(const size_t& node_level, const bool& add_buffer_postfix); -std::string generate_mux_branch_instance_name(const size_t& node_level, +std::string generate_mux_branch_instance_name(const size_t& node_level, const size_t& node_index_at_level, const bool& add_buffer_postfix); -std::string generate_mux_subckt_name(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const size_t& mux_size, - const std::string& posfix) ; +std::string generate_mux_subckt_name(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const size_t& mux_size, + const std::string& posfix); -std::string generate_mux_branch_subckt_name(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const size_t& branch_mux_size, - const size_t& branch_mem_size, +std::string generate_mux_branch_subckt_name(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const size_t& branch_mux_size, + const size_t& branch_mem_size, const std::string& posfix); -std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size, - const size_t& data_size); +std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size, + const size_t& data_size); -std::string generate_memory_decoder_subckt_name(const size_t& addr_size, +std::string generate_memory_decoder_subckt_name(const size_t& addr_size, const size_t& data_size); -std::string generate_memory_decoder_with_data_in_subckt_name(const size_t& addr_size, - const size_t& data_size); +std::string generate_memory_decoder_with_data_in_subckt_name( + const size_t& addr_size, const size_t& data_size); -std::string generate_segment_wire_subckt_name(const std::string& wire_model_name, - const size_t& segment_id); +std::string generate_segment_wire_subckt_name( + const std::string& wire_model_name, const size_t& segment_id); -std::string generate_segment_wire_mid_output_name(const std::string& regular_output_name); +std::string generate_segment_wire_mid_output_name( + const std::string& regular_output_name); std::string generate_memory_module_name(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const CircuitModelId& sram_model, + const CircuitModelId& circuit_model, + const CircuitModelId& sram_model, const std::string& postfix); -std::string generate_routing_block_netlist_name(const std::string& prefix, +std::string generate_routing_block_netlist_name(const std::string& prefix, const size_t& block_id, const std::string& postfix); -std::string generate_routing_block_netlist_name(const std::string& prefix, - const vtr::Point& block_id, - const std::string& postfix); +std::string generate_routing_block_netlist_name( + const std::string& prefix, const vtr::Point& block_id, + const std::string& postfix); -std::string generate_connection_block_netlist_name(const t_rr_type& cb_type, - const vtr::Point& coordinate, - const std::string& postfix); +std::string generate_connection_block_netlist_name( + const t_rr_type& cb_type, const vtr::Point& coordinate, + const std::string& postfix); -std::string generate_routing_channel_module_name(const t_rr_type& chan_type, +std::string generate_routing_channel_module_name(const t_rr_type& chan_type, const size_t& block_id); -std::string generate_routing_channel_module_name(const t_rr_type& chan_type, - const vtr::Point& coordinate); +std::string generate_routing_channel_module_name( + const t_rr_type& chan_type, const vtr::Point& coordinate); -std::string generate_routing_track_port_name(const t_rr_type& chan_type, - const vtr::Point& coordinate, - const size_t& track_id, - const PORTS& port_direction); +std::string generate_routing_track_port_name( + const t_rr_type& chan_type, const vtr::Point& coordinate, + const size_t& track_id, const PORTS& port_direction); -std::string generate_sb_module_track_port_name(const t_rr_type& chan_type, +std::string generate_sb_module_track_port_name(const t_rr_type& chan_type, const e_side& module_side, const PORTS& port_direction); -std::string generate_cb_module_track_port_name(const t_rr_type& chan_type, +std::string generate_cb_module_track_port_name(const t_rr_type& chan_type, const PORTS& port_direction, const bool& upper_location); -std::string generate_routing_track_middle_output_port_name(const t_rr_type& chan_type, - const vtr::Point& coordinate, - const size_t& track_id); +std::string generate_routing_track_middle_output_port_name( + const t_rr_type& chan_type, const vtr::Point& coordinate, + const size_t& track_id); -std::string generate_switch_block_module_name(const vtr::Point& coordinate); +std::string generate_switch_block_module_name( + const vtr::Point& coordinate); -std::string generate_connection_block_module_name(const t_rr_type& cb_type, - const vtr::Point& coordinate); +std::string generate_connection_block_module_name( + const t_rr_type& cb_type, const vtr::Point& coordinate); std::string generate_sb_mux_instance_name(const std::string& prefix, - const e_side& sb_side, - const size_t& track_id, + const e_side& sb_side, + const size_t& track_id, const std::string& postfix); std::string generate_sb_memory_instance_name(const std::string& prefix, - const e_side& sb_side, - const size_t& track_id, + const e_side& sb_side, + const size_t& track_id, const std::string& postfix); std::string generate_cb_mux_instance_name(const std::string& prefix, - const e_side& cb_side, - const size_t& pin_id, + const e_side& cb_side, + const size_t& pin_id, const std::string& postfix); std::string generate_cb_memory_instance_name(const std::string& prefix, - const e_side& cb_side, - const size_t& pin_id, + const e_side& cb_side, + const size_t& pin_id, const std::string& postfix); std::string generate_pb_mux_instance_name(const std::string& prefix, - t_pb_graph_pin* pb_graph_pin, + t_pb_graph_pin* pb_graph_pin, const std::string& postfix); std::string generate_pb_memory_instance_name(const std::string& prefix, - t_pb_graph_pin* pb_graph_pin, + t_pb_graph_pin* pb_graph_pin, const std::string& postfix); -std::string generate_grid_port_name(const size_t& width, - const size_t& height, - const int& subtile_index, - const e_side& side, +std::string generate_grid_port_name(const size_t& width, const size_t& height, + const int& subtile_index, + const e_side& side, const BasicPort& pin_info); -std::string generate_grid_duplicated_port_name(const size_t& width, - const size_t& height, - const int& subtile_index, - const e_side& side, - const BasicPort& pin_info, - const bool& upper_port); +std::string generate_grid_duplicated_port_name( + const size_t& width, const size_t& height, const int& subtile_index, + const e_side& side, const BasicPort& pin_info, const bool& upper_port); -std::string generate_routing_module_grid_port_name(const size_t& width, - const size_t& height, - const int& subtile_index, - const e_side& side, +std::string generate_routing_module_grid_port_name(const size_t& width, + const size_t& height, + const int& subtile_index, + const e_side& side, const BasicPort& pin_info); -std::string generate_reserved_sram_port_name(const e_circuit_model_port_type& port_type); +std::string generate_reserved_sram_port_name( + const e_circuit_model_port_type& port_type); -std::string generate_formal_verification_sram_port_name(const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model); +std::string generate_formal_verification_sram_port_name( + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model); std::string generate_configuration_chain_head_name(); @@ -177,47 +175,47 @@ std::string generate_mux_local_decoder_data_inv_port_name(); std::string generate_local_config_bus_port_name(); -std::string generate_sram_port_name(const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& port_type); +std::string generate_sram_port_name( + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& port_type); -std::string generate_sram_local_port_name(const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& port_type); +std::string generate_sram_local_port_name( + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& port_type); -std::string generate_regional_blwl_port_name(const std::string& blwl_port_prefix, - const ConfigRegionId& region_id); +std::string generate_regional_blwl_port_name( + const std::string& blwl_port_prefix, const ConfigRegionId& region_id); -std::string generate_bl_shift_register_module_name(const std::string& memory_model_name, - const size_t& shift_register_size); +std::string generate_bl_shift_register_module_name( + const std::string& memory_model_name, const size_t& shift_register_size); -std::string generate_wl_shift_register_module_name(const std::string& memory_model_name, - const size_t& shift_register_size); +std::string generate_wl_shift_register_module_name( + const std::string& memory_model_name, const size_t& shift_register_size); std::string generate_mux_input_bus_port_name(const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, - const size_t& mux_size, + const size_t& mux_size, const size_t& mux_instance_id); std::string generate_mux_config_bus_port_name(const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, - const size_t& mux_size, + const size_t& mux_size, const size_t& bus_id, const bool& inverted); -std::string generate_local_sram_port_name(const std::string& port_prefix, - const size_t& instance_id, - const e_circuit_model_port_type& port_type); +std::string generate_local_sram_port_name( + const std::string& port_prefix, const size_t& instance_id, + const e_circuit_model_port_type& port_type); -std::string generate_mux_sram_port_name(const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const size_t& mux_size, - const size_t& mux_instance_id, - const e_circuit_model_port_type& port_type); +std::string generate_mux_sram_port_name( + const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, + const size_t& mux_size, const size_t& mux_instance_id, + const e_circuit_model_port_type& port_type); -std::string generate_logical_tile_netlist_name(const std::string& prefix, - const t_pb_graph_node* pb_graph_head, - const std::string& postfix); +std::string generate_logical_tile_netlist_name( + const std::string& prefix, const t_pb_graph_node* pb_graph_head, + const std::string& postfix); std::string generate_grid_block_prefix(const std::string& prefix, const e_side& io_side); @@ -232,11 +230,10 @@ std::string generate_grid_block_module_name(const std::string& prefix, const bool& is_block_io, const e_side& io_side); -std::string generate_grid_block_instance_name(const std::string& prefix, - const std::string& block_name, - const bool& is_block_io, - const e_side& io_side, - const vtr::Point& grid_coord); +std::string generate_grid_block_instance_name( + const std::string& prefix, const std::string& block_name, + const bool& is_block_io, const e_side& io_side, + const vtr::Point& grid_coord); std::string generate_physical_block_module_name(t_pb_type* physical_pb_type); @@ -246,19 +243,18 @@ std::string generate_physical_block_instance_name(t_pb_type* pb_type, e_side find_grid_border_side(const vtr::Point& device_size, const vtr::Point& grid_coordinate); -bool is_core_grid_on_given_border_side(const vtr::Point& device_size, - const vtr::Point& grid_coordinate, - const e_side& border_side); +bool is_core_grid_on_given_border_side( + const vtr::Point& device_size, + const vtr::Point& grid_coordinate, const e_side& border_side); std::string generate_pb_type_port_name(t_pb_type* pb_type, t_port* pb_type_port); std::string generate_pb_type_port_name(t_port* pb_type_port); -std::string generate_fpga_global_io_port_name(const std::string& prefix, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const CircuitPortId& circuit_port); +std::string generate_fpga_global_io_port_name( + const std::string& prefix, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, const CircuitPortId& circuit_port); std::string generate_fpga_top_module_name(); @@ -266,10 +262,11 @@ std::string generate_fpga_top_netlist_name(const std::string& postfix); std::string generate_const_value_module_name(const size_t& const_val); -std::string generate_const_value_module_output_port_name(const size_t& const_val); +std::string generate_const_value_module_output_port_name( + const size_t& const_val); -std::string generate_analysis_sdc_file_name(const std::string& circuit_name, - const std::string& file_name_postfix); +std::string generate_analysis_sdc_file_name( + const std::string& circuit_name, const std::string& file_name_postfix); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_pb_pin_fixup.cpp b/openfpga/src/base/openfpga_pb_pin_fixup.cpp index b104ea344..6bc693eeb 100644 --- a/openfpga/src/base/openfpga_pb_pin_fixup.cpp +++ b/openfpga/src/base/openfpga_pb_pin_fixup.cpp @@ -1,11 +1,11 @@ /******************************************************************** - * This file includes functions to fix up the pb pin mapping results + * This file includes functions to fix up the pb pin mapping results * after routing optimization *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" #include "vtr_assert.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgashell library */ #include "command_exit_codes.h" @@ -14,12 +14,11 @@ #include "vpr_utils.h" /* Headers from openfpgautil library */ -#include "openfpga_side_manager.h" - -#include "pb_type_utils.h" -#include "openfpga_physical_tile_utils.h" #include "openfpga_device_grid_utils.h" #include "openfpga_pb_pin_fixup.h" +#include "openfpga_physical_tile_utils.h" +#include "openfpga_side_manager.h" +#include "pb_type_utils.h" /* Include global variables of VPR */ #include "globals.h" @@ -29,33 +28,29 @@ namespace openfpga { /******************************************************************** * Fix up the pb pin mapping results for a given clustered block - * 1. For each input/output pin of a clustered pb, + * 1. For each input/output pin of a clustered pb, * - find a corresponding node in RRGraph object * - find the net id for the node in routing context * - find the net id for the node in clustering context * - if the net id does not match, we update the clustering context *******************************************************************/ -static -void update_cluster_pin_with_post_routing_results(const DeviceContext& device_ctx, - const ClusteringContext& clustering_ctx, - const VprRoutingAnnotation& vpr_routing_annotation, - VprClusteringAnnotation& vpr_clustering_annotation, - const vtr::Point& grid_coord, - const ClusterBlockId& blk_id, - const e_side& border_side, - const size_t& z, - const bool& verbose) { +static void update_cluster_pin_with_post_routing_results( + const DeviceContext& device_ctx, const ClusteringContext& clustering_ctx, + const VprRoutingAnnotation& vpr_routing_annotation, + VprClusteringAnnotation& vpr_clustering_annotation, + const vtr::Point& grid_coord, const ClusterBlockId& blk_id, + const e_side& border_side, const size_t& z, const bool& verbose) { /* Handle each pin */ auto logical_block = clustering_ctx.clb_nlist.block_type(blk_id); auto physical_tile = device_ctx.grid[grid_coord.x()][grid_coord.y()].type; for (int j = 0; j < logical_block->pb_type->num_pins; j++) { - /* Get the ptc num for the pin in rr_graph, we need t consider the z offset here - * z offset is the location in the multiple-logic-tile tile - * Get physical pin does not consider THIS!!!! + /* Get the ptc num for the pin in rr_graph, we need t consider the z offset + * here z offset is the location in the multiple-logic-tile tile Get + * physical pin does not consider THIS!!!! */ - int physical_pin = z * logical_block->pb_type->num_pins - + get_physical_pin(physical_tile, logical_block, j); + int physical_pin = z * logical_block->pb_type->num_pins + + get_physical_pin(physical_tile, logical_block, j); auto pin_class = physical_tile->pin_class[physical_pin]; auto class_inf = physical_tile->class_inf[pin_class]; @@ -66,15 +61,18 @@ void update_cluster_pin_with_post_routing_results(const DeviceContext& device_ct VTR_ASSERT(class_inf.type == RECEIVER); rr_node_type = IPIN; } - std::vector pin_sides = find_physical_tile_pin_side(physical_tile, physical_pin, border_side); - /* As some grid has height/width offset, we may not have the pin on any side */ + std::vector pin_sides = + find_physical_tile_pin_side(physical_tile, physical_pin, border_side); + /* As some grid has height/width offset, we may not have the pin on any side + */ if (0 == pin_sides.size()) { continue; } /* For regular grid, we should have pin only one side! - * I/O grids: VPR creates the grid with duplicated pins on every side - * but the expected side (only used side) will be opposite side of the border side! + * I/O grids: VPR creates the grid with duplicated pins on every side + * but the expected side (only used side) will be opposite side of the + * border side! */ e_side pin_side = NUM_SIDES; if (NUM_SIDES == border_side) { @@ -82,74 +80,84 @@ void update_cluster_pin_with_post_routing_results(const DeviceContext& device_ct pin_side = pin_sides[0]; } else { SideManager side_manager(border_side); - VTR_ASSERT(pin_sides.end() != std::find(pin_sides.begin(), pin_sides.end(), side_manager.get_opposite())); + VTR_ASSERT(pin_sides.end() != std::find(pin_sides.begin(), + pin_sides.end(), + side_manager.get_opposite())); pin_side = side_manager.get_opposite(); } /* Find the net mapped to this pin in routing results */ - const RRNodeId& rr_node = device_ctx.rr_graph.node_lookup().find_node(grid_coord.x(), grid_coord.y(), rr_node_type, physical_pin, pin_side); + const RRNodeId& rr_node = device_ctx.rr_graph.node_lookup().find_node( + grid_coord.x(), grid_coord.y(), rr_node_type, physical_pin, pin_side); if (false == device_ctx.rr_graph.valid_node(rr_node)) { continue; } /* Get the cluster net id which has been mapped to this net */ ClusterNetId routing_net_id = vpr_routing_annotation.rr_node_net(rr_node); - /* Find the net mapped to this pin in clustering results. There are two sources: - * - The original clustering netlist, where the pin mapping is based on pre-routing - * - The post-routing pin mapping, where the pin mapping is based on post-routing - * We always check the original clustering netlist first, if there is any remapping, check the remapping data + /* Find the net mapped to this pin in clustering results. There are two + * sources: + * - The original clustering netlist, where the pin mapping is based on + * pre-routing + * - The post-routing pin mapping, where the pin mapping is based on + * post-routing We always check the original clustering netlist first, if + * there is any remapping, check the remapping data */ ClusterNetId cluster_net_id = clustering_ctx.clb_nlist.block_net(blk_id, j); - /* Ignore those net have never been routed: this check is valid only - * when both packer has mapped a net to the pin and the router leaves the pin to be unmapped - * This is important because we cannot bypass when router forces a valid net to be mapped - * and the net remapping has to be considered + /* Ignore those net have never been routed: this check is valid only + * when both packer has mapped a net to the pin and the router leaves the + * pin to be unmapped This is important because we cannot bypass when router + * forces a valid net to be mapped and the net remapping has to be + * considered */ - if ( (ClusterNetId::INVALID() != cluster_net_id) - && (ClusterNetId::INVALID() == routing_net_id) - && (true == clustering_ctx.clb_nlist.net_is_ignored(cluster_net_id))) { - VTR_LOGV(verbose, - "Bypass net at clustered block '%s' pin 'grid[%ld][%ld].%s.%s[%d]' as it is not routed\n", - clustering_ctx.clb_nlist.block_pb(blk_id)->name, - grid_coord.x(), grid_coord.y(), - clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name, - get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name, - get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number - ); + if ((ClusterNetId::INVALID() != cluster_net_id) && + (ClusterNetId::INVALID() == routing_net_id) && + (true == clustering_ctx.clb_nlist.net_is_ignored(cluster_net_id))) { + VTR_LOGV( + verbose, + "Bypass net at clustered block '%s' pin 'grid[%ld][%ld].%s.%s[%d]' as " + "it is not routed\n", + clustering_ctx.clb_nlist.block_pb(blk_id)->name, grid_coord.x(), + grid_coord.y(), + clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name, + get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name, + get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number); continue; } /* Ignore used in local cluster only, reserved one CLB pin */ - if ( (ClusterNetId::INVALID() != cluster_net_id) - && (0 == clustering_ctx.clb_nlist.net_sinks(cluster_net_id).size())) { - VTR_LOGV(verbose, - "Bypass net at clustered block '%s' pin 'grid[%ld][%ld].%s.%s[%d]' as it is a local net inside the cluster\n", - clustering_ctx.clb_nlist.block_pb(blk_id)->name, - grid_coord.x(), grid_coord.y(), - clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name, - get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name, - get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number - ); + if ((ClusterNetId::INVALID() != cluster_net_id) && + (0 == clustering_ctx.clb_nlist.net_sinks(cluster_net_id).size())) { + VTR_LOGV( + verbose, + "Bypass net at clustered block '%s' pin 'grid[%ld][%ld].%s.%s[%d]' as " + "it is a local net inside the cluster\n", + clustering_ctx.clb_nlist.block_pb(blk_id)->name, grid_coord.x(), + grid_coord.y(), + clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name, + get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name, + get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number); continue; } /* If matched, we finish here */ if (routing_net_id == cluster_net_id) { - VTR_LOGV(verbose, - "Bypass net at clustered block '%s' pin 'grid[%ld][%ld].%s.%s[%d]' as it matches cluster routing\n", - clustering_ctx.clb_nlist.block_pb(blk_id)->name, - grid_coord.x(), grid_coord.y(), - clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name, - get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name, - get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number - ); + VTR_LOGV( + verbose, + "Bypass net at clustered block '%s' pin 'grid[%ld][%ld].%s.%s[%d]' as " + "it matches cluster routing\n", + clustering_ctx.clb_nlist.block_pb(blk_id)->name, grid_coord.x(), + grid_coord.y(), + clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name, + get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name, + get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number); continue; } /* Add to net modification */ vpr_clustering_annotation.rename_net(blk_id, j, routing_net_id); - + std::string routing_net_name("unmapped"); if (ClusterNetId::INVALID() != routing_net_id) { routing_net_name = clustering_ctx.clb_nlist.net_name(routing_net_id); @@ -160,31 +168,30 @@ void update_cluster_pin_with_post_routing_results(const DeviceContext& device_ct cluster_net_name = clustering_ctx.clb_nlist.net_name(cluster_net_id); } - VTR_LOGV(verbose, - "Fixed up net '%s' mapping mismatch at clustered block '%s' pin 'grid[%ld][%ld].%s.%s[%d]' (was net '%s')\n", - routing_net_name.c_str(), - clustering_ctx.clb_nlist.block_pb(blk_id)->name, - grid_coord.x(), grid_coord.y(), - clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name, - get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name, - get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number, - cluster_net_name.c_str() - ); + VTR_LOGV( + verbose, + "Fixed up net '%s' mapping mismatch at clustered block '%s' pin " + "'grid[%ld][%ld].%s.%s[%d]' (was net '%s')\n", + routing_net_name.c_str(), clustering_ctx.clb_nlist.block_pb(blk_id)->name, + grid_coord.x(), grid_coord.y(), + clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name, + get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name, + get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number, + cluster_net_name.c_str()); } } /******************************************************************** - * Main function to fix up the pb pin mapping results + * Main function to fix up the pb pin mapping results * This function will walk through each grid *******************************************************************/ -static -void update_pb_pin_with_post_routing_results(const DeviceContext& device_ctx, - const ClusteringContext& clustering_ctx, - const PlacementContext& placement_ctx, - const VprRoutingAnnotation& vpr_routing_annotation, - VprClusteringAnnotation& vpr_clustering_annotation, - const bool& verbose) { - /* Ensure a clean start: remove all the remapping results from VTR's post-routing clustering result sync-up */ +static void update_pb_pin_with_post_routing_results( + const DeviceContext& device_ctx, const ClusteringContext& clustering_ctx, + const PlacementContext& placement_ctx, + const VprRoutingAnnotation& vpr_routing_annotation, + VprClusteringAnnotation& vpr_clustering_annotation, const bool& verbose) { + /* Ensure a clean start: remove all the remapping results from VTR's + * post-routing clustering result sync-up */ vpr_clustering_annotation.clear_net_remapping(); /* Update the core logic (center blocks of the FPGA) */ @@ -195,78 +202,78 @@ void update_pb_pin_with_post_routing_results(const DeviceContext& device_ctx, continue; } /* Get the mapped blocks to this grid */ - for (const ClusterBlockId& cluster_blk_id : placement_ctx.grid_blocks[x][y].blocks) { - /* Skip invalid ids */ + for (const ClusterBlockId& cluster_blk_id : + placement_ctx.grid_blocks[x][y].blocks) { + /* Skip invalid ids */ if (ClusterBlockId::INVALID() == cluster_blk_id) { continue; } - /* We know the entrance to grid info and mapping results, do the fix-up for this block */ + /* We know the entrance to grid info and mapping results, do the fix-up + * for this block */ vtr::Point grid_coord(x, y); - update_cluster_pin_with_post_routing_results(device_ctx, clustering_ctx, - vpr_routing_annotation, - vpr_clustering_annotation, - grid_coord, cluster_blk_id, NUM_SIDES, - placement_ctx.block_locs[cluster_blk_id].loc.sub_tile, - verbose); - } + update_cluster_pin_with_post_routing_results( + device_ctx, clustering_ctx, vpr_routing_annotation, + vpr_clustering_annotation, grid_coord, cluster_blk_id, NUM_SIDES, + placement_ctx.block_locs[cluster_blk_id].loc.sub_tile, verbose); + } } } - + /* Create the coordinate range for each side of FPGA fabric */ - std::map>> io_coordinates = generate_perimeter_grid_coordinates(device_ctx.grid); + std::map>> io_coordinates = + generate_perimeter_grid_coordinates(device_ctx.grid); for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { for (const vtr::Point& io_coord : io_coordinates[io_side]) { /* Bypass EMPTY grid */ - if (true == is_empty_type(device_ctx.grid[io_coord.x()][io_coord.y()].type)) { + if (true == + is_empty_type(device_ctx.grid[io_coord.x()][io_coord.y()].type)) { continue; } /* Get the mapped blocks to this grid */ - for (const ClusterBlockId& cluster_blk_id : placement_ctx.grid_blocks[io_coord.x()][io_coord.y()].blocks) { - /* Skip invalid ids */ + for (const ClusterBlockId& cluster_blk_id : + placement_ctx.grid_blocks[io_coord.x()][io_coord.y()].blocks) { + /* Skip invalid ids */ if (ClusterBlockId::INVALID() == cluster_blk_id) { continue; } /* Update on I/O grid */ - update_cluster_pin_with_post_routing_results(device_ctx, clustering_ctx, - vpr_routing_annotation, - vpr_clustering_annotation, - io_coord, cluster_blk_id, io_side, - placement_ctx.block_locs[cluster_blk_id].loc.sub_tile, - verbose); + update_cluster_pin_with_post_routing_results( + device_ctx, clustering_ctx, vpr_routing_annotation, + vpr_clustering_annotation, io_coord, cluster_blk_id, io_side, + placement_ctx.block_locs[cluster_blk_id].loc.sub_tile, verbose); } } } } /******************************************************************** - * Top-level function to fix up the pb pin mapping results + * Top-level function to fix up the pb pin mapping results * The problem comes from a mismatch between the packing and routing results * When there are equivalent input/output for any grids, router will try - * to swap the net mapping among these pins so as to achieve best + * to swap the net mapping among these pins so as to achieve best * routing optimization. - * However, it will cause the packing results out-of-date as the net mapping + * However, it will cause the packing results out-of-date as the net mapping * of each grid remain untouched once packing is done. * This function aims to fix the mess after routing so that the net mapping * can be synchronized *******************************************************************/ -int pb_pin_fixup(OpenfpgaContext& openfpga_context, - const Command& cmd, const CommandContext& cmd_context) { - - vtr::ScopedStartFinishTimer timer("Fix up pb pin mapping results after routing optimization"); +int pb_pin_fixup(OpenfpgaContext& openfpga_context, const Command& cmd, + const CommandContext& cmd_context) { + vtr::ScopedStartFinishTimer timer( + "Fix up pb pin mapping results after routing optimization"); CommandOptionId opt_verbose = cmd.option("verbose"); /* Apply fix-up to each grid */ - update_pb_pin_with_post_routing_results(g_vpr_ctx.device(), - g_vpr_ctx.clustering(), - g_vpr_ctx.placement(), - openfpga_context.vpr_routing_annotation(), - openfpga_context.mutable_vpr_clustering_annotation(), - cmd_context.option_enable(cmd, opt_verbose)); + update_pb_pin_with_post_routing_results( + g_vpr_ctx.device(), g_vpr_ctx.clustering(), g_vpr_ctx.placement(), + openfpga_context.vpr_routing_annotation(), + openfpga_context.mutable_vpr_clustering_annotation(), + cmd_context.option_enable(cmd, opt_verbose)); /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; -} +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_pb_pin_fixup.h b/openfpga/src/base/openfpga_pb_pin_fixup.h index bab4e9565..e7141ebdc 100644 --- a/openfpga/src/base/openfpga_pb_pin_fixup.h +++ b/openfpga/src/base/openfpga_pb_pin_fixup.h @@ -15,8 +15,8 @@ /* begin namespace openfpga */ namespace openfpga { -int pb_pin_fixup(OpenfpgaContext& openfpga_context, - const Command& cmd, const CommandContext& cmd_context); +int pb_pin_fixup(OpenfpgaContext& openfpga_context, const Command& cmd, + const CommandContext& cmd_context); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_pcf2place.cpp b/openfpga/src/base/openfpga_pcf2place.cpp index 7536e2420..02ecea463 100644 --- a/openfpga/src/base/openfpga_pcf2place.cpp +++ b/openfpga/src/base/openfpga_pcf2place.cpp @@ -2,8 +2,8 @@ * This file includes functions to build bitstream database *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgashell library */ #include "command_exit_codes.h" @@ -12,25 +12,23 @@ #include "openfpga_digest.h" /* Headers from pcf library */ -#include "pcf_reader.h" #include "blif_head_reader.h" +#include "io_net_place.h" +#include "openfpga_pcf2place.h" +#include "pcf2place.h" +#include "pcf_reader.h" #include "read_csv_io_pin_table.h" #include "read_xml_io_location_map.h" -#include "io_net_place.h" -#include "pcf2place.h" - -#include "openfpga_pcf2place.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * Top-level function to convert a .pcf file to a .place file which + * Top-level function to convert a .pcf file to a .place file which * which VPR can force I/O placement *******************************************************************/ int pcf2place_wrapper(const OpenfpgaContext& openfpga_context, const Command& cmd, const CommandContext& cmd_context) { - /* todo: create a factory to produce this in the future*/ CommandOptionId opt_pcf = cmd.option("pcf"); CommandOptionId opt_blif = cmd.option("blif"); @@ -42,9 +40,11 @@ int pcf2place_wrapper(const OpenfpgaContext& openfpga_context, std::string pcf_fname = cmd_context.option_value(cmd, opt_pcf); std::string blif_fname = cmd_context.option_value(cmd, opt_blif); - std::string fpga_io_map_fname = cmd_context.option_value(cmd, opt_fpga_io_map); + std::string fpga_io_map_fname = + cmd_context.option_value(cmd, opt_fpga_io_map); std::string pin_table_fname = cmd_context.option_value(cmd, opt_pin_table); - std::string fpga_fix_pins_fname = cmd_context.option_value(cmd, opt_fpga_fix_pins); + std::string fpga_fix_pins_fname = + cmd_context.option_value(cmd, opt_fpga_fix_pins); /* Parse the input files */ openfpga::PcfData pcf_data; @@ -54,14 +54,14 @@ int pcf2place_wrapper(const OpenfpgaContext& openfpga_context, blifparse::BlifHeadReader callback; blifparse::blif_parse_filename(blif_fname.c_str(), callback); - VTR_LOG("Read the blif from a file: %s.\n", - blif_fname.c_str()); + VTR_LOG("Read the blif from a file: %s.\n", blif_fname.c_str()); if (callback.had_error()) { VTR_LOG_ERROR("Read the blif ends with errors\n"); return CMD_EXEC_FATAL_ERROR; } - IoLocationMap io_location_map = read_xml_io_location_map(fpga_io_map_fname.c_str()); + IoLocationMap io_location_map = + read_xml_io_location_map(fpga_io_map_fname.c_str()); VTR_LOG("Read the I/O location map from an XML file: %s.\n", fpga_io_map_fname.c_str()); @@ -71,15 +71,18 @@ int pcf2place_wrapper(const OpenfpgaContext& openfpga_context, /* Convert */ IoNetPlace io_net_place; - int status = pcf2place(pcf_data, callback.input_pins(), callback.output_pins(), io_pin_table, io_location_map, io_net_place); + int status = + pcf2place(pcf_data, callback.input_pins(), callback.output_pins(), + io_pin_table, io_location_map, io_net_place); if (status) { return status; } /* Output */ - status = io_net_place.write_to_place_file(fpga_fix_pins_fname.c_str(), - cmd_context.option_enable(cmd, opt_no_time_stamp), - cmd_context.option_enable(cmd, opt_verbose)); + status = io_net_place.write_to_place_file( + fpga_fix_pins_fname.c_str(), + cmd_context.option_enable(cmd, opt_no_time_stamp), + cmd_context.option_enable(cmd, opt_verbose)); if (status) { return status; } diff --git a/openfpga/src/base/openfpga_pcf2place.h b/openfpga/src/base/openfpga_pcf2place.h index 5b93272eb..7b8eb1a62 100644 --- a/openfpga/src/base/openfpga_pcf2place.h +++ b/openfpga/src/base/openfpga_pcf2place.h @@ -16,7 +16,7 @@ namespace openfpga { int pcf2place_wrapper(const OpenfpgaContext& openfpga_context, - const Command& cmd, const CommandContext& cmd_context); + const Command& cmd, const CommandContext& cmd_context); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_read_arch.cpp b/openfpga/src/base/openfpga_read_arch.cpp index 56d96f740..9c7f41a3e 100644 --- a/openfpga/src/base/openfpga_read_arch.cpp +++ b/openfpga/src/base/openfpga_read_arch.cpp @@ -9,13 +9,12 @@ #include "command_exit_codes.h" /* Headers from archopenfpga library */ -#include "read_xml_openfpga_arch.h" #include "check_circuit_library.h" -#include "circuit_library_utils.h" #include "check_tile_annotation.h" -#include "write_xml_openfpga_arch.h" - +#include "circuit_library_utils.h" #include "openfpga_read_arch.h" +#include "read_xml_openfpga_arch.h" +#include "write_xml_openfpga_arch.h" /* Include global variables of VPR */ #include "globals.h" @@ -25,15 +24,15 @@ namespace openfpga { /******************************************************************** * Top-level function to read an OpenFPGA architecture file - * we use the APIs from the libarchopenfpga library + * we use the APIs from the libarchopenfpga library * * The command will accept an option '--file' which is the architecture - * file provided by users + * file provided by users *******************************************************************/ -int read_arch(OpenfpgaContext& 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 +int read_arch(OpenfpgaContext& 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"); @@ -42,9 +41,9 @@ int read_arch(OpenfpgaContext& openfpga_context, std::string arch_file_name = cmd_context.option_value(cmd, opt_file); - VTR_LOG("Reading XML architecture '%s'...\n", - arch_file_name.c_str()); - openfpga_context.mutable_arch() = read_xml_openfpga_arch(arch_file_name.c_str()); + VTR_LOG("Reading XML architecture '%s'...\n", arch_file_name.c_str()); + openfpga_context.mutable_arch() = + read_xml_openfpga_arch(arch_file_name.c_str()); /* Check the architecture: * 1. Circuit library @@ -56,8 +55,9 @@ int read_arch(OpenfpgaContext& openfpga_context, return CMD_EXEC_FATAL_ERROR; } - if (false == check_configurable_memory_circuit_model(openfpga_context.arch().config_protocol, - openfpga_context.arch().circuit_lib)) { + if (false == check_configurable_memory_circuit_model( + openfpga_context.arch().config_protocol, + openfpga_context.arch().circuit_lib)) { return CMD_EXEC_FATAL_ERROR; } @@ -68,19 +68,19 @@ int read_arch(OpenfpgaContext& openfpga_context, } return CMD_EXEC_SUCCESS; -} +} /******************************************************************** * A function to write an OpenFPGA architecture file - * we use the APIs from the libarchopenfpga library + * we use the APIs from the libarchopenfpga library * * The command will accept an option '--file' which is the architecture - * file provided by users + * file provided by users *******************************************************************/ -int write_arch(const OpenfpgaContext& 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 +int write_arch(const OpenfpgaContext& 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"); @@ -89,25 +89,25 @@ int write_arch(const OpenfpgaContext& openfpga_context, std::string arch_file_name = cmd_context.option_value(cmd, opt_file); - VTR_LOG("Writing XML architecture to '%s'...\n", - arch_file_name.c_str()); + VTR_LOG("Writing XML architecture to '%s'...\n", arch_file_name.c_str()); write_xml_openfpga_arch(arch_file_name.c_str(), openfpga_context.arch()); /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; -} +} /******************************************************************** * Top-level function to read an OpenFPGA simulation setting file - * we use the APIs from the libarchopenfpga library + * we use the APIs from the libarchopenfpga library * * The command will accept an option '--file' which is the simulation setting - * file provided by users + * file provided by users *******************************************************************/ int read_simulation_setting(OpenfpgaContext& 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 + 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"); @@ -116,9 +116,9 @@ int read_simulation_setting(OpenfpgaContext& openfpga_context, std::string arch_file_name = cmd_context.option_value(cmd, opt_file); - VTR_LOG("Reading XML simulation setting '%s'...\n", - arch_file_name.c_str()); - openfpga_context.mutable_simulation_setting() = read_xml_openfpga_simulation_settings(arch_file_name.c_str()); + VTR_LOG("Reading XML simulation setting '%s'...\n", arch_file_name.c_str()); + openfpga_context.mutable_simulation_setting() = + read_xml_openfpga_simulation_settings(arch_file_name.c_str()); /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; @@ -126,15 +126,16 @@ int read_simulation_setting(OpenfpgaContext& openfpga_context, /******************************************************************** * A function to write an OpenFPGA simulation setting file - * we use the APIs from the libarchopenfpga library + * we use the APIs from the libarchopenfpga library * * The command will accept an option '--file' which is the simulation setting - * file provided by users + * file provided by users *******************************************************************/ int write_simulation_setting(const OpenfpgaContext& 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 + 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"); @@ -145,23 +146,25 @@ int write_simulation_setting(const OpenfpgaContext& openfpga_context, VTR_LOG("Writing XML simulation setting to '%s'...\n", arch_file_name.c_str()); - write_xml_openfpga_simulation_settings(arch_file_name.c_str(), openfpga_context.simulation_setting()); + write_xml_openfpga_simulation_settings(arch_file_name.c_str(), + openfpga_context.simulation_setting()); /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; -} +} /******************************************************************** * Top-level function to read an OpenFPGA bitstream setting file - * we use the APIs from the libarchopenfpga library + * we use the APIs from the libarchopenfpga library * * The command will accept an option '--file' which is the bitstream setting - * file provided by users + * file provided by users *******************************************************************/ int read_bitstream_setting(OpenfpgaContext& 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 + 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"); @@ -170,9 +173,9 @@ int read_bitstream_setting(OpenfpgaContext& openfpga_context, std::string arch_file_name = cmd_context.option_value(cmd, opt_file); - VTR_LOG("Reading XML bitstream setting '%s'...\n", - arch_file_name.c_str()); - openfpga_context.mutable_bitstream_setting() = read_xml_openfpga_bitstream_settings(arch_file_name.c_str()); + VTR_LOG("Reading XML bitstream setting '%s'...\n", arch_file_name.c_str()); + openfpga_context.mutable_bitstream_setting() = + read_xml_openfpga_bitstream_settings(arch_file_name.c_str()); /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; @@ -180,15 +183,16 @@ int read_bitstream_setting(OpenfpgaContext& openfpga_context, /******************************************************************** * A function to write an OpenFPGA bitstream setting file - * we use the APIs from the libarchopenfpga library + * we use the APIs from the libarchopenfpga library * * The command will accept an option '--file' which is the simulation setting - * file provided by users + * file provided by users *******************************************************************/ int write_bitstream_setting(const OpenfpgaContext& 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 + 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"); @@ -197,13 +201,12 @@ int write_bitstream_setting(const OpenfpgaContext& openfpga_context, std::string arch_file_name = cmd_context.option_value(cmd, opt_file); - VTR_LOG("Writing XML bitstream setting to '%s'...\n", - arch_file_name.c_str()); - write_xml_openfpga_bitstream_settings(arch_file_name.c_str(), openfpga_context.bitstream_setting()); + VTR_LOG("Writing XML bitstream setting to '%s'...\n", arch_file_name.c_str()); + write_xml_openfpga_bitstream_settings(arch_file_name.c_str(), + openfpga_context.bitstream_setting()); /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; -} +} } /* end namespace openfpga */ - diff --git a/openfpga/src/base/openfpga_read_arch.h b/openfpga/src/base/openfpga_read_arch.h index 9ffc0d3cb..1d1e8d230 100644 --- a/openfpga/src/base/openfpga_read_arch.h +++ b/openfpga/src/base/openfpga_read_arch.h @@ -15,24 +15,27 @@ /* begin namespace openfpga */ namespace openfpga { -int read_arch(OpenfpgaContext& openfpga_context, - const Command& cmd, const CommandContext& cmd_context); +int read_arch(OpenfpgaContext& openfpga_context, const Command& cmd, + const CommandContext& cmd_context); -int write_arch(const OpenfpgaContext& openfpga_context, - const Command& cmd, const CommandContext& cmd_context); +int write_arch(const OpenfpgaContext& openfpga_context, const Command& cmd, + const CommandContext& cmd_context); int read_simulation_setting(OpenfpgaContext& openfpga_context, - const Command& cmd, const CommandContext& cmd_context); + const Command& cmd, + const CommandContext& cmd_context); int write_simulation_setting(const OpenfpgaContext& openfpga_context, - const Command& cmd, const CommandContext& cmd_context); + const Command& cmd, + const CommandContext& cmd_context); int read_bitstream_setting(OpenfpgaContext& openfpga_context, - const Command& cmd, const CommandContext& cmd_context); + const Command& cmd, + const CommandContext& cmd_context); int write_bitstream_setting(const OpenfpgaContext& openfpga_context, - const Command& cmd, const CommandContext& cmd_context); - + const Command& cmd, + const CommandContext& cmd_context); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_repack.cpp b/openfpga/src/base/openfpga_repack.cpp index 050aba312..2d607b58c 100644 --- a/openfpga/src/base/openfpga_repack.cpp +++ b/openfpga/src/base/openfpga_repack.cpp @@ -2,20 +2,18 @@ * This file includes functions to compress the hierachy of routing architecture *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgashell library */ #include "command_exit_codes.h" /* Headers from librepackdc library */ -#include "repack_design_constraints.h" -#include "read_xml_repack_design_constraints.h" - #include "build_physical_truth_table.h" -#include "repack.h" #include "openfpga_repack.h" - +#include "read_xml_repack_design_constraints.h" +#include "repack.h" +#include "repack_design_constraints.h" /* Include global variables of VPR */ #include "globals.h" @@ -24,27 +22,30 @@ namespace openfpga { /******************************************************************** - * A wrapper function to call the fabric_verilog function of FPGA-Verilog + * A wrapper function to call the fabric_verilog function of FPGA-Verilog *******************************************************************/ -int repack(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - +int repack(OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_design_constraints = cmd.option("design_constraints"); - CommandOptionId opt_ignore_global_nets = cmd.option("ignore_global_nets_on_pins"); + CommandOptionId opt_ignore_global_nets = + cmd.option("ignore_global_nets_on_pins"); CommandOptionId opt_verbose = cmd.option("verbose"); /* Load design constraints from file */ RepackDesignConstraints repack_design_constraints; if (true == cmd_context.option_enable(cmd, opt_design_constraints)) { - std::string dc_fname = cmd_context.option_value(cmd, opt_design_constraints); + std::string dc_fname = + cmd_context.option_value(cmd, opt_design_constraints); VTR_ASSERT(false == dc_fname.empty()); - repack_design_constraints = read_xml_repack_design_constraints(dc_fname.c_str()); + repack_design_constraints = + read_xml_repack_design_constraints(dc_fname.c_str()); } /* Setup repacker options */ RepackOption options; options.set_design_constraints(repack_design_constraints); - options.set_ignore_global_nets_on_pins(cmd_context.option_value(cmd, opt_ignore_global_nets)); + options.set_ignore_global_nets_on_pins( + cmd_context.option_value(cmd, opt_ignore_global_nets)); options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); if (!options.valid()) { @@ -52,24 +53,20 @@ int repack(OpenfpgaContext& openfpga_ctx, return CMD_EXEC_FATAL_ERROR; } - pack_physical_pbs(g_vpr_ctx.device(), - g_vpr_ctx.atom(), + pack_physical_pbs(g_vpr_ctx.device(), g_vpr_ctx.atom(), g_vpr_ctx.clustering(), openfpga_ctx.mutable_vpr_device_annotation(), openfpga_ctx.mutable_vpr_clustering_annotation(), openfpga_ctx.vpr_bitstream_annotation(), - openfpga_ctx.arch().circuit_lib, - options); + openfpga_ctx.arch().circuit_lib, options); - build_physical_lut_truth_tables(openfpga_ctx.mutable_vpr_clustering_annotation(), - g_vpr_ctx.atom(), - g_vpr_ctx.clustering(), - openfpga_ctx.vpr_device_annotation(), - openfpga_ctx.arch().circuit_lib, - options.verbose_output()); + build_physical_lut_truth_tables( + openfpga_ctx.mutable_vpr_clustering_annotation(), g_vpr_ctx.atom(), + g_vpr_ctx.clustering(), openfpga_ctx.vpr_device_annotation(), + openfpga_ctx.arch().circuit_lib, options.verbose_output()); /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; -} +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_repack.h b/openfpga/src/base/openfpga_repack.h index 83e4bce63..0ad9d5f73 100644 --- a/openfpga/src/base/openfpga_repack.h +++ b/openfpga/src/base/openfpga_repack.h @@ -15,8 +15,8 @@ /* begin namespace openfpga */ namespace openfpga { -int repack(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); +int repack(OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_sdc.cpp b/openfpga/src/base/openfpga_sdc.cpp index 44aa2d51e..c99275ad5 100644 --- a/openfpga/src/base/openfpga_sdc.cpp +++ b/openfpga/src/base/openfpga_sdc.cpp @@ -2,22 +2,21 @@ * This file includes functions to compress the hierachy of routing architecture *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgashell library */ #include "command_exit_codes.h" /* Headers from openfpgautil library */ -#include "openfpga_scale.h" -#include "openfpga_digest.h" - -#include "circuit_library_utils.h" -#include "pnr_sdc_writer.h" #include "analysis_sdc_writer.h" +#include "circuit_library_utils.h" #include "configuration_chain_sdc_writer.h" #include "configure_port_sdc_writer.h" +#include "openfpga_digest.h" +#include "openfpga_scale.h" #include "openfpga_sdc.h" +#include "pnr_sdc_writer.h" /* Include global variables of VPR */ #include "globals.h" @@ -28,29 +27,35 @@ namespace openfpga { /******************************************************************** * A wrapper function to call the PnR SDC generator of FPGA-SDC *******************************************************************/ -int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - +int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_output_dir = cmd.option("file"); CommandOptionId opt_flatten_names = cmd.option("flatten_names"); CommandOptionId opt_hierarchical = cmd.option("hierarchical"); CommandOptionId opt_time_unit = cmd.option("time_unit"); CommandOptionId opt_output_hierarchy = cmd.option("output_hierarchy"); - CommandOptionId opt_constrain_global_port = cmd.option("constrain_global_port"); - CommandOptionId opt_constrain_non_clock_global_port = cmd.option("constrain_non_clock_global_port"); + CommandOptionId opt_constrain_global_port = + cmd.option("constrain_global_port"); + CommandOptionId opt_constrain_non_clock_global_port = + cmd.option("constrain_non_clock_global_port"); CommandOptionId opt_constrain_grid = cmd.option("constrain_grid"); CommandOptionId opt_constrain_sb = cmd.option("constrain_sb"); CommandOptionId opt_constrain_cb = cmd.option("constrain_cb"); - CommandOptionId opt_constrain_configurable_memory_outputs = cmd.option("constrain_configurable_memory_outputs"); - CommandOptionId opt_constrain_routing_multiplexer_outputs = cmd.option("constrain_routing_multiplexer_outputs"); - CommandOptionId opt_constrain_switch_block_outputs = cmd.option("constrain_switch_block_outputs"); - CommandOptionId opt_constrain_zero_delay_paths = cmd.option("constrain_zero_delay_paths"); + CommandOptionId opt_constrain_configurable_memory_outputs = + cmd.option("constrain_configurable_memory_outputs"); + CommandOptionId opt_constrain_routing_multiplexer_outputs = + cmd.option("constrain_routing_multiplexer_outputs"); + CommandOptionId opt_constrain_switch_block_outputs = + cmd.option("constrain_switch_block_outputs"); + CommandOptionId opt_constrain_zero_delay_paths = + cmd.option("constrain_zero_delay_paths"); CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); - /* This is an intermediate data structure which is designed to modularize the FPGA-SDC - * Keep it independent from any other outside data structures + /* This is an intermediate data structure which is designed to modularize the + * FPGA-SDC Keep it independent from any other outside data structures */ - std::string sdc_dir_path = format_dir_path(cmd_context.option_value(cmd, opt_output_dir)); + std::string sdc_dir_path = + format_dir_path(cmd_context.option_value(cmd, opt_output_dir)); /* Create directories */ create_directory(sdc_dir_path); @@ -59,59 +64,68 @@ int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx, options.set_flatten_names(cmd_context.option_enable(cmd, opt_flatten_names)); options.set_hierarchical(cmd_context.option_enable(cmd, opt_hierarchical)); - + if (true == cmd_context.option_enable(cmd, opt_time_unit)) { - options.set_time_unit(string_to_time_unit(cmd_context.option_value(cmd, opt_time_unit))); + options.set_time_unit( + string_to_time_unit(cmd_context.option_value(cmd, opt_time_unit))); } - options.set_output_hierarchy(cmd_context.option_enable(cmd, opt_output_hierarchy)); + options.set_output_hierarchy( + cmd_context.option_enable(cmd, opt_output_hierarchy)); - options.set_constrain_global_port(cmd_context.option_enable(cmd, opt_constrain_global_port)); - options.set_constrain_non_clock_global_port(cmd_context.option_enable(cmd, opt_constrain_non_clock_global_port)); - options.set_constrain_grid(cmd_context.option_enable(cmd, opt_constrain_grid)); + options.set_constrain_global_port( + cmd_context.option_enable(cmd, opt_constrain_global_port)); + options.set_constrain_non_clock_global_port( + cmd_context.option_enable(cmd, opt_constrain_non_clock_global_port)); + options.set_constrain_grid( + cmd_context.option_enable(cmd, opt_constrain_grid)); options.set_constrain_sb(cmd_context.option_enable(cmd, opt_constrain_sb)); options.set_constrain_cb(cmd_context.option_enable(cmd, opt_constrain_cb)); - options.set_constrain_configurable_memory_outputs(cmd_context.option_enable(cmd, opt_constrain_configurable_memory_outputs)); - options.set_constrain_routing_multiplexer_outputs(cmd_context.option_enable(cmd, opt_constrain_routing_multiplexer_outputs)); - options.set_constrain_switch_block_outputs(cmd_context.option_enable(cmd, opt_constrain_switch_block_outputs)); - options.set_constrain_zero_delay_paths(cmd_context.option_enable(cmd, opt_constrain_zero_delay_paths)); + options.set_constrain_configurable_memory_outputs( + cmd_context.option_enable(cmd, opt_constrain_configurable_memory_outputs)); + options.set_constrain_routing_multiplexer_outputs( + cmd_context.option_enable(cmd, opt_constrain_routing_multiplexer_outputs)); + options.set_constrain_switch_block_outputs( + cmd_context.option_enable(cmd, opt_constrain_switch_block_outputs)); + options.set_constrain_zero_delay_paths( + cmd_context.option_enable(cmd, opt_constrain_zero_delay_paths)); options.set_time_stamp(!cmd_context.option_enable(cmd, opt_no_time_stamp)); - /* We first turn on default sdc option and then disable part of them by following users' options */ + /* We first turn on default sdc option and then disable part of them by + * following users' options */ if (false == options.generate_sdc_pnr()) { options.set_generate_sdc_pnr(true); } /* Execute only when sdc is enabled */ - if (true == options.generate_sdc_pnr()) { - print_pnr_sdc(options, - g_vpr_ctx.device(), - openfpga_ctx.vpr_device_annotation(), - openfpga_ctx.device_rr_gsb(), - openfpga_ctx.module_graph(), - openfpga_ctx.mux_lib(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.fabric_global_port_info(), - openfpga_ctx.simulation_setting(), - openfpga_ctx.flow_manager().compress_routing()); + if (true == options.generate_sdc_pnr()) { + print_pnr_sdc( + options, g_vpr_ctx.device(), openfpga_ctx.vpr_device_annotation(), + openfpga_ctx.device_rr_gsb(), openfpga_ctx.module_graph(), + openfpga_ctx.mux_lib(), openfpga_ctx.arch().circuit_lib, + openfpga_ctx.fabric_global_port_info(), openfpga_ctx.simulation_setting(), + openfpga_ctx.flow_manager().compress_routing()); } /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; -} +} /******************************************************************** - * A wrapper function to call the PnR SDC generator on configuration chain + * A wrapper function to call the PnR SDC generator on configuration chain * of FPGA-SDC *******************************************************************/ int write_configuration_chain_sdc(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - /* If the configuration protocol is not a configuration chain, we will not write anything */ + const Command& cmd, + const CommandContext& cmd_context) { + /* If the configuration protocol is not a configuration chain, we will not + * write anything */ if (CONFIG_MEM_SCAN_CHAIN != openfpga_ctx.arch().config_protocol.type()) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Configuration protocol is %s. Expected %s to write SDC!\n", - CONFIG_PROTOCOL_TYPE_STRING[openfpga_ctx.arch().config_protocol.type()], - CONFIG_PROTOCOL_TYPE_STRING[CONFIG_MEM_SCAN_CHAIN]); + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Configuration protocol is %s. Expected %s to write SDC!\n", + CONFIG_PROTOCOL_TYPE_STRING[openfpga_ctx.arch().config_protocol.type()], + CONFIG_PROTOCOL_TYPE_STRING[CONFIG_MEM_SCAN_CHAIN]); return CMD_EXEC_FATAL_ERROR; } @@ -122,17 +136,19 @@ int write_configuration_chain_sdc(const OpenfpgaContext& openfpga_ctx, CommandOptionId opt_max_delay = cmd.option("max_delay"); CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); - std::string sdc_dir_path = format_dir_path(cmd_context.option_value(cmd, opt_output_dir)); + std::string sdc_dir_path = + format_dir_path(cmd_context.option_value(cmd, opt_output_dir)); - float time_unit = string_to_time_unit(cmd_context.option_value(cmd, opt_time_unit)); + float time_unit = + string_to_time_unit(cmd_context.option_value(cmd, opt_time_unit)); /* Write the SDC for configuration chain */ - print_pnr_sdc_constrain_configurable_chain(cmd_context.option_value(cmd, opt_output_dir), - time_unit, - std::stof(cmd_context.option_value(cmd, opt_max_delay)), - std::stof(cmd_context.option_value(cmd, opt_min_delay)), - !cmd_context.option_enable(cmd, opt_no_time_stamp), - openfpga_ctx.module_graph()); + print_pnr_sdc_constrain_configurable_chain( + cmd_context.option_value(cmd, opt_output_dir), time_unit, + std::stof(cmd_context.option_value(cmd, opt_max_delay)), + std::stof(cmd_context.option_value(cmd, opt_min_delay)), + !cmd_context.option_enable(cmd, opt_no_time_stamp), + openfpga_ctx.module_graph()); return CMD_EXEC_SUCCESS; } @@ -141,26 +157,27 @@ int write_configuration_chain_sdc(const OpenfpgaContext& openfpga_ctx, * A wrapper function to call the PnR SDC generator on routing multiplexers * of FPGA-SDC *******************************************************************/ -int write_sdc_disable_timing_configure_ports(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - +int write_sdc_disable_timing_configure_ports( + const OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { /* Get command options */ CommandOptionId opt_output_dir = cmd.option("file"); CommandOptionId opt_flatten_names = cmd.option("flatten_names"); CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); CommandOptionId opt_verbose = cmd.option("verbose"); - std::string sdc_dir_path = format_dir_path(cmd_context.option_value(cmd, opt_output_dir)); + std::string sdc_dir_path = + format_dir_path(cmd_context.option_value(cmd, opt_output_dir)); /* Write the SDC for configuration chain */ - if (CMD_EXEC_FATAL_ERROR == - print_sdc_disable_timing_configure_ports(cmd_context.option_value(cmd, opt_output_dir), - cmd_context.option_enable(cmd, opt_flatten_names), - openfpga_ctx.mux_lib(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.module_graph(), - !cmd_context.option_enable(cmd, opt_no_time_stamp), - cmd_context.option_enable(cmd, opt_verbose))) { + if (CMD_EXEC_FATAL_ERROR == + print_sdc_disable_timing_configure_ports( + cmd_context.option_value(cmd, opt_output_dir), + cmd_context.option_enable(cmd, opt_flatten_names), + openfpga_ctx.mux_lib(), openfpga_ctx.arch().circuit_lib, + openfpga_ctx.module_graph(), + !cmd_context.option_enable(cmd, opt_no_time_stamp), + cmd_context.option_enable(cmd, opt_verbose))) { return CMD_EXEC_FATAL_ERROR; } @@ -170,18 +187,18 @@ int write_sdc_disable_timing_configure_ports(const OpenfpgaContext& openfpga_ctx /******************************************************************** * A wrapper function to call the analysis SDC generator of FPGA-SDC *******************************************************************/ -int write_analysis_sdc(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - +int write_analysis_sdc(const OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_output_dir = cmd.option("file"); CommandOptionId opt_flatten_names = cmd.option("flatten_names"); CommandOptionId opt_time_unit = cmd.option("time_unit"); CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); - /* This is an intermediate data structure which is designed to modularize the FPGA-SDC - * Keep it independent from any other outside data structures + /* This is an intermediate data structure which is designed to modularize the + * FPGA-SDC Keep it independent from any other outside data structures */ - std::string sdc_dir_path = format_dir_path(cmd_context.option_value(cmd, opt_output_dir)); + std::string sdc_dir_path = + format_dir_path(cmd_context.option_value(cmd, opt_output_dir)); /* Create directories */ create_directory(sdc_dir_path); @@ -192,15 +209,16 @@ int write_analysis_sdc(const OpenfpgaContext& openfpga_ctx, options.set_time_stamp(!cmd_context.option_enable(cmd, opt_no_time_stamp)); if (true == cmd_context.option_enable(cmd, opt_time_unit)) { - options.set_time_unit(string_to_time_unit(cmd_context.option_value(cmd, opt_time_unit))); + options.set_time_unit( + string_to_time_unit(cmd_context.option_value(cmd, opt_time_unit))); } if (true == options.generate_sdc_analysis()) { - print_analysis_sdc(options, - 1./openfpga_ctx.simulation_setting().default_operating_clock_frequency(), - g_vpr_ctx, - openfpga_ctx, - openfpga_ctx.flow_manager().compress_routing()); + print_analysis_sdc( + options, + 1. / + openfpga_ctx.simulation_setting().default_operating_clock_frequency(), + g_vpr_ctx, openfpga_ctx, openfpga_ctx.flow_manager().compress_routing()); } /* TODO: should identify the error code from internal function execution */ diff --git a/openfpga/src/base/openfpga_sdc.h b/openfpga/src/base/openfpga_sdc.h index 2dd97b72a..8b039080c 100644 --- a/openfpga/src/base/openfpga_sdc.h +++ b/openfpga/src/base/openfpga_sdc.h @@ -15,17 +15,19 @@ /* begin namespace openfpga */ namespace openfpga { -int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); +int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context); int write_configuration_chain_sdc(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); + const Command& cmd, + const CommandContext& cmd_context); -int write_sdc_disable_timing_configure_ports(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); +int write_sdc_disable_timing_configure_ports( + const OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context); -int write_analysis_sdc(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); +int write_analysis_sdc(const OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_sdc_command.cpp b/openfpga/src/base/openfpga_sdc_command.cpp index 42b14a290..ba1985a81 100644 --- a/openfpga/src/base/openfpga_sdc_command.cpp +++ b/openfpga/src/base/openfpga_sdc_command.cpp @@ -1,79 +1,105 @@ /******************************************************************** - * Add commands to the OpenFPGA shell interface, + * Add commands to the OpenFPGA shell interface, * in purpose of generate SDC files * - write_pnr_sdc : generate SDC to constrain the back-end flow for FPGA fabric * - write_analysis_sdc: TODO: generate SDC based on users' implementations *******************************************************************/ -#include "openfpga_sdc.h" #include "openfpga_sdc_command.h" +#include "openfpga_sdc.h" + /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * - Add a command to Shell environment: generate PnR SDC - * - Add associated options + * - Add a command to Shell environment: generate PnR SDC + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_write_pnr_sdc_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_pnr_sdc_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_pnr_sdc"); /* Add an option '--file' in short '-f'*/ - CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for SDC files"); + CommandOptionId output_opt = shell_cmd.add_option( + "file", true, "Specify the output directory for SDC files"); shell_cmd.set_option_short_name(output_opt, "f"); shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); /* Add an option '--flatten_name' */ - shell_cmd.add_option("flatten_names", false, "Use flatten names (no wildcards) in SDC files"); + shell_cmd.add_option("flatten_names", false, + "Use flatten names (no wildcards) in SDC files"); /* Add an option '--hierarchical' */ - shell_cmd.add_option("hierarchical", false, "Output SDC files hierachically (without full path in hierarchy)"); + shell_cmd.add_option( + "hierarchical", false, + "Output SDC files hierachically (without full path in hierarchy)"); /* Add an option '--output_hierarchy' */ - shell_cmd.add_option("output_hierarchy", false, "Output hierachy of Multiple-Instance-Blocks (MIBs) to plain text file. This is applied to constrain timing for grid, SBs and CBs"); + shell_cmd.add_option( + "output_hierarchy", false, + "Output hierachy of Multiple-Instance-Blocks (MIBs) to plain text file. " + "This is applied to constrain timing for grid, SBs and CBs"); /* Add an option '--time_unit' */ - CommandOptionId time_unit_opt = shell_cmd.add_option("time_unit", false, "Specify the time unit in SDC files. Acceptable is [a|f|p|n|u|m|k|M]s"); + CommandOptionId time_unit_opt = shell_cmd.add_option( + "time_unit", false, + "Specify the time unit in SDC files. Acceptable is [a|f|p|n|u|m|k|M]s"); shell_cmd.set_option_require_value(time_unit_opt, openfpga::OPT_STRING); /* Add an option '--constrain_global_port' */ - shell_cmd.add_option("constrain_global_port", false, "Constrain all the global ports of FPGA fabric"); + shell_cmd.add_option("constrain_global_port", false, + "Constrain all the global ports of FPGA fabric"); /* Add an option '--constrain_non_clock_global_port' */ - shell_cmd.add_option("constrain_non_clock_global_port", false, "Constrain all the non-clock global ports as clock ports of FPGA fabric"); + shell_cmd.add_option( + "constrain_non_clock_global_port", false, + "Constrain all the non-clock global ports as clock ports of FPGA fabric"); /* Add an option '--constrain_grid' */ - shell_cmd.add_option("constrain_grid", false, "Constrain all the grids of FPGA fabric"); + shell_cmd.add_option("constrain_grid", false, + "Constrain all the grids of FPGA fabric"); /* Add an option '--constrain_sb' */ - shell_cmd.add_option("constrain_sb", false, "Constrain all the switch blocks of FPGA fabric"); + shell_cmd.add_option("constrain_sb", false, + "Constrain all the switch blocks of FPGA fabric"); /* Add an option '--constrain_cb' */ - shell_cmd.add_option("constrain_cb", false, "Constrain all the connection blocks of FPGA fabric"); + shell_cmd.add_option("constrain_cb", false, + "Constrain all the connection blocks of FPGA fabric"); /* Add an option '--constrain_configurable_memory_outputs' */ - shell_cmd.add_option("constrain_configurable_memory_outputs", false, "Constrain all the outputs of configurable memories of FPGA fabric"); + shell_cmd.add_option( + "constrain_configurable_memory_outputs", false, + "Constrain all the outputs of configurable memories of FPGA fabric"); /* Add an option '--constrain_routing_multiplexer_outputs' */ - shell_cmd.add_option("constrain_routing_multiplexer_outputs", false, "Constrain all the outputs of routing multiplexer of FPGA fabric"); + shell_cmd.add_option( + "constrain_routing_multiplexer_outputs", false, + "Constrain all the outputs of routing multiplexer of FPGA fabric"); /* Add an option '--constrain_switch_block_outputs' */ - shell_cmd.add_option("constrain_switch_block_outputs", false, "Constrain all the outputs of switch blocks of FPGA fabric"); + shell_cmd.add_option( + "constrain_switch_block_outputs", false, + "Constrain all the outputs of switch blocks of FPGA fabric"); /* Add an option '--constrain_zero_delay_paths' */ - shell_cmd.add_option("constrain_zero_delay_paths", false, "Constrain zero-delay paths in FPGA fabric"); + shell_cmd.add_option("constrain_zero_delay_paths", false, + "Constrain zero-delay paths in FPGA fabric"); /* Add an option '--no_time_stamp' */ - shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files"); + shell_cmd.add_option("no_time_stamp", false, + "Do not print time stamp in output files"); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); - + /* Add command 'write_fabric_verilog' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate SDC files to constrain the backend flow for FPGA fabric"); + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, + "generate SDC files to constrain the backend flow for FPGA fabric"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_const_execute_function(shell_cmd_id, write_pnr_sdc); @@ -84,40 +110,50 @@ ShellCommandId add_openfpga_write_pnr_sdc_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_configuration_chain_sdc_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_configuration_chain_sdc"); /* Add an option '--file' in short '-f'*/ - CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the SDC file to constrain configuration chain"); + CommandOptionId output_opt = shell_cmd.add_option( + "file", true, "Specify the SDC file to constrain configuration chain"); shell_cmd.set_option_short_name(output_opt, "f"); shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); /* Add an option '--time_unit' */ - CommandOptionId time_unit_opt = shell_cmd.add_option("time_unit", false, "Specify the time unit in SDC files. Acceptable is [a|f|p|n|u|m|k|M]s"); + CommandOptionId time_unit_opt = shell_cmd.add_option( + "time_unit", false, + "Specify the time unit in SDC files. Acceptable is [a|f|p|n|u|m|k|M]s"); shell_cmd.set_option_require_value(time_unit_opt, openfpga::OPT_STRING); /* Add an option '--min_delay' */ - CommandOptionId min_dly_opt = shell_cmd.add_option("min_delay", false, "Specify the minimum delay to be used."); + CommandOptionId min_dly_opt = shell_cmd.add_option( + "min_delay", false, "Specify the minimum delay to be used."); shell_cmd.set_option_require_value(min_dly_opt, openfpga::OPT_STRING); /* Add an option '--max_delay' */ - CommandOptionId max_dly_opt = shell_cmd.add_option("max_delay", false, "Specify the maximum delay to be used."); + CommandOptionId max_dly_opt = shell_cmd.add_option( + "max_delay", false, "Specify the maximum delay to be used."); shell_cmd.set_option_require_value(max_dly_opt, openfpga::OPT_STRING); /* Add an option '--no_time_stamp' */ - shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files"); + shell_cmd.add_option("no_time_stamp", false, + "Do not print time stamp in output files"); /* Add command 'write_configuration_chain_sdc' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate SDC files to constrain the configuration chain for FPGA fabric"); + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, + "generate SDC files to constrain the configuration chain for FPGA fabric"); shell.set_command_class(shell_cmd_id, cmd_class_id); - shell.set_command_const_execute_function(shell_cmd_id, write_configuration_chain_sdc); + shell.set_command_const_execute_function(shell_cmd_id, + write_configuration_chain_sdc); /* Add command dependency to the Shell */ shell.set_command_dependency(shell_cmd_id, dependent_cmds); @@ -127,33 +163,41 @@ ShellCommandId add_openfpga_write_configuration_chain_sdc_command(openfpga::Shel /******************************************************************** * - Add a command to Shell environment: generate PnR SDC for configure ports - * - Add associated options + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_write_sdc_disable_timing_configure_ports_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId +add_openfpga_write_sdc_disable_timing_configure_ports_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_sdc_disable_timing_configure_ports"); /* Add an option '--file' in short '-f'*/ - CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory"); + CommandOptionId output_opt = + shell_cmd.add_option("file", true, "Specify the output directory"); shell_cmd.set_option_short_name(output_opt, "f"); shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); /* Add an option '--flatten_name' */ - shell_cmd.add_option("flatten_names", false, "Use flatten names (no wildcards) in SDC files"); + shell_cmd.add_option("flatten_names", false, + "Use flatten names (no wildcards) in SDC files"); /* Add an option '--no_time_stamp' */ - shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files"); + shell_cmd.add_option("no_time_stamp", false, + "Do not print time stamp in output files"); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose outputs"); /* Add command 'write_configuration_chain_sdc' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate SDC files to disable timing for configure ports across FPGA fabric"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, + "generate SDC files to disable timing for configure " + "ports across FPGA fabric"); shell.set_command_class(shell_cmd_id, cmd_class_id); - shell.set_command_const_execute_function(shell_cmd_id, write_sdc_disable_timing_configure_ports); + shell.set_command_const_execute_function( + shell_cmd_id, write_sdc_disable_timing_configure_ports); /* Add command dependency to the Shell */ shell.set_command_dependency(shell_cmd_id, dependent_cmds); @@ -162,18 +206,19 @@ ShellCommandId add_openfpga_write_sdc_disable_timing_configure_ports_command(ope } /******************************************************************** - * - Add a command to Shell environment: generate PnR SDC - * - Add associated options + * - Add a command to Shell environment: generate PnR SDC + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_write_analysis_sdc_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_analysis_sdc_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_analysis_sdc"); /* Add an option '--file' in short '-f'*/ - CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for SDC files"); + CommandOptionId output_opt = shell_cmd.add_option( + "file", true, "Specify the output directory for SDC files"); shell_cmd.set_option_short_name(output_opt, "f"); shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); @@ -181,17 +226,24 @@ ShellCommandId add_openfpga_write_analysis_sdc_command(openfpga::Shell& shell) { - /* Get the unique id of 'build_fabric' command which is to be used in creating the dependency graph */ - const ShellCommandId& build_fabric_id = shell.command(std::string("build_fabric")); + /* Get the unique id of 'build_fabric' command which is to be used in creating + * the dependency graph */ + const ShellCommandId& build_fabric_id = + shell.command(std::string("build_fabric")); /* Add a new class of commands */ - ShellCommandClassId openfpga_sdc_cmd_class = shell.add_command_class("FPGA-SDC"); + ShellCommandClassId openfpga_sdc_cmd_class = + shell.add_command_class("FPGA-SDC"); - /******************************** - * Command 'write_pnr_sdc' + /******************************** + * Command 'write_pnr_sdc' */ /* The 'write_pnr_sdc' command should NOT be executed before 'build_fabric' */ std::vector pnr_sdc_cmd_dependency; pnr_sdc_cmd_dependency.push_back(build_fabric_id); - add_openfpga_write_pnr_sdc_command(shell, - openfpga_sdc_cmd_class, + add_openfpga_write_pnr_sdc_command(shell, openfpga_sdc_cmd_class, pnr_sdc_cmd_dependency); - /******************************** - * Command 'write_configuration_chain_sdc' + /******************************** + * Command 'write_configuration_chain_sdc' */ - /* The 'write_configuration_chain_sdc' command should NOT be executed before 'build_fabric' */ + /* The 'write_configuration_chain_sdc' command should NOT be executed before + * 'build_fabric' */ std::vector cc_sdc_cmd_dependency; cc_sdc_cmd_dependency.push_back(build_fabric_id); - add_openfpga_write_configuration_chain_sdc_command(shell, - openfpga_sdc_cmd_class, - cc_sdc_cmd_dependency); + add_openfpga_write_configuration_chain_sdc_command( + shell, openfpga_sdc_cmd_class, cc_sdc_cmd_dependency); - /******************************** - * Command 'write_sdc_disable_timing_configure_ports' + /******************************** + * Command 'write_sdc_disable_timing_configure_ports' */ - /* The 'write_sdc_disable_timing_configure_ports' command should NOT be executed before 'build_fabric' */ + /* The 'write_sdc_disable_timing_configure_ports' command should NOT be + * executed before 'build_fabric' */ std::vector config_port_sdc_cmd_dependency; config_port_sdc_cmd_dependency.push_back(build_fabric_id); - add_openfpga_write_sdc_disable_timing_configure_ports_command(shell, - openfpga_sdc_cmd_class, - config_port_sdc_cmd_dependency); + add_openfpga_write_sdc_disable_timing_configure_ports_command( + shell, openfpga_sdc_cmd_class, config_port_sdc_cmd_dependency); - /******************************** - * Command 'write_analysis_sdc' + /******************************** + * Command 'write_analysis_sdc' */ - /* The 'write_analysis_sdc' command should NOT be executed before 'build_fabric' */ + /* The 'write_analysis_sdc' command should NOT be executed before + * 'build_fabric' */ std::vector analysis_sdc_cmd_dependency; analysis_sdc_cmd_dependency.push_back(build_fabric_id); - add_openfpga_write_analysis_sdc_command(shell, - openfpga_sdc_cmd_class, + add_openfpga_write_analysis_sdc_command(shell, openfpga_sdc_cmd_class, analysis_sdc_cmd_dependency); - -} +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_sdc_command.h b/openfpga/src/base/openfpga_sdc_command.h index 9fbeb42a5..5ddeb29e7 100644 --- a/openfpga/src/base/openfpga_sdc_command.h +++ b/openfpga/src/base/openfpga_sdc_command.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "shell.h" #include "openfpga_context.h" +#include "shell.h" /******************************************************************** * Function declaration @@ -14,7 +14,7 @@ /* begin namespace openfpga */ namespace openfpga { -void add_openfpga_sdc_commands(openfpga::Shell& shell); +void add_openfpga_sdc_commands(openfpga::Shell& shell); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_setup_command.cpp b/openfpga/src/base/openfpga_setup_command.cpp index e61d7f8d6..50719d026 100644 --- a/openfpga/src/base/openfpga_setup_command.cpp +++ b/openfpga/src/base/openfpga_setup_command.cpp @@ -1,38 +1,41 @@ /******************************************************************** - * Add commands to the OpenFPGA shell interface, + * Add commands to the OpenFPGA shell interface, * in purpose of setting up OpenFPGA core engine, including: * - read_openfpga_arch : read OpenFPGA architecture file *******************************************************************/ -#include "openfpga_read_arch.h" -#include "openfpga_link_arch.h" -#include "openfpga_pb_pin_fixup.h" -#include "openfpga_lut_truth_table_fixup.h" +#include "openfpga_setup_command.h" + #include "check_netlist_naming_conflict.h" #include "openfpga_build_fabric.h" -#include "openfpga_write_gsb.h" +#include "openfpga_link_arch.h" +#include "openfpga_lut_truth_table_fixup.h" +#include "openfpga_pb_pin_fixup.h" #include "openfpga_pcf2place.h" -#include "openfpga_setup_command.h" +#include "openfpga_read_arch.h" +#include "openfpga_write_gsb.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** * - Add a command to Shell environment: read_openfpga_arch - * - Add associated options + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_read_arch_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id) { +static ShellCommandId add_openfpga_read_arch_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id) { Command shell_cmd("read_openfpga_arch"); /* Add an option '--file' in short '-f'*/ - CommandOptionId opt_arch_file = shell_cmd.add_option("file", true, "file path to the architecture XML"); + CommandOptionId opt_arch_file = + shell_cmd.add_option("file", true, "file path to the architecture XML"); shell_cmd.set_option_short_name(opt_arch_file, "f"); shell_cmd.set_option_require_value(opt_arch_file, openfpga::OPT_STRING); /* Add command 'read_openfpga_arch' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "read OpenFPGA architecture file"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, "read OpenFPGA architecture file"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, read_arch); @@ -41,21 +44,23 @@ ShellCommandId add_openfpga_read_arch_command(openfpga::Shell& /******************************************************************** * - Add a command to Shell environment: write_openfpga_arch - * - Add associated options + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_write_arch_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_arch_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_openfpga_arch"); /* Add an option '--file' in short '-f'*/ - CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to the architecture XML"); + CommandOptionId opt_file = + shell_cmd.add_option("file", true, "file path to the 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_arch' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "write OpenFPGA architecture file"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, "write OpenFPGA architecture file"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_const_execute_function(shell_cmd_id, write_arch); @@ -67,21 +72,23 @@ ShellCommandId add_openfpga_write_arch_command(openfpga::Shell& /******************************************************************** * - Add a command to Shell environment: read_openfpga_simulation_setting - * - Add associated options + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_read_simulation_setting_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id) { +static ShellCommandId add_openfpga_read_simulation_setting_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id) { Command shell_cmd("read_openfpga_simulation_setting"); /* Add an option '--file' in short '-f'*/ - CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to the simulation setting XML"); + CommandOptionId opt_file = shell_cmd.add_option( + "file", true, "file path to the simulation setting 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_arch' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "read OpenFPGA simulation setting file"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, "read OpenFPGA simulation setting file"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, read_simulation_setting); @@ -90,23 +97,26 @@ ShellCommandId add_openfpga_read_simulation_setting_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_simulation_setting_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_openfpga_simulation_setting"); /* Add an option '--file' in short '-f'*/ - CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to the simulation setting XML"); + CommandOptionId opt_file = shell_cmd.add_option( + "file", true, "file path to the simulation setting 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_arch' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "write OpenFPGA simulation setting file"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, "write OpenFPGA simulation setting file"); shell.set_command_class(shell_cmd_id, cmd_class_id); - shell.set_command_const_execute_function(shell_cmd_id, write_simulation_setting); + shell.set_command_const_execute_function(shell_cmd_id, + write_simulation_setting); /* Add command dependency to the Shell */ shell.set_command_dependency(shell_cmd_id, dependent_cmds); @@ -116,21 +126,23 @@ ShellCommandId add_openfpga_write_simulation_setting_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id) { +static ShellCommandId add_openfpga_read_bitstream_setting_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id) { Command shell_cmd("read_openfpga_bitstream_setting"); /* Add an option '--file' in short '-f'*/ - CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to the bitstream setting XML"); + CommandOptionId opt_file = shell_cmd.add_option( + "file", true, "file path to the bitstream setting 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_bitstream_setting' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "read OpenFPGA bitstream setting file"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, "read OpenFPGA bitstream setting file"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, read_bitstream_setting); @@ -139,23 +151,26 @@ ShellCommandId add_openfpga_read_bitstream_setting_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_bitstream_setting_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_openfpga_bitstream_setting"); /* Add an option '--file' in short '-f'*/ - CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to the bitstream setting XML"); + CommandOptionId opt_file = shell_cmd.add_option( + "file", true, "file path to the bitstream setting 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_bitstream_setting' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "write OpenFPGA bitstream setting file"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, "write OpenFPGA bitstream setting file"); shell.set_command_class(shell_cmd_id, cmd_class_id); - shell.set_command_const_execute_function(shell_cmd_id, write_bitstream_setting); + shell.set_command_const_execute_function(shell_cmd_id, + write_bitstream_setting); /* Add command dependency to the Shell */ shell.set_command_dependency(shell_cmd_id, dependent_cmds); @@ -165,27 +180,31 @@ ShellCommandId add_openfpga_write_bitstream_setting_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_link_arch_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("link_openfpga_arch"); /* Add an option '--activity_file'*/ - CommandOptionId opt_act_file = shell_cmd.add_option("activity_file", false, "file path to the signal activity"); + CommandOptionId opt_act_file = shell_cmd.add_option( + "activity_file", false, "file path to the signal activity"); shell_cmd.set_option_require_value(opt_act_file, openfpga::OPT_STRING); /* Add an option '--sort_gsb_chan_node_in_edges'*/ - shell_cmd.add_option("sort_gsb_chan_node_in_edges", false, "Sort all the incoming edges for each routing track output node in General Switch Blocks (GSBs)"); + shell_cmd.add_option("sort_gsb_chan_node_in_edges", false, + "Sort all the incoming edges for each routing track " + "output node in General Switch Blocks (GSBs)"); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Show verbose outputs"); - + /* Add command 'link_openfpga_arch' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Bind OpenFPGA architecture to VPR"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, "Bind OpenFPGA architecture to VPR"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, link_arch); @@ -197,16 +216,17 @@ ShellCommandId add_openfpga_link_arch_command(openfpga::Shell& /******************************************************************** * - Add a command to Shell environment: write_gsb_to_xml - * - Add associated options + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_write_gsb_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_gsb_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_gsb_to_xml"); /* Add an option '--file' in short '-f'*/ - CommandOptionId opt_file = shell_cmd.add_option("file", true, "path to the directory that stores the XML files"); + CommandOptionId opt_file = shell_cmd.add_option( + "file", true, "path to the directory that stores the XML files"); shell_cmd.set_option_short_name(opt_file, "f"); shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); @@ -214,21 +234,33 @@ ShellCommandId add_openfpga_write_gsb_command(openfpga::Shell& shell_cmd.add_option("unique", false, "Only output unique GSB blocks"); /* Add an option '--exclude_rr_info' */ - shell_cmd.add_option("exclude_rr_info", false, "Exclude routing resource graph information from output files, e.g., node id as well as other attributes. This is useful to check the connection inside GSBs purely."); + shell_cmd.add_option("exclude_rr_info", false, + "Exclude routing resource graph information from output " + "files, e.g., node id as well as other attributes. This " + "is useful to check the connection inside GSBs purely."); /* Add an option '--exclude'*/ - CommandOptionId opt_exclude = shell_cmd.add_option("exclude", false, "Exclude part of the GSB data to be outputted. Can be [``sb``|``cbx``|``cby``]. Users can exclude multiple parts by using a splitter ``,``"); + CommandOptionId opt_exclude = + shell_cmd.add_option("exclude", false, + "Exclude part of the GSB data to be outputted. Can be " + "[``sb``|``cbx``|``cby``]. Users can exclude multiple " + "parts by using a splitter ``,``"); shell_cmd.set_option_require_value(opt_exclude, openfpga::OPT_STRING); /* Add an option '--gsb_names'*/ - CommandOptionId opt_gsb_names = shell_cmd.add_option("gsb_names", false, "Specify the name of GSB to be outputted. Users can specify multiple GSBs by using a splitter ``,``"); + CommandOptionId opt_gsb_names = + shell_cmd.add_option("gsb_names", false, + "Specify the name of GSB to be outputted. Users can " + "specify multiple GSBs by using a splitter ``,``"); shell_cmd.set_option_require_value(opt_gsb_names, openfpga::OPT_STRING); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Show verbose outputs"); /* Add command 'write_openfpga_arch' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "write internal structures of General Switch Blocks to XML file"); + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, + "write internal structures of General Switch Blocks to XML file"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_const_execute_function(shell_cmd_id, write_gsb); @@ -240,27 +272,31 @@ ShellCommandId add_openfpga_write_gsb_command(openfpga::Shell& /******************************************************************** * - Add a command to Shell environment: check_netlist_naming_conflict - * - Add associated options + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_check_netlist_naming_conflict_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { - +static ShellCommandId add_openfpga_check_netlist_naming_conflict_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("check_netlist_naming_conflict"); /* Add an option '--fix' */ shell_cmd.add_option("fix", false, "Apply correction to any conflicts found"); /* Add an option '--report' */ - CommandOptionId opt_rpt = shell_cmd.add_option("report", false, "Output a report file about what any correction applied"); + CommandOptionId opt_rpt = shell_cmd.add_option( + "report", false, "Output a report file about what any correction applied"); shell_cmd.set_option_require_value(opt_rpt, openfpga::OPT_STRING); /* Add command 'check_netlist_naming_conflict' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Check any block/net naming in users' BLIF netlist violates the syntax of fabric generator"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, + "Check any block/net naming in users' BLIF netlist " + "violates the syntax of fabric generator"); shell.set_command_class(shell_cmd_id, cmd_class_id); - shell.set_command_execute_function(shell_cmd_id, check_netlist_naming_conflict); + shell.set_command_execute_function(shell_cmd_id, + check_netlist_naming_conflict); /* Add command dependency to the Shell */ shell.set_command_dependency(shell_cmd_id, dependent_cmds); @@ -270,21 +306,22 @@ ShellCommandId add_openfpga_check_netlist_naming_conflict_command(openfpga::Shel /******************************************************************** * - Add a command to Shell environment: pb_pin_fixup - * - Add associated options + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_pb_pin_fixup_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { - +static ShellCommandId add_openfpga_pb_pin_fixup_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("pb_pin_fixup"); /* 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, "Fix up the packing results due to pin swapping during routing stage"); + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, + "Fix up the packing results due to pin swapping during routing stage"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, pb_pin_fixup); @@ -296,20 +333,22 @@ ShellCommandId add_openfpga_pb_pin_fixup_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { - +static ShellCommandId add_openfpga_lut_truth_table_fixup_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("lut_truth_table_fixup"); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Show verbose outputs"); /* Add command 'lut_truth_table_fixup' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Fix up the truth table of Look-Up Tables due to pin swapping during packing stage"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, + "Fix up the truth table of Look-Up Tables due to pin " + "swapping during packing stage"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, lut_truth_table_fixup); @@ -321,41 +360,50 @@ ShellCommandId add_openfpga_lut_truth_table_fixup_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { - +static ShellCommandId add_openfpga_build_fabric_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("build_fabric"); /* Add an option '--frame_view' */ - shell_cmd.add_option("frame_view", false, "Build only frame view of the fabric (nets are skipped)"); + shell_cmd.add_option( + "frame_view", false, + "Build only frame view of the fabric (nets are skipped)"); /* Add an option '--compress_routing' */ - shell_cmd.add_option("compress_routing", false, "Compress the number of unique routing modules by identifying the unique GSBs"); + shell_cmd.add_option("compress_routing", false, + "Compress the number of unique routing modules by " + "identifying the unique GSBs"); /* Add an option '--duplicate_grid_pin' */ - shell_cmd.add_option("duplicate_grid_pin", false, "Duplicate the pins on the same side of a grid"); + shell_cmd.add_option("duplicate_grid_pin", false, + "Duplicate the pins on the same side of a grid"); /* Add an option '--load_fabric_key' */ - CommandOptionId opt_load_fkey = shell_cmd.add_option("load_fabric_key", false, "load the fabric key from the given file"); + CommandOptionId opt_load_fkey = shell_cmd.add_option( + "load_fabric_key", false, "load the fabric key from the given file"); shell_cmd.set_option_require_value(opt_load_fkey, openfpga::OPT_STRING); /* Add an option '--write_fabric_key' */ - CommandOptionId opt_write_fkey = shell_cmd.add_option("write_fabric_key", false, "output current fabric key to a file"); + CommandOptionId opt_write_fkey = shell_cmd.add_option( + "write_fabric_key", false, "output current fabric key to a file"); shell_cmd.set_option_require_value(opt_write_fkey, openfpga::OPT_STRING); /* Add an option '--generate_random_fabric_key' */ - shell_cmd.add_option("generate_random_fabric_key", false, "Create a random fabric key which will shuffle the memory address for encryption purpose"); + shell_cmd.add_option("generate_random_fabric_key", false, + "Create a random fabric key which will shuffle the " + "memory address for encryption purpose"); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Show verbose outputs"); /* Add command 'compact_routing_hierarchy' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Build the FPGA fabric in a graph of modules"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, "Build the FPGA fabric in a graph of modules"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, build_fabric); @@ -367,32 +415,36 @@ ShellCommandId add_openfpga_build_fabric_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { - +static ShellCommandId add_openfpga_write_fabric_hierarchy_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_fabric_hierarchy"); /* Add an option '--file' */ - CommandOptionId opt_file = shell_cmd.add_option("file", true, "Specify the file name to write the hierarchy to"); + CommandOptionId opt_file = shell_cmd.add_option( + "file", true, "Specify the file name to write the hierarchy to"); shell_cmd.set_option_short_name(opt_file, "f"); shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); /* Add an option '--depth' */ - CommandOptionId opt_depth = shell_cmd.add_option("depth", false, "Specify the depth of hierarchy to which the writer should stop"); + CommandOptionId opt_depth = shell_cmd.add_option( + "depth", false, + "Specify the depth of hierarchy to which the writer should stop"); shell_cmd.set_option_require_value(opt_depth, openfpga::OPT_INT); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Show verbose outputs"); /* Add command 'write_fabric_hierarchy' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Write the hierarchy of FPGA fabric graph to a plain-text file"); + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, "Write the hierarchy of FPGA fabric graph to a plain-text file"); shell.set_command_class(shell_cmd_id, cmd_class_id); - shell.set_command_const_execute_function(shell_cmd_id, write_fabric_hierarchy); + shell.set_command_const_execute_function(shell_cmd_id, + write_fabric_hierarchy); /* Add command dependency to the Shell */ shell.set_command_dependency(shell_cmd_id, dependent_cmds); @@ -402,28 +454,33 @@ ShellCommandId add_openfpga_write_fabric_hierarchy_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_fabric_io_info_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_fabric_io_info"); /* Add an option '--file' in short '-f'*/ - CommandOptionId opt_file = shell_cmd.add_option("file", true, "file path to output the I/O information"); + CommandOptionId opt_file = shell_cmd.add_option( + "file", true, "file path to output the I/O information"); shell_cmd.set_option_short_name(opt_file, "f"); shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); /* Add an option '--no_time_stamp' */ - shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files"); + shell_cmd.add_option("no_time_stamp", false, + "Do not print time stamp in output files"); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); /* Add command the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Write the I/O information, e.g., locations and similar attributes, to a file"); + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, + "Write the I/O information, e.g., locations and similar " + "attributes, to a file"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, write_fabric_io_info); @@ -435,42 +492,52 @@ ShellCommandId add_openfpga_write_fabric_io_info_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id) { +static ShellCommandId add_openfpga_pcf2place_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id) { Command shell_cmd("pcf2place"); /* Add an option '--pcf'*/ - CommandOptionId opt_pcf_file = shell_cmd.add_option("pcf", true, "file path to the user pin constraint"); + CommandOptionId opt_pcf_file = + shell_cmd.add_option("pcf", true, "file path to the user pin constraint"); shell_cmd.set_option_require_value(opt_pcf_file, openfpga::OPT_STRING); /* Add an option '--blif'*/ - CommandOptionId opt_blif_file = shell_cmd.add_option("blif", true, "file path to the synthesized netlist (.blif)"); + CommandOptionId opt_blif_file = shell_cmd.add_option( + "blif", true, "file path to the synthesized netlist (.blif)"); shell_cmd.set_option_require_value(opt_blif_file, openfpga::OPT_STRING); /* Add an option '--fpga_io_map'*/ - CommandOptionId opt_fpga_io_map_file = shell_cmd.add_option("fpga_io_map", true, "file path to FPGA I/O location map (.xml)"); - shell_cmd.set_option_require_value(opt_fpga_io_map_file, openfpga::OPT_STRING); + CommandOptionId opt_fpga_io_map_file = shell_cmd.add_option( + "fpga_io_map", true, "file path to FPGA I/O location map (.xml)"); + shell_cmd.set_option_require_value(opt_fpga_io_map_file, + openfpga::OPT_STRING); /* Add an option '--pin_table'*/ - CommandOptionId opt_pin_table_file = shell_cmd.add_option("pin_table", true, "file path to the pin table (.csv)"); + CommandOptionId opt_pin_table_file = shell_cmd.add_option( + "pin_table", true, "file path to the pin table (.csv)"); shell_cmd.set_option_require_value(opt_pin_table_file, openfpga::OPT_STRING); /* Add an option '--fpga_fix_pins'*/ - CommandOptionId opt_fpga_fix_pins_file = shell_cmd.add_option("fpga_fix_pins", true, "file path to the output fix-pin placement file (.place)"); - shell_cmd.set_option_require_value(opt_fpga_fix_pins_file, openfpga::OPT_STRING); + CommandOptionId opt_fpga_fix_pins_file = shell_cmd.add_option( + "fpga_fix_pins", true, + "file path to the output fix-pin placement file (.place)"); + shell_cmd.set_option_require_value(opt_fpga_fix_pins_file, + openfpga::OPT_STRING); /* Add an option '--no_time_stamp' */ - shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files"); + shell_cmd.add_option("no_time_stamp", false, + "Do not print time stamp in output files"); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); /* Add command to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "Convert user Pin Constraint File (.pcf) to an placement file"); + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, "Convert user Pin Constraint File (.pcf) to an placement file"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, pcf2place_wrapper); @@ -478,65 +545,70 @@ ShellCommandId add_openfpga_pcf2place_command(openfpga::Shell& } void add_openfpga_setup_commands(openfpga::Shell& shell) { - /* Get the unique id of 'vpr' command which is to be used in creating the dependency graph */ + /* Get the unique id of 'vpr' command which is to be used in creating the + * dependency graph */ const ShellCommandId& vpr_cmd_id = shell.command(std::string("vpr")); /* Add a new class of commands */ - ShellCommandClassId openfpga_setup_cmd_class = shell.add_command_class("OpenFPGA setup"); + ShellCommandClassId openfpga_setup_cmd_class = + shell.add_command_class("OpenFPGA setup"); - /******************************** - * Command 'pcf2place' + /******************************** + * Command 'pcf2place' */ add_openfpga_pcf2place_command(shell, openfpga_setup_cmd_class); - /******************************** - * Command 'read_openfpga_arch' + /******************************** + * Command 'read_openfpga_arch' */ - ShellCommandId read_arch_cmd_id = add_openfpga_read_arch_command(shell, - openfpga_setup_cmd_class); + ShellCommandId read_arch_cmd_id = + add_openfpga_read_arch_command(shell, openfpga_setup_cmd_class); - /******************************** - * Command 'write_openfpga_arch' + /******************************** + * Command 'write_openfpga_arch' */ - /* The 'write_openfpga_arch' command should NOT be executed before 'read_openfpga_arch' */ + /* The 'write_openfpga_arch' command should NOT be executed before + * 'read_openfpga_arch' */ std::vector write_arch_dependent_cmds(1, read_arch_cmd_id); - add_openfpga_write_arch_command(shell, - openfpga_setup_cmd_class, + add_openfpga_write_arch_command(shell, openfpga_setup_cmd_class, write_arch_dependent_cmds); - /******************************** - * Command 'read_openfpga_simulation_setting' + /******************************** + * Command 'read_openfpga_simulation_setting' */ - ShellCommandId read_sim_setting_cmd_id = add_openfpga_read_simulation_setting_command(shell, - openfpga_setup_cmd_class); + ShellCommandId read_sim_setting_cmd_id = + add_openfpga_read_simulation_setting_command(shell, + openfpga_setup_cmd_class); - /******************************** - * Command 'write_openfpga_simulation_setting' + /******************************** + * Command 'write_openfpga_simulation_setting' */ - /* The 'write_openfpga_simulation_setting' command should NOT be executed before 'read_openfpga_simulation_setting' */ - std::vector write_sim_setting_dependent_cmds(1, read_sim_setting_cmd_id); - add_openfpga_write_simulation_setting_command(shell, - openfpga_setup_cmd_class, - write_sim_setting_dependent_cmds); + /* The 'write_openfpga_simulation_setting' command should NOT be executed + * before 'read_openfpga_simulation_setting' */ + std::vector write_sim_setting_dependent_cmds( + 1, read_sim_setting_cmd_id); + add_openfpga_write_simulation_setting_command( + shell, openfpga_setup_cmd_class, write_sim_setting_dependent_cmds); - /******************************** - * Command 'read_openfpga_bitstream_setting' + /******************************** + * Command 'read_openfpga_bitstream_setting' */ - ShellCommandId read_bitstream_setting_cmd_id = add_openfpga_read_bitstream_setting_command(shell, - openfpga_setup_cmd_class); + ShellCommandId read_bitstream_setting_cmd_id = + add_openfpga_read_bitstream_setting_command(shell, + openfpga_setup_cmd_class); - /******************************** - * Command 'write_openfpga_bitstream_setting' + /******************************** + * Command 'write_openfpga_bitstream_setting' */ - /* The 'write_openfpga_bitstream_setting' command should NOT be executed before 'read_openfpga_bitstream_setting' */ - std::vector write_bitstream_setting_dependent_cmds(1, read_bitstream_setting_cmd_id); - add_openfpga_write_bitstream_setting_command(shell, - openfpga_setup_cmd_class, - write_bitstream_setting_dependent_cmds); + /* The 'write_openfpga_bitstream_setting' command should NOT be executed + * before 'read_openfpga_bitstream_setting' */ + std::vector write_bitstream_setting_dependent_cmds( + 1, read_bitstream_setting_cmd_id); + add_openfpga_write_bitstream_setting_command( + shell, openfpga_setup_cmd_class, write_bitstream_setting_dependent_cmds); - - /******************************** - * Command 'link_openfpga_arch' + /******************************** + * Command 'link_openfpga_arch' */ /* The 'link_openfpga_arch' command should NOT be executed before 'vpr' */ std::vector link_arch_dependent_cmds; @@ -545,78 +617,79 @@ void add_openfpga_setup_commands(openfpga::Shell& shell) { */ link_arch_dependent_cmds.push_back(read_sim_setting_cmd_id); link_arch_dependent_cmds.push_back(vpr_cmd_id); - ShellCommandId link_arch_cmd_id = add_openfpga_link_arch_command(shell, - openfpga_setup_cmd_class, - link_arch_dependent_cmds); + ShellCommandId link_arch_cmd_id = add_openfpga_link_arch_command( + shell, openfpga_setup_cmd_class, link_arch_dependent_cmds); - /******************************** - * Command 'write_gsb' + /******************************** + * Command 'write_gsb' + */ + /* The 'write_gsb' command should NOT be executed before 'link_openfpga_arch' */ - /* The 'write_gsb' command should NOT be executed before 'link_openfpga_arch' */ std::vector write_gsb_dependent_cmds; write_gsb_dependent_cmds.push_back(link_arch_cmd_id); - add_openfpga_write_gsb_command(shell, - openfpga_setup_cmd_class, + add_openfpga_write_gsb_command(shell, openfpga_setup_cmd_class, write_gsb_dependent_cmds); - /******************************************* + /******************************************* * Command 'check_netlist_naming_conflict' - */ - /* The 'check_netlist_naming_conflict' command should NOT be executed before 'vpr' */ + */ + /* The 'check_netlist_naming_conflict' command should NOT be executed before + * 'vpr' */ std::vector nlist_naming_dependent_cmds; nlist_naming_dependent_cmds.push_back(vpr_cmd_id); - add_openfpga_check_netlist_naming_conflict_command(shell, - openfpga_setup_cmd_class, - nlist_naming_dependent_cmds); + add_openfpga_check_netlist_naming_conflict_command( + shell, openfpga_setup_cmd_class, nlist_naming_dependent_cmds); - /******************************** - * Command 'pb_pin_fixup' + /******************************** + * Command 'pb_pin_fixup' */ - /* The 'pb_pin_fixup' command should NOT be executed before 'read_openfpga_arch' and 'vpr' */ + /* The 'pb_pin_fixup' command should NOT be executed before + * 'read_openfpga_arch' and 'vpr' */ std::vector pb_pin_fixup_dependent_cmds; pb_pin_fixup_dependent_cmds.push_back(read_arch_cmd_id); pb_pin_fixup_dependent_cmds.push_back(vpr_cmd_id); - add_openfpga_pb_pin_fixup_command(shell, - openfpga_setup_cmd_class, + add_openfpga_pb_pin_fixup_command(shell, openfpga_setup_cmd_class, pb_pin_fixup_dependent_cmds); - /******************************** - * Command 'lut_truth_table_fixup' + /******************************** + * Command 'lut_truth_table_fixup' */ - /* The 'lut_truth_table_fixup' command should NOT be executed before 'read_openfpga_arch' and 'vpr' */ + /* The 'lut_truth_table_fixup' command should NOT be executed before + * 'read_openfpga_arch' and 'vpr' */ std::vector lut_tt_fixup_dependent_cmds; lut_tt_fixup_dependent_cmds.push_back(read_arch_cmd_id); lut_tt_fixup_dependent_cmds.push_back(vpr_cmd_id); - add_openfpga_lut_truth_table_fixup_command(shell, - openfpga_setup_cmd_class, + add_openfpga_lut_truth_table_fixup_command(shell, openfpga_setup_cmd_class, lut_tt_fixup_dependent_cmds); - /******************************** - * Command 'build_fabric' + /******************************** + * Command 'build_fabric' */ - /* The 'build_fabric' command should NOT be executed before 'link_openfpga_arch' */ + /* The 'build_fabric' command should NOT be executed before + * 'link_openfpga_arch' */ std::vector build_fabric_dependent_cmds; build_fabric_dependent_cmds.push_back(link_arch_cmd_id); - ShellCommandId build_fabric_cmd_id = add_openfpga_build_fabric_command(shell, - openfpga_setup_cmd_class, - build_fabric_dependent_cmds); + ShellCommandId build_fabric_cmd_id = add_openfpga_build_fabric_command( + shell, openfpga_setup_cmd_class, build_fabric_dependent_cmds); - /******************************** - * Command 'write_fabric_hierarchy' + /******************************** + * Command 'write_fabric_hierarchy' */ - /* The 'write_fabric_hierarchy' command should NOT be executed before 'build_fabric' */ + /* The 'write_fabric_hierarchy' command should NOT be executed before + * 'build_fabric' */ std::vector write_fabric_hie_dependent_cmds; write_fabric_hie_dependent_cmds.push_back(build_fabric_cmd_id); - add_openfpga_write_fabric_hierarchy_command(shell, - openfpga_setup_cmd_class, + add_openfpga_write_fabric_hierarchy_command(shell, openfpga_setup_cmd_class, write_fabric_hie_dependent_cmds); - /******************************** - * Command 'write_fabric_io_info' + /******************************** + * Command 'write_fabric_io_info' */ - /* The 'write_fabric_io_info' command should NOT be executed before 'build_fabric' */ + /* The 'write_fabric_io_info' command should NOT be executed before + * 'build_fabric' */ std::vector cmd_dependency_write_fabric_io_info; cmd_dependency_write_fabric_io_info.push_back(build_fabric_cmd_id); - add_openfpga_write_fabric_io_info_command(shell, openfpga_setup_cmd_class, cmd_dependency_write_fabric_io_info); -} + add_openfpga_write_fabric_io_info_command( + shell, openfpga_setup_cmd_class, cmd_dependency_write_fabric_io_info); +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_setup_command.h b/openfpga/src/base/openfpga_setup_command.h index 03d4220f5..b6923af22 100644 --- a/openfpga/src/base/openfpga_setup_command.h +++ b/openfpga/src/base/openfpga_setup_command.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "shell.h" #include "openfpga_context.h" +#include "shell.h" /******************************************************************** * Function declaration @@ -14,7 +14,7 @@ /* begin namespace openfpga */ namespace openfpga { -void add_openfpga_setup_commands(openfpga::Shell& shell); +void add_openfpga_setup_commands(openfpga::Shell& shell); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_spice.cpp b/openfpga/src/base/openfpga_spice.cpp index c1b418835..f18ae76c5 100644 --- a/openfpga/src/base/openfpga_spice.cpp +++ b/openfpga/src/base/openfpga_spice.cpp @@ -2,14 +2,13 @@ * This file includes functions to compress the hierachy of routing architecture *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgashell library */ #include "command_exit_codes.h" - -#include "spice_api.h" #include "openfpga_spice.h" +#include "spice_api.h" /* Include global variables of VPR */ #include "globals.h" @@ -20,33 +19,31 @@ namespace openfpga { /******************************************************************** * A wrapper function to call the fabric SPICE generator of FPGA-SPICE *******************************************************************/ -int write_fabric_spice(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - +int write_fabric_spice(OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_output_dir = cmd.option("file"); - CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); + CommandOptionId opt_explicit_port_mapping = + cmd.option("explicit_port_mapping"); CommandOptionId opt_verbose = cmd.option("verbose"); - /* This is an intermediate data structure which is designed to modularize the FPGA-SPICE - * Keep it independent from any other outside data structures + /* This is an intermediate data structure which is designed to modularize the + * FPGA-SPICE Keep it independent from any other outside data structures */ FabricSpiceOption options; options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir)); - options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); + options.set_explicit_port_mapping( + cmd_context.option_enable(cmd, opt_explicit_port_mapping)); options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); options.set_compress_routing(openfpga_ctx.flow_manager().compress_routing()); - + int status = CMD_EXEC_SUCCESS; - status = fpga_fabric_spice(openfpga_ctx.module_graph(), - openfpga_ctx.mutable_spice_netlists(), - openfpga_ctx.arch(), - openfpga_ctx.mux_lib(), - g_vpr_ctx.device(), - openfpga_ctx.vpr_device_annotation(), - openfpga_ctx.device_rr_gsb(), - options); + status = fpga_fabric_spice( + openfpga_ctx.module_graph(), openfpga_ctx.mutable_spice_netlists(), + openfpga_ctx.arch(), openfpga_ctx.mux_lib(), g_vpr_ctx.device(), + openfpga_ctx.vpr_device_annotation(), openfpga_ctx.device_rr_gsb(), + options); return status; -} +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_spice.h b/openfpga/src/base/openfpga_spice.h index c5f47b66a..83d3bcdb2 100644 --- a/openfpga/src/base/openfpga_spice.h +++ b/openfpga/src/base/openfpga_spice.h @@ -15,8 +15,8 @@ /* begin namespace openfpga */ namespace openfpga { -int write_fabric_spice(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); +int write_fabric_spice(OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_spice_command.cpp b/openfpga/src/base/openfpga_spice_command.cpp index ae6ff8e92..d3c512311 100644 --- a/openfpga/src/base/openfpga_spice_command.cpp +++ b/openfpga/src/base/openfpga_spice_command.cpp @@ -1,48 +1,60 @@ /******************************************************************** - * Add commands to the OpenFPGA shell interface, + * Add commands to the OpenFPGA shell interface, * in purpose of generate SPICE netlists modeling the full FPGA fabric * This is one of the core engine of openfpga, including: - * - generate_fabric_spice : generate Verilog netlists about FPGA fabric - * - TODO: generate_spice_top_testbench : generate SPICE testbenches for top-level module + * - generate_fabric_spice : generate Verilog netlists about FPGA fabric + * - TODO: generate_spice_top_testbench : generate SPICE testbenches for + *top-level module * - TODO: generate_spice_grid_testbench : generate SPICE testbenches for grids - * - TODO: generate_spice_cb_testbench : generate SPICE testbenches for connection blocks - * - TODO: generate_spice_sb_testbench : generate SPICE testbenches for switch blocks - * - TODO: generate_spice_lut_testbench : generate SPICE testbenches for Look-Up Tables - * - TODO: generate_spice_hard_logic_testbench : generate SPICE testbenches for all the hard logics - * - TODO: generate_spice_local_routing_testbench : generate SPICE testbenches for local routing - * - TODO: generate_spice_cb_routing_testbench : generate SPICE testbenches for routing circuit inside connection blocks - * - TODO: generate_spice_sb_routing_testbench : generate SPICE testbenches for routing circuit inside switch blocks + * - TODO: generate_spice_cb_testbench : generate SPICE testbenches for + *connection blocks + * - TODO: generate_spice_sb_testbench : generate SPICE testbenches for switch + *blocks + * - TODO: generate_spice_lut_testbench : generate SPICE testbenches for Look-Up + *Tables + * - TODO: generate_spice_hard_logic_testbench : generate SPICE testbenches for + *all the hard logics + * - TODO: generate_spice_local_routing_testbench : generate SPICE testbenches + *for local routing + * - TODO: generate_spice_cb_routing_testbench : generate SPICE testbenches for + *routing circuit inside connection blocks + * - TODO: generate_spice_sb_routing_testbench : generate SPICE testbenches for + *routing circuit inside switch blocks *******************************************************************/ -#include "openfpga_spice.h" #include "openfpga_spice_command.h" +#include "openfpga_spice.h" + /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * - Add a command to Shell environment: generate fabric Verilog - * - Add associated options + * - Add a command to Shell environment: generate fabric Verilog + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_write_fabric_spice_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_fabric_spice_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_fabric_spice"); /* Add an option '--file' in short '-f'*/ - CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for SPICE netlists"); + CommandOptionId output_opt = shell_cmd.add_option( + "file", true, "Specify the output directory for SPICE netlists"); shell_cmd.set_option_short_name(output_opt, "f"); shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); /* Add an option '--explicit_port_mapping' */ - shell_cmd.add_option("explicit_port_mapping", false, "Use explicit port mapping in Verilog netlists"); + shell_cmd.add_option("explicit_port_mapping", false, + "Use explicit port mapping in Verilog netlists"); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); - + /* Add command 'write_fabric_spice' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate SPICE netlists modeling full FPGA fabric"); + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, "generate SPICE netlists modeling full FPGA fabric"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, write_fabric_spice); @@ -53,26 +65,30 @@ ShellCommandId add_openfpga_write_fabric_spice_command(openfpga::Shell& shell) { - /* Get the unique id of 'build_fabric' command which is to be used in creating the dependency graph */ - const ShellCommandId& build_fabric_cmd_id = shell.command(std::string("build_fabric")); + /* Get the unique id of 'build_fabric' command which is to be used in creating + * the dependency graph */ + const ShellCommandId& build_fabric_cmd_id = + shell.command(std::string("build_fabric")); /* Add a new class of commands */ - ShellCommandClassId openfpga_spice_cmd_class = shell.add_command_class("FPGA-SPICE"); + ShellCommandClassId openfpga_spice_cmd_class = + shell.add_command_class("FPGA-SPICE"); - /******************************** - * Command 'write_fabric_spice' + /******************************** + * Command 'write_fabric_spice' */ - /* The 'write_fabric_spice' command should NOT be executed before 'build_fabric' */ + /* The 'write_fabric_spice' command should NOT be executed before + * 'build_fabric' */ std::vector fabric_spice_dependent_cmds; fabric_spice_dependent_cmds.push_back(build_fabric_cmd_id); - add_openfpga_write_fabric_spice_command(shell, - openfpga_spice_cmd_class, + add_openfpga_write_fabric_spice_command(shell, openfpga_spice_cmd_class, fabric_spice_dependent_cmds); - /******************************** - * TODO: Command 'write_spice_top_testbench' + /******************************** + * TODO: Command 'write_spice_top_testbench' */ - /* The command 'write_spice_top_testbench' should NOT be executed before 'build_fabric' */ -} + /* The command 'write_spice_top_testbench' should NOT be executed before + * 'build_fabric' */ +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_spice_command.h b/openfpga/src/base/openfpga_spice_command.h index 7262aa0b4..7d266d9d3 100644 --- a/openfpga/src/base/openfpga_spice_command.h +++ b/openfpga/src/base/openfpga_spice_command.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "shell.h" #include "openfpga_context.h" +#include "shell.h" /******************************************************************** * Function declaration @@ -14,7 +14,7 @@ /* begin namespace openfpga */ namespace openfpga { -void add_openfpga_spice_commands(openfpga::Shell& shell); +void add_openfpga_spice_commands(openfpga::Shell& shell); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_title.cpp b/openfpga/src/base/openfpga_title.cpp index 5635b4502..e789eed38 100644 --- a/openfpga/src/base/openfpga_title.cpp +++ b/openfpga/src/base/openfpga_title.cpp @@ -2,53 +2,86 @@ * This file includes the functions to create the title page * which introduces generality of OpenFPGA framework *******************************************************************/ -#include "vtr_log.h" - #include "openfpga_title.h" + #include "openfpga_version.h" +#include "vtr_log.h" /******************************************************************** * Generate a string of openfpga title introduction - * This is mainly used when launching OpenFPGA shell + * This is mainly used when launching OpenFPGA shell *******************************************************************/ std::string create_openfpga_title() { std::string title; title += std::string("\n"); - title += std::string(" ___ _____ ____ ____ _ \n"); - title += std::string(" / _ \\ _ __ ___ _ __ | ___| _ \\ / ___| / \\ \n"); - title += std::string(" | | | | '_ \\ / _ \\ '_ \\| |_ | |_) | | _ / _ \\ \n"); - title += std::string(" | |_| | |_) | __/ | | | _| | __/| |_| |/ ___ \\ \n"); - title += std::string(" \\___/| .__/ \\___|_| |_|_| |_| \\____/_/ \\_\\ \n"); - title += std::string(" |_| \n"); + title += std::string( + " ___ _____ ____ ____ _ \n"); + title += std::string( + " / _ \\ _ __ ___ _ __ | ___| _ \\ / ___| / \\ \n"); + title += std::string( + " | | | | '_ \\ / _ \\ '_ \\| |_ | |_) | | _ / _ \\ \n"); + title += std::string( + " | |_| | |_) | __/ | | | _| | __/| |_| |/ ___ \\ \n"); + title += std::string( + " \\___/| .__/ \\___|_| |_|_| |_| \\____/_/ \\_\\ \n"); + title += std::string( + " |_| \n"); title += std::string("\n"); - title += std::string(" OpenFPGA: An Open-source FPGA IP Generator\n"); - title += std::string(" Versatile Place and Route (VPR)\n"); + title += + std::string(" OpenFPGA: An Open-source FPGA IP Generator\n"); + title += + std::string(" Versatile Place and Route (VPR)\n"); title += std::string(" FPGA-Verilog\n"); title += std::string(" FPGA-SPICE\n"); title += std::string(" FPGA-SDC\n"); title += std::string(" FPGA-Bitstream\n"); title += std::string("\n"); - title += std::string(" This is a free software under the MIT License\n"); + title += + std::string(" This is a free software under the MIT License\n"); title += std::string("\n"); - title += std::string(" Copyright (c) 2018 LNIS - The University of Utah\n"); + title += std::string( + " Copyright (c) 2018 LNIS - The University of Utah\n"); title += std::string("\n"); - title += std::string("Permission is hereby granted, free of charge, to any person obtaining a copy\n"); - title += std::string("of this software and associated documentation files (the \"Software\"), to deal\n"); - title += std::string("in the Software without restriction, including without limitation the rights\n"); - title += std::string("to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n"); - title += std::string("copies of the Software, and to permit persons to whom the Software is\n"); - title += std::string("furnished to do so, subject to the following conditions:\n"); + title += std::string( + "Permission is hereby granted, free of charge, to any person obtaining a " + "copy\n"); + title += std::string( + "of this software and associated documentation files (the \"Software\"), " + "to deal\n"); + title += std::string( + "in the Software without restriction, including without limitation the " + "rights\n"); + title += std::string( + "to use, copy, modify, merge, publish, distribute, sublicense, and/or " + "sell\n"); + title += std::string( + "copies of the Software, and to permit persons to whom the Software is\n"); + title += + std::string("furnished to do so, subject to the following conditions:\n"); title += std::string("\n"); - title += std::string("The above copyright notice and this permission notice shall be included in\n"); + title += std::string( + "The above copyright notice and this permission notice shall be included " + "in\n"); title += std::string("all copies or substantial portions of the Software.\n"); title += std::string("\n"); - title += std::string("THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"); - title += std::string("IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"); - title += std::string("FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n"); - title += std::string("AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"); - title += std::string("LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n"); - title += std::string("OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n"); + title += std::string( + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS " + "OR\n"); + title += std::string( + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF " + "MERCHANTABILITY,\n"); + title += std::string( + "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL " + "THE\n"); + title += std::string( + "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"); + title += std::string( + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING " + "FROM,\n"); + title += std::string( + "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS " + "IN\n"); title += std::string("THE SOFTWARE.\n"); title += std::string("\n"); @@ -57,7 +90,7 @@ std::string create_openfpga_title() { /******************************************************************** * Generate a string of openfpga title introduction - * This is mainly used when launching OpenFPGA shell + * This is mainly used when launching OpenFPGA shell *******************************************************************/ void print_openfpga_version_info() { /* Display version */ diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index ae154435f..90bd48eb1 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -2,17 +2,16 @@ * This file includes functions to compress the hierachy of routing architecture *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgashell library */ #include "command_exit_codes.h" /* Headers from openfpgautil library */ #include "openfpga_scale.h" - -#include "verilog_api.h" #include "openfpga_verilog.h" +#include "verilog_api.h" /* Headers from pcf library */ #include "read_xml_pin_constraints.h" @@ -27,278 +26,302 @@ namespace openfpga { /******************************************************************** - * A wrapper function to call the fabric Verilog generator of FPGA-Verilog + * A wrapper function to call the fabric Verilog generator of FPGA-Verilog *******************************************************************/ -int write_fabric_verilog(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - +int write_fabric_verilog(OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_output_dir = cmd.option("file"); - CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); + CommandOptionId opt_explicit_port_mapping = + cmd.option("explicit_port_mapping"); CommandOptionId opt_include_timing = cmd.option("include_timing"); - CommandOptionId opt_print_user_defined_template = cmd.option("print_user_defined_template"); + CommandOptionId opt_print_user_defined_template = + cmd.option("print_user_defined_template"); CommandOptionId opt_default_net_type = cmd.option("default_net_type"); CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); CommandOptionId opt_use_relative_path = cmd.option("use_relative_path"); CommandOptionId opt_verbose = cmd.option("verbose"); - /* This is an intermediate data structure which is designed to modularize the FPGA-Verilog - * Keep it independent from any other outside data structures + /* This is an intermediate data structure which is designed to modularize the + * FPGA-Verilog Keep it independent from any other outside data structures */ FabricVerilogOption options; options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir)); - options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); - options.set_include_timing(cmd_context.option_enable(cmd, opt_include_timing)); + options.set_explicit_port_mapping( + cmd_context.option_enable(cmd, opt_explicit_port_mapping)); + options.set_include_timing( + cmd_context.option_enable(cmd, opt_include_timing)); options.set_time_stamp(!cmd_context.option_enable(cmd, opt_no_time_stamp)); - options.set_use_relative_path(cmd_context.option_enable(cmd, opt_use_relative_path)); - options.set_print_user_defined_template(cmd_context.option_enable(cmd, opt_print_user_defined_template)); + options.set_use_relative_path( + cmd_context.option_enable(cmd, opt_use_relative_path)); + options.set_print_user_defined_template( + cmd_context.option_enable(cmd, opt_print_user_defined_template)); if (true == cmd_context.option_enable(cmd, opt_default_net_type)) { - options.set_default_net_type(cmd_context.option_value(cmd, opt_default_net_type)); + options.set_default_net_type( + cmd_context.option_value(cmd, opt_default_net_type)); } options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); options.set_compress_routing(openfpga_ctx.flow_manager().compress_routing()); - + fpga_fabric_verilog(openfpga_ctx.mutable_module_graph(), openfpga_ctx.mutable_verilog_netlists(), openfpga_ctx.blwl_shift_register_banks(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.mux_lib(), - openfpga_ctx.decoder_lib(), - g_vpr_ctx.device(), + openfpga_ctx.arch().circuit_lib, openfpga_ctx.mux_lib(), + openfpga_ctx.decoder_lib(), g_vpr_ctx.device(), openfpga_ctx.vpr_device_annotation(), - openfpga_ctx.device_rr_gsb(), - options); + openfpga_ctx.device_rr_gsb(), options); /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; -} +} /******************************************************************** - * A wrapper function to call the full testbench generator of FPGA-Verilog + * A wrapper function to call the full testbench generator of FPGA-Verilog *******************************************************************/ int write_full_testbench(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - + const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_output_dir = cmd.option("file"); CommandOptionId opt_bitstream = cmd.option("bitstream"); CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); CommandOptionId opt_bgf = cmd.option("bus_group_file"); - CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path"); + CommandOptionId opt_reference_benchmark = + cmd.option("reference_benchmark_file_path"); CommandOptionId opt_fast_configuration = cmd.option("fast_configuration"); - CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); + CommandOptionId opt_explicit_port_mapping = + cmd.option("explicit_port_mapping"); CommandOptionId opt_default_net_type = cmd.option("default_net_type"); CommandOptionId opt_include_signal_init = cmd.option("include_signal_init"); CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); CommandOptionId opt_use_relative_path = cmd.option("use_relative_path"); CommandOptionId opt_verbose = cmd.option("verbose"); - /* This is an intermediate data structure which is designed to modularize the FPGA-Verilog - * Keep it independent from any other outside data structures + /* This is an intermediate data structure which is designed to modularize the + * FPGA-Verilog Keep it independent from any other outside data structures */ VerilogTestbenchOption options; options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir)); - options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist)); - options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark)); - options.set_fast_configuration(cmd_context.option_enable(cmd, opt_fast_configuration)); - options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); + options.set_fabric_netlist_file_path( + cmd_context.option_value(cmd, opt_fabric_netlist)); + options.set_reference_benchmark_file_path( + cmd_context.option_value(cmd, opt_reference_benchmark)); + options.set_fast_configuration( + cmd_context.option_enable(cmd, opt_fast_configuration)); + options.set_explicit_port_mapping( + cmd_context.option_enable(cmd, opt_explicit_port_mapping)); options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); options.set_time_stamp(!cmd_context.option_enable(cmd, opt_no_time_stamp)); - options.set_use_relative_path(cmd_context.option_enable(cmd, opt_use_relative_path)); + options.set_use_relative_path( + cmd_context.option_enable(cmd, opt_use_relative_path)); options.set_print_top_testbench(true); - options.set_include_signal_init(cmd_context.option_enable(cmd, opt_include_signal_init)); + options.set_include_signal_init( + cmd_context.option_enable(cmd, opt_include_signal_init)); if (true == cmd_context.option_enable(cmd, opt_default_net_type)) { - options.set_default_net_type(cmd_context.option_value(cmd, opt_default_net_type)); + options.set_default_net_type( + cmd_context.option_value(cmd, opt_default_net_type)); } /* If pin constraints are enabled by command options, read the file */ PinConstraints pin_constraints; if (true == cmd_context.option_enable(cmd, opt_pcf)) { - pin_constraints = read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str()); + pin_constraints = + read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str()); } /* If bug group file are enabled by command options, read the file */ BusGroup bus_group; if (true == cmd_context.option_enable(cmd, opt_bgf)) { - bus_group = read_xml_bus_group(cmd_context.option_value(cmd, opt_bgf).c_str()); + bus_group = + read_xml_bus_group(cmd_context.option_value(cmd, opt_bgf).c_str()); } - - return fpga_verilog_full_testbench(openfpga_ctx.module_graph(), - openfpga_ctx.bitstream_manager(), - openfpga_ctx.fabric_bitstream(), - openfpga_ctx.blwl_shift_register_banks(), - g_vpr_ctx.atom(), - g_vpr_ctx.placement(), - pin_constraints, - bus_group, - cmd_context.option_value(cmd, opt_bitstream), - openfpga_ctx.io_location_map(), - openfpga_ctx.fabric_global_port_info(), - openfpga_ctx.vpr_netlist_annotation(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.simulation_setting(), - openfpga_ctx.arch().config_protocol, - options); -} + + return fpga_verilog_full_testbench( + openfpga_ctx.module_graph(), openfpga_ctx.bitstream_manager(), + openfpga_ctx.fabric_bitstream(), openfpga_ctx.blwl_shift_register_banks(), + g_vpr_ctx.atom(), g_vpr_ctx.placement(), pin_constraints, bus_group, + cmd_context.option_value(cmd, opt_bitstream), + openfpga_ctx.io_location_map(), openfpga_ctx.fabric_global_port_info(), + openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.arch().circuit_lib, + openfpga_ctx.simulation_setting(), openfpga_ctx.arch().config_protocol, + options); +} /******************************************************************** - * A wrapper function to call the preconfigured wrapper generator of FPGA-Verilog + * A wrapper function to call the preconfigured wrapper generator of + *FPGA-Verilog *******************************************************************/ int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - + const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_output_dir = cmd.option("file"); CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); CommandOptionId opt_bgf = cmd.option("bus_group_file"); - CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); + CommandOptionId opt_explicit_port_mapping = + cmd.option("explicit_port_mapping"); CommandOptionId opt_default_net_type = cmd.option("default_net_type"); CommandOptionId opt_include_signal_init = cmd.option("include_signal_init"); CommandOptionId opt_embed_bitstream = cmd.option("embed_bitstream"); CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); CommandOptionId opt_verbose = cmd.option("verbose"); - /* This is an intermediate data structure which is designed to modularize the FPGA-Verilog - * Keep it independent from any other outside data structures + /* This is an intermediate data structure which is designed to modularize the + * FPGA-Verilog Keep it independent from any other outside data structures */ VerilogTestbenchOption options; options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir)); - options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist)); - options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); + options.set_fabric_netlist_file_path( + cmd_context.option_value(cmd, opt_fabric_netlist)); + options.set_explicit_port_mapping( + cmd_context.option_enable(cmd, opt_explicit_port_mapping)); options.set_time_stamp(!cmd_context.option_enable(cmd, opt_no_time_stamp)); options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); - options.set_include_signal_init(cmd_context.option_enable(cmd, opt_include_signal_init)); + options.set_include_signal_init( + cmd_context.option_enable(cmd, opt_include_signal_init)); options.set_print_formal_verification_top_netlist(true); if (true == cmd_context.option_enable(cmd, opt_default_net_type)) { - options.set_default_net_type(cmd_context.option_value(cmd, opt_default_net_type)); + options.set_default_net_type( + cmd_context.option_value(cmd, opt_default_net_type)); } if (true == cmd_context.option_enable(cmd, opt_embed_bitstream)) { - options.set_embedded_bitstream_hdl_type(cmd_context.option_value(cmd, opt_embed_bitstream)); + options.set_embedded_bitstream_hdl_type( + cmd_context.option_value(cmd, opt_embed_bitstream)); } /* 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()); + pin_constraints = + read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str()); } /* If bug group file are enabled by command options, read the file */ BusGroup bus_group; if (true == cmd_context.option_enable(cmd, opt_bgf)) { - bus_group = read_xml_bus_group(cmd_context.option_value(cmd, opt_bgf).c_str()); + bus_group = + read_xml_bus_group(cmd_context.option_value(cmd, opt_bgf).c_str()); } - - return fpga_verilog_preconfigured_fabric_wrapper(openfpga_ctx.module_graph(), - openfpga_ctx.bitstream_manager(), - g_vpr_ctx.atom(), - g_vpr_ctx.placement(), - pin_constraints, - bus_group, - openfpga_ctx.io_location_map(), - openfpga_ctx.fabric_global_port_info(), - openfpga_ctx.vpr_netlist_annotation(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.arch().config_protocol, - options); -} + + return fpga_verilog_preconfigured_fabric_wrapper( + openfpga_ctx.module_graph(), openfpga_ctx.bitstream_manager(), + g_vpr_ctx.atom(), g_vpr_ctx.placement(), pin_constraints, bus_group, + openfpga_ctx.io_location_map(), openfpga_ctx.fabric_global_port_info(), + openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.arch().circuit_lib, + openfpga_ctx.arch().config_protocol, options); +} /******************************************************************** - * A wrapper function to call the preconfigured testbench generator of FPGA-Verilog + * A wrapper function to call the preconfigured testbench generator of + *FPGA-Verilog *******************************************************************/ int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - + const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_output_dir = cmd.option("file"); CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); CommandOptionId opt_bgf = cmd.option("bus_group_file"); CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); - CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path"); - CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); + CommandOptionId opt_reference_benchmark = + cmd.option("reference_benchmark_file_path"); + CommandOptionId opt_explicit_port_mapping = + cmd.option("explicit_port_mapping"); CommandOptionId opt_default_net_type = cmd.option("default_net_type"); CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); CommandOptionId opt_use_relative_path = cmd.option("use_relative_path"); CommandOptionId opt_verbose = cmd.option("verbose"); - /* This is an intermediate data structure which is designed to modularize the FPGA-Verilog - * Keep it independent from any other outside data structures + /* This is an intermediate data structure which is designed to modularize the + * FPGA-Verilog Keep it independent from any other outside data structures */ VerilogTestbenchOption options; options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir)); - options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist)); - options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark)); - options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); + options.set_fabric_netlist_file_path( + cmd_context.option_value(cmd, opt_fabric_netlist)); + options.set_reference_benchmark_file_path( + cmd_context.option_value(cmd, opt_reference_benchmark)); + options.set_explicit_port_mapping( + cmd_context.option_enable(cmd, opt_explicit_port_mapping)); options.set_time_stamp(!cmd_context.option_enable(cmd, opt_no_time_stamp)); - options.set_use_relative_path(cmd_context.option_enable(cmd, opt_use_relative_path)); + options.set_use_relative_path( + cmd_context.option_enable(cmd, opt_use_relative_path)); options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); options.set_print_preconfig_top_testbench(true); if (true == cmd_context.option_enable(cmd, opt_default_net_type)) { - options.set_default_net_type(cmd_context.option_value(cmd, opt_default_net_type)); + options.set_default_net_type( + cmd_context.option_value(cmd, opt_default_net_type)); } /* If pin constraints are enabled by command options, read the file */ PinConstraints pin_constraints; if (true == cmd_context.option_enable(cmd, opt_pcf)) { - pin_constraints = read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str()); + pin_constraints = + read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str()); } /* If bug group file are enabled by command options, read the file */ BusGroup bus_group; if (true == cmd_context.option_enable(cmd, opt_bgf)) { - bus_group = read_xml_bus_group(cmd_context.option_value(cmd, opt_bgf).c_str()); + bus_group = + read_xml_bus_group(cmd_context.option_value(cmd, opt_bgf).c_str()); } - - return fpga_verilog_preconfigured_testbench(openfpga_ctx.module_graph(), - g_vpr_ctx.atom(), - pin_constraints, - bus_group, - openfpga_ctx.fabric_global_port_info(), - openfpga_ctx.vpr_netlist_annotation(), - openfpga_ctx.simulation_setting(), - options); -} + + return fpga_verilog_preconfigured_testbench( + openfpga_ctx.module_graph(), g_vpr_ctx.atom(), pin_constraints, bus_group, + openfpga_ctx.fabric_global_port_info(), + openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.simulation_setting(), + options); +} /******************************************************************** - * A wrapper function to call the simulation task information generator of FPGA-Verilog + * A wrapper function to call the simulation task information generator of + *FPGA-Verilog *******************************************************************/ int write_simulation_task_info(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - + const Command& cmd, + const CommandContext& cmd_context) { CommandOptionId opt_file = cmd.option("file"); CommandOptionId opt_hdl_dir = cmd.option("hdl_dir"); - CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path"); + CommandOptionId opt_reference_benchmark = + cmd.option("reference_benchmark_file_path"); CommandOptionId opt_tb_type = cmd.option("testbench_type"); CommandOptionId opt_time_unit = cmd.option("time_unit"); CommandOptionId opt_verbose = cmd.option("verbose"); - /* This is an intermediate data structure which is designed to modularize the FPGA-Verilog - * Keep it independent from any other outside data structures + /* This is an intermediate data structure which is designed to modularize the + * FPGA-Verilog Keep it independent from any other outside data structures */ VerilogTestbenchOption options; options.set_output_directory(cmd_context.option_value(cmd, opt_hdl_dir)); - options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark)); + options.set_reference_benchmark_file_path( + cmd_context.option_value(cmd, opt_reference_benchmark)); options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); options.set_print_simulation_ini(cmd_context.option_value(cmd, opt_file)); if (true == cmd_context.option_enable(cmd, opt_time_unit)) { - options.set_time_unit(string_to_time_unit(cmd_context.option_value(cmd, opt_time_unit))); + options.set_time_unit( + string_to_time_unit(cmd_context.option_value(cmd, opt_time_unit))); } /* Identify testbench type */ std::string full_tb_tag("full_testbench"); std::string preconfig_tb_tag("preconfigured_testbench"); if (true == cmd_context.option_enable(cmd, opt_tb_type)) { - if (std::string("preconfigured_testbench") == cmd_context.option_value(cmd, opt_tb_type)) { + if (std::string("preconfigured_testbench") == + cmd_context.option_value(cmd, opt_tb_type)) { options.set_print_preconfig_top_testbench(true); - } else if (std::string("full_testbench") == cmd_context.option_value(cmd, opt_tb_type)) { + } else if (std::string("full_testbench") == + cmd_context.option_value(cmd, opt_tb_type)) { options.set_print_preconfig_top_testbench(false); options.set_print_top_testbench(true); } else { /* Invalid option, error out */ - VTR_LOG_ERROR("Invalid option value for testbench type: '%s'! Should be either '%s' or '%s'\n", - cmd_context.option_value(cmd, opt_tb_type).c_str(), - full_tb_tag.c_str(), - preconfig_tb_tag.c_str()); + VTR_LOG_ERROR( + "Invalid option value for testbench type: '%s'! Should be either '%s' " + "or '%s'\n", + cmd_context.option_value(cmd, opt_tb_type).c_str(), full_tb_tag.c_str(), + preconfig_tb_tag.c_str()); return CMD_EXEC_FATAL_ERROR; } } else { @@ -306,14 +329,11 @@ int write_simulation_task_info(const OpenfpgaContext& openfpga_ctx, options.set_print_preconfig_top_testbench(true); } - return fpga_verilog_simulation_task_info(openfpga_ctx.module_graph(), - openfpga_ctx.bitstream_manager(), - g_vpr_ctx.atom(), - g_vpr_ctx.placement(), - openfpga_ctx.io_location_map(), - openfpga_ctx.simulation_setting(), - openfpga_ctx.arch().config_protocol, - options); -} + return fpga_verilog_simulation_task_info( + openfpga_ctx.module_graph(), openfpga_ctx.bitstream_manager(), + g_vpr_ctx.atom(), g_vpr_ctx.placement(), openfpga_ctx.io_location_map(), + openfpga_ctx.simulation_setting(), openfpga_ctx.arch().config_protocol, + options); +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_verilog.h b/openfpga/src/base/openfpga_verilog.h index 3bbd7fab3..34b967d0a 100644 --- a/openfpga/src/base/openfpga_verilog.h +++ b/openfpga/src/base/openfpga_verilog.h @@ -15,20 +15,23 @@ /* begin namespace openfpga */ namespace openfpga { -int write_fabric_verilog(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); +int write_fabric_verilog(OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context); int write_full_testbench(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); + const Command& cmd, const CommandContext& cmd_context); int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); + const Command& cmd, + const CommandContext& cmd_context); int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); + const Command& cmd, + const CommandContext& cmd_context); int write_simulation_task_info(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); + const Command& cmd, + const CommandContext& cmd_context); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_verilog_command.cpp b/openfpga/src/base/openfpga_verilog_command.cpp index 1cc85333a..6ce1ea193 100644 --- a/openfpga/src/base/openfpga_verilog_command.cpp +++ b/openfpga/src/base/openfpga_verilog_command.cpp @@ -1,56 +1,69 @@ /******************************************************************** - * Add commands to the OpenFPGA shell interface, + * Add commands to the OpenFPGA shell interface, * in purpose of generate Verilog netlists modeling the full FPGA fabric * This is one of the core engine of openfpga, including: - * - generate_fabric_verilog : generate Verilog netlists about FPGA fabric - * - generate_fabric_verilog_testbench : TODO: generate Verilog testbenches + * - generate_fabric_verilog : generate Verilog netlists about FPGA fabric + * - generate_fabric_verilog_testbench : TODO: generate Verilog testbenches *******************************************************************/ -#include "openfpga_verilog.h" #include "openfpga_verilog_command.h" +#include "openfpga_verilog.h" + /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * - Add a command to Shell environment: generate fabric Verilog - * - Add associated options + * - Add a command to Shell environment: generate fabric Verilog + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_write_fabric_verilog_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_fabric_verilog_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_fabric_verilog"); /* Add an option '--file' in short '-f'*/ - CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for Verilog netlists"); + CommandOptionId output_opt = shell_cmd.add_option( + "file", true, "Specify the output directory for Verilog netlists"); shell_cmd.set_option_short_name(output_opt, "f"); shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); /* Add an option '--explicit_port_mapping' */ - shell_cmd.add_option("explicit_port_mapping", false, "Use explicit port mapping in Verilog netlists"); + shell_cmd.add_option("explicit_port_mapping", false, + "Use explicit port mapping in Verilog netlists"); /* Add an option '--include_timing' */ - shell_cmd.add_option("include_timing", false, "Enable timing annotation in Verilog netlists"); + shell_cmd.add_option("include_timing", false, + "Enable timing annotation in Verilog netlists"); /* Add an option '--print_user_defined_template' */ - shell_cmd.add_option("print_user_defined_template", false, "Generate a template Verilog files for user-defined circuit models"); + shell_cmd.add_option( + "print_user_defined_template", false, + "Generate a template Verilog files for user-defined circuit models"); /* Add an option '--default_net_type' */ - CommandOptionId default_net_type_opt = shell_cmd.add_option("default_net_type", false, "Set the default net type for Verilog netlists. Default value is 'none'"); - shell_cmd.set_option_require_value(default_net_type_opt, openfpga::OPT_STRING); + CommandOptionId default_net_type_opt = shell_cmd.add_option( + "default_net_type", false, + "Set the default net type for Verilog netlists. Default value is 'none'"); + shell_cmd.set_option_require_value(default_net_type_opt, + openfpga::OPT_STRING); /* Add an option '--no_time_stamp' */ - shell_cmd.add_option("no_time_stamp", false, "Do not print a time stamp in the output files"); + shell_cmd.add_option("no_time_stamp", false, + "Do not print a time stamp in the output files"); /* Add an option '--use_relative_path' */ - shell_cmd.add_option("use_relative_path", false, "Force to use relative path in netlists when including other netlists"); + shell_cmd.add_option( + "use_relative_path", false, + "Force to use relative path in netlists when including other netlists"); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); - + /* Add command 'write_fabric_verilog' to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate Verilog netlists modeling full FPGA fabric"); + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, "generate Verilog netlists modeling full FPGA fabric"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, write_fabric_verilog); @@ -62,69 +75,92 @@ ShellCommandId add_openfpga_write_fabric_verilog_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_full_testbench_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_full_testbench"); /* add an option '--file' in short '-f'*/ - CommandOptionId output_opt = shell_cmd.add_option("file", true, "specify the output directory for hdl netlists"); + CommandOptionId output_opt = shell_cmd.add_option( + "file", true, "specify the output directory for hdl netlists"); shell_cmd.set_option_short_name(output_opt, "f"); shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); /* add an option '--bitstream'*/ - CommandOptionId bitstream_opt = shell_cmd.add_option("bitstream", true, "specify the bitstream to be loaded in the testbench"); + CommandOptionId bitstream_opt = shell_cmd.add_option( + "bitstream", true, "specify the bitstream to be loaded in the testbench"); shell_cmd.set_option_require_value(bitstream_opt, openfpga::OPT_STRING); /* add an option '--fabric_netlist_file_path'*/ - CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "specify the file path to the fabric hdl netlist"); + CommandOptionId fabric_netlist_opt = + shell_cmd.add_option("fabric_netlist_file_path", false, + "specify the file path to the fabric hdl netlist"); shell_cmd.set_option_require_value(fabric_netlist_opt, openfpga::OPT_STRING); /* add an option '--pin_constraints_file in short '-pcf' */ - CommandOptionId pcf_opt = shell_cmd.add_option("pin_constraints_file", false, "specify the file path to the pin constraints"); + CommandOptionId pcf_opt = + shell_cmd.add_option("pin_constraints_file", false, + "specify the file path to the pin constraints"); shell_cmd.set_option_short_name(pcf_opt, "pcf"); shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING); /* add an option '--bus_group_file in short '-bgf' */ - CommandOptionId bgf_opt = shell_cmd.add_option("bus_group_file", false, "specify the file path to the group pins to bus"); + CommandOptionId bgf_opt = shell_cmd.add_option( + "bus_group_file", false, "specify the file path to the group pins to bus"); shell_cmd.set_option_short_name(bgf_opt, "bgf"); shell_cmd.set_option_require_value(bgf_opt, openfpga::OPT_STRING); /* add an option '--reference_benchmark_file_path'*/ - CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", false, "specify the file path to the reference verilog netlist. If specified, the testbench will include self-checking codes"); + CommandOptionId ref_bm_opt = shell_cmd.add_option( + "reference_benchmark_file_path", false, + "specify the file path to the reference verilog netlist. If specified, the " + "testbench will include self-checking codes"); shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING); /* add an option '--fast_configuration' */ - shell_cmd.add_option("fast_configuration", false, "reduce the period of configuration by skip certain data points"); + shell_cmd.add_option( + "fast_configuration", false, + "reduce the period of configuration by skip certain data points"); /* add an option '--explicit_port_mapping' */ - shell_cmd.add_option("explicit_port_mapping", false, "use explicit port mapping in verilog netlists"); + shell_cmd.add_option("explicit_port_mapping", false, + "use explicit port mapping in verilog netlists"); /* Add an option '--default_net_type' */ - CommandOptionId default_net_type_opt = shell_cmd.add_option("default_net_type", false, "Set the default net type for Verilog netlists. Default value is 'none'"); - shell_cmd.set_option_require_value(default_net_type_opt, openfpga::OPT_STRING); + CommandOptionId default_net_type_opt = shell_cmd.add_option( + "default_net_type", false, + "Set the default net type for Verilog netlists. Default value is 'none'"); + shell_cmd.set_option_require_value(default_net_type_opt, + openfpga::OPT_STRING); /* Add an option '--no_self_checking' */ - shell_cmd.add_option("no_self_checking", false, "Do not generate self-checking codes for Verilog testbenches."); + shell_cmd.add_option( + "no_self_checking", false, + "Do not generate self-checking codes for Verilog testbenches."); /* add an option '--include_signal_init' */ - shell_cmd.add_option("include_signal_init", false, "initialize all the signals in verilog testbenches"); + shell_cmd.add_option("include_signal_init", false, + "initialize all the signals in verilog testbenches"); /* Add an option '--no_time_stamp' */ - shell_cmd.add_option("no_time_stamp", false, "Do not print a time stamp in the output files"); + shell_cmd.add_option("no_time_stamp", false, + "Do not print a time stamp in the output files"); /* Add an option '--use_relative_path' */ - shell_cmd.add_option("use_relative_path", false, "Force to use relative path in netlists when including other netlists"); + shell_cmd.add_option( + "use_relative_path", false, + "Force to use relative path in netlists when including other netlists"); /* add an option '--verbose' */ shell_cmd.add_option("verbose", false, "enable verbose output"); - + /* add command to the shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate full testbenches for an fpga fabric"); + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, "generate full testbenches for an fpga fabric"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, write_full_testbench); @@ -136,58 +172,75 @@ ShellCommandId add_openfpga_write_full_testbench_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_preconfigured_fabric_wrapper_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_preconfigured_fabric_wrapper"); /* add an option '--file' in short '-f'*/ - CommandOptionId output_opt = shell_cmd.add_option("file", true, "specify the output directory for hdl netlists"); + CommandOptionId output_opt = shell_cmd.add_option( + "file", true, "specify the output directory for hdl netlists"); shell_cmd.set_option_short_name(output_opt, "f"); shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); /* add an option '--fabric_netlist_file_path'*/ - CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "specify the file path to the fabric hdl netlist"); + CommandOptionId fabric_netlist_opt = + shell_cmd.add_option("fabric_netlist_file_path", false, + "specify the file path to the fabric hdl netlist"); shell_cmd.set_option_require_value(fabric_netlist_opt, openfpga::OPT_STRING); /* add an option '--pin_constraints_file in short '-pcf' */ - CommandOptionId pcf_opt = shell_cmd.add_option("pin_constraints_file", false, "specify the file path to the pin constraints"); + CommandOptionId pcf_opt = + shell_cmd.add_option("pin_constraints_file", false, + "specify the file path to the pin constraints"); shell_cmd.set_option_short_name(pcf_opt, "pcf"); shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING); /* add an option '--bus_group_file in short '-bgf' */ - CommandOptionId bgf_opt = shell_cmd.add_option("bus_group_file", false, "specify the file path to the group pins to bus"); + CommandOptionId bgf_opt = shell_cmd.add_option( + "bus_group_file", false, "specify the file path to the group pins to bus"); shell_cmd.set_option_short_name(bgf_opt, "bgf"); shell_cmd.set_option_require_value(bgf_opt, openfpga::OPT_STRING); /* add an option '--explicit_port_mapping' */ - shell_cmd.add_option("explicit_port_mapping", false, "use explicit port mapping in verilog netlists"); + shell_cmd.add_option("explicit_port_mapping", false, + "use explicit port mapping in verilog netlists"); /* Add an option '--default_net_type' */ - CommandOptionId default_net_type_opt = shell_cmd.add_option("default_net_type", false, "Set the default net type for Verilog netlists. Default value is 'none'"); - shell_cmd.set_option_require_value(default_net_type_opt, openfpga::OPT_STRING); + CommandOptionId default_net_type_opt = shell_cmd.add_option( + "default_net_type", false, + "Set the default net type for Verilog netlists. Default value is 'none'"); + shell_cmd.set_option_require_value(default_net_type_opt, + openfpga::OPT_STRING); /* Add an option '--embed_bitstream' */ - CommandOptionId embed_bitstream_opt = shell_cmd.add_option("embed_bitstream", false, "Embed bitstream to the Verilog wrapper netlist; This may cause a large netlist file size"); + CommandOptionId embed_bitstream_opt = + shell_cmd.add_option("embed_bitstream", false, + "Embed bitstream to the Verilog wrapper netlist; This " + "may cause a large netlist file size"); shell_cmd.set_option_require_value(embed_bitstream_opt, openfpga::OPT_STRING); /* add an option '--include_signal_init' */ - shell_cmd.add_option("include_signal_init", false, "initialize all the signals in verilog testbenches"); + shell_cmd.add_option("include_signal_init", false, + "initialize all the signals in verilog testbenches"); /* Add an option '--no_time_stamp' */ - shell_cmd.add_option("no_time_stamp", false, "Do not print a time stamp in the output files"); + shell_cmd.add_option("no_time_stamp", false, + "Do not print a time stamp in the output files"); /* add an option '--verbose' */ shell_cmd.add_option("verbose", false, "enable verbose output"); - + /* add command to the shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate a wrapper for a pre-configured fpga fabric"); + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, "generate a wrapper for a pre-configured fpga fabric"); shell.set_command_class(shell_cmd_id, cmd_class_id); - shell.set_command_execute_function(shell_cmd_id, write_preconfigured_fabric_wrapper); + shell.set_command_execute_function(shell_cmd_id, + write_preconfigured_fabric_wrapper); /* add command dependency to the shell */ shell.set_command_dependency(shell_cmd_id, dependent_cmds); @@ -197,58 +250,76 @@ ShellCommandId add_openfpga_write_preconfigured_fabric_wrapper_command(openfpga: /******************************************************************** * - Add a command to Shell environment: write preconfigured testbench - * - Add associated options + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_write_preconfigured_testbench_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_preconfigured_testbench_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_preconfigured_testbench"); /* Add an option '--file' in short '-f'*/ - CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for HDL netlists"); + CommandOptionId output_opt = shell_cmd.add_option( + "file", true, "Specify the output directory for HDL netlists"); shell_cmd.set_option_short_name(output_opt, "f"); shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); /* add an option '--fabric_netlist_file_path'*/ - CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "specify the file path to the fabric hdl netlist"); + CommandOptionId fabric_netlist_opt = + shell_cmd.add_option("fabric_netlist_file_path", false, + "specify the file path to the fabric hdl netlist"); shell_cmd.set_option_require_value(fabric_netlist_opt, openfpga::OPT_STRING); /* Add an option '--pin_constraints_file in short '-pcf' */ - CommandOptionId pcf_opt = shell_cmd.add_option("pin_constraints_file", false, "Specify the file path to the pin constraints"); + CommandOptionId pcf_opt = + shell_cmd.add_option("pin_constraints_file", false, + "Specify the file path to the pin constraints"); shell_cmd.set_option_short_name(pcf_opt, "pcf"); shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING); /* add an option '--bus_group_file in short '-bgf' */ - CommandOptionId bgf_opt = shell_cmd.add_option("bus_group_file", false, "specify the file path to the group pins to bus"); + CommandOptionId bgf_opt = shell_cmd.add_option( + "bus_group_file", false, "specify the file path to the group pins to bus"); shell_cmd.set_option_short_name(bgf_opt, "bgf"); shell_cmd.set_option_require_value(bgf_opt, openfpga::OPT_STRING); /* Add an option '--reference_benchmark_file_path'*/ - CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", false, "Specify the file path to the reference Verilog netlist. If specified, the testbench will include self-checking codes"); + CommandOptionId ref_bm_opt = shell_cmd.add_option( + "reference_benchmark_file_path", false, + "Specify the file path to the reference Verilog netlist. If specified, the " + "testbench will include self-checking codes"); shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING); /* Add an option '--explicit_port_mapping' */ - shell_cmd.add_option("explicit_port_mapping", false, "Use explicit port mapping in Verilog netlists"); + shell_cmd.add_option("explicit_port_mapping", false, + "Use explicit port mapping in Verilog netlists"); /* Add an option '--default_net_type' */ - CommandOptionId default_net_type_opt = shell_cmd.add_option("default_net_type", false, "Set the default net type for Verilog netlists. Default value is 'none'"); - shell_cmd.set_option_require_value(default_net_type_opt, openfpga::OPT_STRING); + CommandOptionId default_net_type_opt = shell_cmd.add_option( + "default_net_type", false, + "Set the default net type for Verilog netlists. Default value is 'none'"); + shell_cmd.set_option_require_value(default_net_type_opt, + openfpga::OPT_STRING); /* Add an option '--no_time_stamp' */ - shell_cmd.add_option("no_time_stamp", false, "Do not print a time stamp in the output files"); + shell_cmd.add_option("no_time_stamp", false, + "Do not print a time stamp in the output files"); /* Add an option '--use_relative_path' */ - shell_cmd.add_option("use_relative_path", false, "Force to use relative path in netlists when including other netlists"); + shell_cmd.add_option( + "use_relative_path", false, + "Force to use relative path in netlists when including other netlists"); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); - + /* Add command to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate testbenches for a preconfigured FPGA fabric"); + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, "generate testbenches for a preconfigured FPGA fabric"); shell.set_command_class(shell_cmd_id, cmd_class_id); - shell.set_command_execute_function(shell_cmd_id, write_preconfigured_testbench); + shell.set_command_execute_function(shell_cmd_id, + write_preconfigured_testbench); /* Add command dependency to the Shell */ shell.set_command_dependency(shell_cmd_id, dependent_cmds); @@ -258,41 +329,55 @@ ShellCommandId add_openfpga_write_preconfigured_testbench_command(openfpga::Shel /******************************************************************** * - Add a command to Shell environment: write simulation task info - * - Add associated options + * - Add associated options * - Add command dependency *******************************************************************/ -static -ShellCommandId add_openfpga_write_simulation_task_info_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { +static ShellCommandId add_openfpga_write_simulation_task_info_command( + openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { Command shell_cmd("write_simulation_task_info"); /* Add an option '--file' in short '-f'*/ - CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the file path to output simulation-related information"); + CommandOptionId output_opt = shell_cmd.add_option( + "file", true, + "Specify the file path to output simulation-related information"); shell_cmd.set_option_short_name(output_opt, "f"); shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); /* Add an option '--hdl_dir'*/ - CommandOptionId hdl_dir_opt = shell_cmd.add_option("hdl_dir", true, "Specify the directory path where HDL netlists are created"); + CommandOptionId hdl_dir_opt = shell_cmd.add_option( + "hdl_dir", true, + "Specify the directory path where HDL netlists are created"); shell_cmd.set_option_require_value(hdl_dir_opt, openfpga::OPT_STRING); /* Add an option '--reference_benchmark_file_path'*/ - CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", false, "Specify the file path to the reference Verilog netlist. If specified, the testbench will include self-checking codes"); + CommandOptionId ref_bm_opt = shell_cmd.add_option( + "reference_benchmark_file_path", false, + "Specify the file path to the reference Verilog netlist. If specified, the " + "testbench will include self-checking codes"); shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING); /* Add an option '--testbench_type'*/ - CommandOptionId tb_type_opt = shell_cmd.add_option("testbench_type", false, "Specify the type of testbenches to be considered. Different testbenches have different simulation parameters."); + CommandOptionId tb_type_opt = shell_cmd.add_option( + "testbench_type", false, + "Specify the type of testbenches to be considered. Different testbenches " + "have different simulation parameters."); shell_cmd.set_option_require_value(tb_type_opt, openfpga::OPT_STRING); /* Add an option '--time_unit' */ - CommandOptionId time_unit_opt = shell_cmd.add_option("time_unit", false, "Specify the time unit to be used in HDL simulation. Acceptable is [a|f|p|n|u|m|k|M]s"); + CommandOptionId time_unit_opt = + shell_cmd.add_option("time_unit", false, + "Specify the time unit to be used in HDL simulation. " + "Acceptable is [a|f|p|n|u|m|k|M]s"); shell_cmd.set_option_require_value(time_unit_opt, openfpga::OPT_STRING); /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); - + /* Add command to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate an interchangable simulation task configuration file"); + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, "generate an interchangable simulation task configuration file"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, write_simulation_task_info); @@ -303,61 +388,64 @@ ShellCommandId add_openfpga_write_simulation_task_info_command(openfpga::Shell& shell) { - /* Get the unique id of 'build_fabric' command which is to be used in creating the dependency graph */ - const ShellCommandId& build_fabric_cmd_id = shell.command(std::string("build_fabric")); + /* Get the unique id of 'build_fabric' command which is to be used in creating + * the dependency graph */ + const ShellCommandId& build_fabric_cmd_id = + shell.command(std::string("build_fabric")); /* Add a new class of commands */ - ShellCommandClassId openfpga_verilog_cmd_class = shell.add_command_class("FPGA-Verilog"); + ShellCommandClassId openfpga_verilog_cmd_class = + shell.add_command_class("FPGA-Verilog"); - /******************************** - * Command 'write_fabric_verilog' + /******************************** + * Command 'write_fabric_verilog' */ - /* The 'write_fabric_verilog' command should NOT be executed before 'build_fabric' */ + /* The 'write_fabric_verilog' command should NOT be executed before + * 'build_fabric' */ std::vector fabric_verilog_dependent_cmds; fabric_verilog_dependent_cmds.push_back(build_fabric_cmd_id); - add_openfpga_write_fabric_verilog_command(shell, - openfpga_verilog_cmd_class, + add_openfpga_write_fabric_verilog_command(shell, openfpga_verilog_cmd_class, fabric_verilog_dependent_cmds); - /******************************** - * Command 'write_full_testbench' + /******************************** + * Command 'write_full_testbench' */ - /* The command 'write_full_testbench' should NOT be executed before 'build_fabric' */ + /* The command 'write_full_testbench' should NOT be executed before + * 'build_fabric' */ std::vector full_testbench_dependent_cmds; full_testbench_dependent_cmds.push_back(build_fabric_cmd_id); - add_openfpga_write_full_testbench_command(shell, - openfpga_verilog_cmd_class, + add_openfpga_write_full_testbench_command(shell, openfpga_verilog_cmd_class, full_testbench_dependent_cmds); - /******************************** - * Command 'write_preconfigured_fabric_wrapper' + /******************************** + * Command 'write_preconfigured_fabric_wrapper' */ - /* The command 'write_preconfigured_fabric_wrapper' should NOT be executed before 'build_fabric' */ + /* The command 'write_preconfigured_fabric_wrapper' should NOT be executed + * before 'build_fabric' */ std::vector preconfig_wrapper_dependent_cmds; preconfig_wrapper_dependent_cmds.push_back(build_fabric_cmd_id); - add_openfpga_write_preconfigured_fabric_wrapper_command(shell, - openfpga_verilog_cmd_class, - preconfig_wrapper_dependent_cmds); + add_openfpga_write_preconfigured_fabric_wrapper_command( + shell, openfpga_verilog_cmd_class, preconfig_wrapper_dependent_cmds); - /******************************** - * Command 'write_preconfigured_testbench' + /******************************** + * Command 'write_preconfigured_testbench' */ - /* The command 'write_preconfigured_testbench' should NOT be executed before 'build_fabric' */ + /* The command 'write_preconfigured_testbench' should NOT be executed before + * 'build_fabric' */ std::vector preconfig_testbench_dependent_cmds; preconfig_testbench_dependent_cmds.push_back(build_fabric_cmd_id); - add_openfpga_write_preconfigured_testbench_command(shell, - openfpga_verilog_cmd_class, - preconfig_testbench_dependent_cmds); + add_openfpga_write_preconfigured_testbench_command( + shell, openfpga_verilog_cmd_class, preconfig_testbench_dependent_cmds); - /******************************** - * Command 'write_simulation_task_info' + /******************************** + * Command 'write_simulation_task_info' */ - /* The command 'write_simulation_task_info' should NOT be executed before 'build_fabric' */ + /* The command 'write_simulation_task_info' should NOT be executed before + * 'build_fabric' */ std::vector sim_task_info_dependent_cmds; sim_task_info_dependent_cmds.push_back(build_fabric_cmd_id); - add_openfpga_write_simulation_task_info_command(shell, - openfpga_verilog_cmd_class, - sim_task_info_dependent_cmds); -} + add_openfpga_write_simulation_task_info_command( + shell, openfpga_verilog_cmd_class, sim_task_info_dependent_cmds); +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_verilog_command.h b/openfpga/src/base/openfpga_verilog_command.h index a99b809dd..5141a1f82 100644 --- a/openfpga/src/base/openfpga_verilog_command.h +++ b/openfpga/src/base/openfpga_verilog_command.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "shell.h" #include "openfpga_context.h" +#include "shell.h" /******************************************************************** * Function declaration @@ -14,7 +14,7 @@ /* begin namespace openfpga */ namespace openfpga { -void add_openfpga_verilog_commands(openfpga::Shell& shell); +void add_openfpga_verilog_commands(openfpga::Shell& shell); } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_write_gsb.cpp b/openfpga/src/base/openfpga_write_gsb.cpp index 3ce1ffae0..be74c2a11 100644 --- a/openfpga/src/base/openfpga_write_gsb.cpp +++ b/openfpga/src/base/openfpga_write_gsb.cpp @@ -2,15 +2,13 @@ * This file includes functions to compress the hierachy of routing architecture *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgashell library */ #include "command_exit_codes.h" - -#include "write_xml_device_rr_gsb.h" - #include "openfpga_write_gsb.h" +#include "write_xml_device_rr_gsb.h" /* Include global variables of VPR */ #include "globals.h" @@ -20,13 +18,12 @@ namespace openfpga { /******************************************************************** * Write internal structrure of all the General Switch Blocks (GSBs) - * to an XML file + * to an XML file *******************************************************************/ -int write_gsb(const OpenfpgaContext& openfpga_ctx, - 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 +int write_gsb(const OpenfpgaContext& openfpga_ctx, 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"); @@ -43,7 +40,8 @@ int write_gsb(const OpenfpgaContext& openfpga_ctx, RRGSBWriterOption options; options.set_output_directory(cmd_context.option_value(cmd, opt_file)); options.set_unique_module_only(cmd_context.option_enable(cmd, opt_unique)); - options.set_exclude_rr_info(cmd_context.option_enable(cmd, opt_exclude_rr_info)); + options.set_exclude_rr_info( + cmd_context.option_enable(cmd, opt_exclude_rr_info)); options.set_exclude_content(cmd_context.option_value(cmd, opt_exclude)); options.set_include_gsb_names(cmd_context.option_value(cmd, opt_gsb_names)); options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); @@ -53,14 +51,12 @@ int write_gsb(const OpenfpgaContext& openfpga_ctx, return CMD_EXEC_FATAL_ERROR; } - write_device_rr_gsb_to_xml(g_vpr_ctx.device().grid, - openfpga_ctx.vpr_device_annotation(), - g_vpr_ctx.device().rr_graph, - openfpga_ctx.device_rr_gsb(), - options); + write_device_rr_gsb_to_xml( + g_vpr_ctx.device().grid, openfpga_ctx.vpr_device_annotation(), + g_vpr_ctx.device().rr_graph, openfpga_ctx.device_rr_gsb(), options); /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; -} +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_write_gsb.h b/openfpga/src/base/openfpga_write_gsb.h index 206e6cd5a..a059724cd 100644 --- a/openfpga/src/base/openfpga_write_gsb.h +++ b/openfpga/src/base/openfpga_write_gsb.h @@ -15,8 +15,8 @@ /* begin namespace openfpga */ namespace openfpga { -int write_gsb(const OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); +int write_gsb(const OpenfpgaContext& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_decoder_modules.cpp b/openfpga/src/fabric/build_decoder_modules.cpp index 85ed342aa..f309be6d1 100644 --- a/openfpga/src/fabric/build_decoder_modules.cpp +++ b/openfpga/src/fabric/build_decoder_modules.cpp @@ -1,20 +1,20 @@ /*************************************************************************************** - * This file includes functions that are used to build modules for decoders, including: + * This file includes functions that are used to build modules for decoders, + *including: * 1. Local decoders used by multiplexers ONLY * 2. Decoders used by grid/routing/top-level module for memory address decoding ***************************************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" -#include "vtr_assert.h" -#include "vtr_time.h" +#include "build_decoder_modules.h" -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" #include "decoder_library_utils.h" #include "module_manager_utils.h" - -#include "build_decoder_modules.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" /* begin namespace openfpga */ namespace openfpga { @@ -23,7 +23,7 @@ namespace openfpga { * Create a module for a decoder with a given output size * * Data input - * | | ... | + * | | ... | * v v v * +-----------+ * / \ @@ -32,10 +32,10 @@ namespace openfpga { * | | | ... | | | * v v v v v v * Data Outputs - * + * * The outputs are assumes to be one-hot codes (at most only one '1' exist) - * Considering this fact, there are only num_of_outputs conditions to be encoded. - * Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2)) + * Considering this fact, there are only num_of_outputs conditions to be + *encoded. Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2)) ***************************************************************************************/ ModuleId build_frame_memory_decoder_module(ModuleManager& module_manager, const DecoderLibrary& decoder_lib, @@ -45,10 +45,12 @@ ModuleId build_frame_memory_decoder_module(ModuleManager& module_manager, size_t data_size = decoder_lib.data_size(decoder); /* Create a name for the local encoder */ - std::string module_name = generate_memory_decoder_subckt_name(addr_size, data_size); + std::string module_name = + generate_memory_decoder_subckt_name(addr_size, data_size); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = module_manager.add_module(module_name); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(module_id)); /* Add enable port */ @@ -56,19 +58,23 @@ ModuleId build_frame_memory_decoder_module(ModuleManager& module_manager, module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); /* Add each input port */ BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), addr_size); - module_manager.add_port(module_id, addr_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(module_id, addr_port, + ModuleManager::MODULE_INPUT_PORT); /* Add each output port */ BasicPort data_port(std::string(DECODER_DATA_OUT_PORT_NAME), data_size); - module_manager.add_port(module_id, data_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(module_id, data_port, + ModuleManager::MODULE_OUTPUT_PORT); - /* Data port is registered. It should be outputted as - * output reg [lsb:msb] data + /* Data port is registered. It should be outputted as + * output reg [lsb:msb] data */ module_manager.set_port_is_register(module_id, data_port.get_name(), true); /* Add data_in port */ if (true == decoder_lib.use_data_inv_port(decoder)) { - BasicPort data_inv_port(std::string(DECODER_DATA_OUT_INV_PORT_NAME), data_size); - module_manager.add_port(module_id, data_inv_port, ModuleManager::MODULE_OUTPUT_PORT); + BasicPort data_inv_port(std::string(DECODER_DATA_OUT_INV_PORT_NAME), + data_size); + module_manager.add_port(module_id, data_inv_port, + ModuleManager::MODULE_OUTPUT_PORT); } return module_id; @@ -78,7 +84,7 @@ ModuleId build_frame_memory_decoder_module(ModuleManager& module_manager, * Create a module for a BL decoder with a given output size * * BL Address - * | | ... | + * | | ... | * v v v * +-----------+ * / \<-- data_in @@ -87,10 +93,10 @@ ModuleId build_frame_memory_decoder_module(ModuleManager& module_manager, * | | | ... | | | * v v v v v v * Data Outputs - * + * * The outputs are assumes to be one-hot codes (at most only one '1' exist) - * Considering this fact, there are only num_of_outputs conditions to be encoded. - * Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2)) + * Considering this fact, there are only num_of_outputs conditions to be + *encoded. Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2)) ***************************************************************************************/ ModuleId build_bl_memory_decoder_module(ModuleManager& module_manager, const DecoderLibrary& decoder_lib, @@ -100,10 +106,12 @@ ModuleId build_bl_memory_decoder_module(ModuleManager& module_manager, size_t data_size = decoder_lib.data_size(decoder); /* Create a name for the local encoder */ - std::string module_name = generate_memory_decoder_with_data_in_subckt_name(addr_size, data_size); + std::string module_name = + generate_memory_decoder_with_data_in_subckt_name(addr_size, data_size); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = module_manager.add_module(module_name); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(module_id)); /* Add enable port */ @@ -111,22 +119,27 @@ ModuleId build_bl_memory_decoder_module(ModuleManager& module_manager, module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); /* Add each input port */ BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), addr_size); - module_manager.add_port(module_id, addr_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(module_id, addr_port, + ModuleManager::MODULE_INPUT_PORT); /* Add each input port */ BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), 1); - module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(module_id, din_port, + ModuleManager::MODULE_INPUT_PORT); /* Add each output port */ BasicPort data_port(std::string(DECODER_DATA_OUT_PORT_NAME), data_size); - module_manager.add_port(module_id, data_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(module_id, data_port, + ModuleManager::MODULE_OUTPUT_PORT); - /* Data port is registered. It should be outputted as - * output reg [lsb:msb] data + /* Data port is registered. It should be outputted as + * output reg [lsb:msb] data */ module_manager.set_port_is_register(module_id, data_port.get_name(), true); /* Add data_in port */ if (true == decoder_lib.use_data_inv_port(decoder)) { - BasicPort data_inv_port(std::string(DECODER_DATA_OUT_INV_PORT_NAME), data_size); - module_manager.add_port(module_id, data_inv_port, ModuleManager::MODULE_OUTPUT_PORT); + BasicPort data_inv_port(std::string(DECODER_DATA_OUT_INV_PORT_NAME), + data_size); + module_manager.add_port(module_id, data_inv_port, + ModuleManager::MODULE_OUTPUT_PORT); } return module_id; @@ -136,7 +149,7 @@ ModuleId build_bl_memory_decoder_module(ModuleManager& module_manager, * Create a module for a Word-line decoder with a given output size * * WL Address - * | | ... | + * | | ... | * v v v * +-----------+ * / \ @@ -145,10 +158,10 @@ ModuleId build_bl_memory_decoder_module(ModuleManager& module_manager, * | | | ... | | | * v v v v v v * Data Outputs - * + * * The outputs are assumes to be one-hot codes (at most only one '1' exist) - * Considering this fact, there are only num_of_outputs conditions to be encoded. - * Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2)) + * Considering this fact, there are only num_of_outputs conditions to be + *encoded. Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2)) ***************************************************************************************/ ModuleId build_wl_memory_decoder_module(ModuleManager& module_manager, const DecoderLibrary& decoder_lib, @@ -158,10 +171,12 @@ ModuleId build_wl_memory_decoder_module(ModuleManager& module_manager, size_t data_size = decoder_lib.data_size(decoder); /* Create a name for the local encoder */ - std::string module_name = generate_memory_decoder_subckt_name(addr_size, data_size); + std::string module_name = + generate_memory_decoder_subckt_name(addr_size, data_size); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = module_manager.add_module(module_name); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(module_id)); /* Add enable port */ @@ -169,32 +184,40 @@ ModuleId build_wl_memory_decoder_module(ModuleManager& module_manager, module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); /* Add each input port */ BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), addr_size); - module_manager.add_port(module_id, addr_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(module_id, addr_port, + ModuleManager::MODULE_INPUT_PORT); /* Add each output port */ BasicPort data_port(std::string(DECODER_DATA_OUT_PORT_NAME), data_size); - module_manager.add_port(module_id, data_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(module_id, data_port, + ModuleManager::MODULE_OUTPUT_PORT); - /* Data port is registered. It should be outputted as - * output reg [lsb:msb] data + /* Data port is registered. It should be outputted as + * output reg [lsb:msb] data */ module_manager.set_port_is_register(module_id, data_port.get_name(), true); /* Add data_in port */ if (true == decoder_lib.use_data_inv_port(decoder)) { - BasicPort data_inv_port(std::string(DECODER_DATA_OUT_INV_PORT_NAME), data_size); - module_manager.add_port(module_id, data_inv_port, ModuleManager::MODULE_OUTPUT_PORT); + BasicPort data_inv_port(std::string(DECODER_DATA_OUT_INV_PORT_NAME), + data_size); + module_manager.add_port(module_id, data_inv_port, + ModuleManager::MODULE_OUTPUT_PORT); } /* Add readback port */ if (true == decoder_lib.use_readback(decoder)) { BasicPort readback_port(std::string(DECODER_READBACK_PORT_NAME), 1); - module_manager.add_port(module_id, readback_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(module_id, readback_port, + ModuleManager::MODULE_INPUT_PORT); } /* Add data read-enable port */ if (true == decoder_lib.use_readback(decoder)) { - BasicPort data_ren_port(std::string(DECODER_DATA_READ_ENABLE_PORT_NAME), data_size); - module_manager.add_port(module_id, data_ren_port, ModuleManager::MODULE_OUTPUT_PORT); - module_manager.set_port_is_register(module_id, data_ren_port.get_name(), true); + BasicPort data_ren_port(std::string(DECODER_DATA_READ_ENABLE_PORT_NAME), + data_size); + module_manager.add_port(module_id, data_ren_port, + ModuleManager::MODULE_OUTPUT_PORT); + module_manager.set_port_is_register(module_id, data_ren_port.get_name(), + true); } return module_id; @@ -203,8 +226,8 @@ ModuleId build_wl_memory_decoder_module(ModuleManager& module_manager, /*************************************************************************************** * Create a module for a decoder with a given output size * - * Inputs - * | | ... | + * Inputs + * | | ... | * v v v * +-----------+ * / \ @@ -213,24 +236,25 @@ ModuleId build_wl_memory_decoder_module(ModuleManager& module_manager, * | | | ... | | | * v v v v v v * Outputs - * + * * The outputs are assumes to be one-hot codes (at most only one '1' exist) - * Considering this fact, there are only num_of_outputs conditions to be encoded. - * Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2)) + * Considering this fact, there are only num_of_outputs conditions to be + *encoded. Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2)) ***************************************************************************************/ -static -void build_mux_local_decoder_module(ModuleManager& module_manager, - const DecoderLibrary& decoder_lib, - const DecoderId& decoder) { +static void build_mux_local_decoder_module(ModuleManager& module_manager, + const DecoderLibrary& decoder_lib, + const DecoderId& decoder) { /* Get the number of inputs */ size_t addr_size = decoder_lib.addr_size(decoder); size_t data_size = decoder_lib.data_size(decoder); /* Create a name for the local encoder */ - std::string module_name = generate_mux_local_decoder_subckt_name(addr_size, data_size); + std::string module_name = + generate_mux_local_decoder_subckt_name(addr_size, data_size); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = module_manager.add_module(module_name); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(module_id)); /* Label module usage */ @@ -239,32 +263,36 @@ void build_mux_local_decoder_module(ModuleManager& module_manager, /* Add module ports */ /* Add each input port */ BasicPort addr_port(generate_mux_local_decoder_addr_port_name(), addr_size); - module_manager.add_port(module_id, addr_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(module_id, addr_port, + ModuleManager::MODULE_INPUT_PORT); /* Add each output port */ BasicPort data_port(generate_mux_local_decoder_data_port_name(), data_size); - module_manager.add_port(module_id, data_port, ModuleManager::MODULE_OUTPUT_PORT); - /* Data port is registered. It should be outputted as - * output reg [lsb:msb] data + module_manager.add_port(module_id, data_port, + ModuleManager::MODULE_OUTPUT_PORT); + /* Data port is registered. It should be outputted as + * output reg [lsb:msb] data * Only applicable to data port size > 1 */ if (1 < data_port.get_width()) { module_manager.set_port_is_register(module_id, data_port.get_name(), true); } /* Add data_in port */ - BasicPort data_inv_port(generate_mux_local_decoder_data_inv_port_name(), data_size); + BasicPort data_inv_port(generate_mux_local_decoder_data_inv_port_name(), + data_size); VTR_ASSERT(true == decoder_lib.use_data_inv_port(decoder)); - module_manager.add_port(module_id, data_inv_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(module_id, data_inv_port, + ModuleManager::MODULE_OUTPUT_PORT); } /*************************************************************************************** - * This function will generate all the unique Verilog modules of local decoders for - * the multiplexers used in a FPGA fabric - * It will reach the goal in two steps: - * 1. Find the unique local decoders w.r.t. the number of inputs/outputs - * We will generate the subgraphs from the multiplexing graph of each multiplexers - * The number of memory bits is the number of outputs. - * From that we can infer the number of inputs of each local decoders. - * Here is an illustrative example of how local decoders are interfaced with multi-level MUXes + * This function will generate all the unique Verilog modules of local decoders + *for the multiplexers used in a FPGA fabric It will reach the goal in two + *steps: + * 1. Find the unique local decoders w.r.t. the number of inputs/outputs + * We will generate the subgraphs from the multiplexing graph of each + *multiplexers The number of memory bits is the number of outputs. From that we + *can infer the number of inputs of each local decoders. Here is an illustrative + *example of how local decoders are interfaced with multi-level MUXes * * +---------+ +---------+ * | Local | | Local | @@ -277,24 +305,26 @@ void build_mux_local_decoder_module(ModuleManager& module_manager, * | MUX Level 0 |--->| MUX Level 1 | * +--------------+ +--------------+ * 2. Generate local decoder Verilog modules using behavioral description. - * Note that the implementation of local decoders can be dependent on the technology - * and standard cell libraries. - * Therefore, behavioral Verilog is used and the local decoders should be synthesized - * before running the back-end flow for FPGA fabric - * See more details in the function print_verilog_mux_local_decoder() for more details + * Note that the implementation of local decoders can be dependent on the + *technology and standard cell libraries. Therefore, behavioral Verilog is used + *and the local decoders should be synthesized before running the back-end flow + *for FPGA fabric See more details in the function + *print_verilog_mux_local_decoder() for more details ***************************************************************************************/ void build_mux_local_decoder_modules(ModuleManager& module_manager, const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib) { - vtr::ScopedStartFinishTimer timer("Build local encoder (for multiplexers) modules"); + vtr::ScopedStartFinishTimer timer( + "Build local encoder (for multiplexers) modules"); /* Create a library for local encoders with different sizes */ DecoderLibrary decoder_lib; - - /* Find unique local decoders for unique branches shared by the multiplexers */ + + /* Find unique local decoders for unique branches shared by the multiplexers + */ for (auto mux : mux_lib.muxes()) { /* Local decoders are need only when users specify them */ - CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); + CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); /* If this MUX does not need local decoder, we skip it */ if (false == circuit_lib.mux_use_local_encoder(mux_circuit_model)) { continue; @@ -302,7 +332,8 @@ void build_mux_local_decoder_modules(ModuleManager& module_manager, const MuxGraph& mux_graph = mux_lib.mux_graph(mux); /* Create a mux graph for the branch circuit */ - std::vector branch_mux_graphs = mux_graph.build_mux_branch_graphs(); + std::vector branch_mux_graphs = + mux_graph.build_mux_branch_graphs(); /* Add the decoder to the decoder library */ for (auto branch_mux_graph : branch_mux_graphs) { /* The decoder size depends on the number of memories of a branch MUX. @@ -312,8 +343,8 @@ void build_mux_local_decoder_modules(ModuleManager& module_manager, if (0 == decoder_data_size) { continue; } - /* Try to find if the decoder already exists in the library, - * If there is no such decoder, add it to the library + /* Try to find if the decoder already exists in the library, + * If there is no such decoder, add it to the library */ add_mux_local_decoder_to_library(decoder_lib, decoder_data_size); } diff --git a/openfpga/src/fabric/build_decoder_modules.h b/openfpga/src/fabric/build_decoder_modules.h index 13d5091d4..2aeb40078 100644 --- a/openfpga/src/fabric/build_decoder_modules.h +++ b/openfpga/src/fabric/build_decoder_modules.h @@ -4,10 +4,10 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "module_manager.h" -#include "decoder_library.h" -#include "mux_library.h" #include "circuit_library.h" +#include "decoder_library.h" +#include "module_manager.h" +#include "mux_library.h" /******************************************************************** * Function declaration diff --git a/openfpga/src/fabric/build_device_module.cpp b/openfpga/src/fabric/build_device_module.cpp index 53ae7f3fc..bcfbfdf45 100644 --- a/openfpga/src/fabric/build_device_module.cpp +++ b/openfpga/src/fabric/build_device_module.cpp @@ -9,49 +9,46 @@ #include "vtr_time.h" /* Headers from openfpgashell library */ -#include "command_exit_codes.h" - -#include "build_essential_modules.h" #include "build_decoder_modules.h" -#include "build_mux_modules.h" -#include "build_lut_modules.h" -#include "build_wire_modules.h" -#include "build_memory_modules.h" +#include "build_device_module.h" +#include "build_essential_modules.h" #include "build_grid_modules.h" +#include "build_lut_modules.h" +#include "build_memory_modules.h" +#include "build_mux_modules.h" #include "build_routing_modules.h" #include "build_top_module.h" -#include "build_device_module.h" +#include "build_wire_modules.h" +#include "command_exit_codes.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * The main function to be called for building module graphs + * The main function to be called for building module graphs * for a FPGA fabric *******************************************************************/ -int build_device_module_graph(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - MemoryBankShiftRegisterBanks& blwl_sr_banks, - const OpenfpgaContext& openfpga_ctx, - const DeviceContext& vpr_device_ctx, - const bool& frame_view, - const bool& compress_routing, - const bool& duplicate_grid_pin, - const FabricKey& fabric_key, - const bool& generate_random_fabric_key, - const bool& verbose) { +int build_device_module_graph( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + MemoryBankShiftRegisterBanks& blwl_sr_banks, + const OpenfpgaContext& openfpga_ctx, const DeviceContext& vpr_device_ctx, + const bool& frame_view, const bool& compress_routing, + const bool& duplicate_grid_pin, const FabricKey& fabric_key, + const bool& generate_random_fabric_key, const bool& verbose) { vtr::ScopedStartFinishTimer timer("Build fabric module graph"); int status = CMD_EXEC_SUCCESS; - CircuitModelId sram_model = openfpga_ctx.arch().config_protocol.memory_model(); - VTR_ASSERT(true == openfpga_ctx.arch().circuit_lib.valid_model_id(sram_model)); + CircuitModelId sram_model = + openfpga_ctx.arch().config_protocol.memory_model(); + VTR_ASSERT(true == + openfpga_ctx.arch().circuit_lib.valid_model_id(sram_model)); /* Add constant generator modules: VDD and GND */ build_constant_generator_modules(module_manager); /* Register all the user-defined modules in the module manager - * This should be done prior to other steps in this function, + * This should be done prior to other steps in this function, * because they will be instanciated by other primitive modules */ build_user_defined_modules(module_manager, openfpga_ctx.arch().circuit_lib); @@ -59,12 +56,14 @@ int build_device_module_graph(ModuleManager& module_manager, /* Build elmentary modules */ build_essential_modules(module_manager, openfpga_ctx.arch().circuit_lib); - /* Build local encoders for multiplexers, this MUST be called before multiplexer building */ - build_mux_local_decoder_modules(module_manager, openfpga_ctx.mux_lib(), + /* Build local encoders for multiplexers, this MUST be called before + * multiplexer building */ + build_mux_local_decoder_modules(module_manager, openfpga_ctx.mux_lib(), openfpga_ctx.arch().circuit_lib); /* Build multiplexer modules */ - build_mux_modules(module_manager, openfpga_ctx.mux_lib(), openfpga_ctx.arch().circuit_lib); + build_mux_modules(module_manager, openfpga_ctx.mux_lib(), + openfpga_ctx.arch().circuit_lib); /* Build LUT modules */ build_lut_modules(module_manager, openfpga_ctx.arch().circuit_lib); @@ -73,72 +72,55 @@ int build_device_module_graph(ModuleManager& module_manager, build_wire_modules(module_manager, openfpga_ctx.arch().circuit_lib); /* Build memory modules */ - build_memory_modules(module_manager, - decoder_lib, - openfpga_ctx.mux_lib(), + build_memory_modules(module_manager, decoder_lib, openfpga_ctx.mux_lib(), openfpga_ctx.arch().circuit_lib, openfpga_ctx.arch().config_protocol.type()); /* Build grid and programmable block modules */ - build_grid_modules(module_manager, - decoder_lib, - vpr_device_ctx, + build_grid_modules(module_manager, decoder_lib, vpr_device_ctx, openfpga_ctx.vpr_device_annotation(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.mux_lib(), - openfpga_ctx.arch().config_protocol.type(), - sram_model, duplicate_grid_pin, verbose); + openfpga_ctx.arch().circuit_lib, openfpga_ctx.mux_lib(), + openfpga_ctx.arch().config_protocol.type(), sram_model, + duplicate_grid_pin, verbose); if (true == compress_routing) { - build_unique_routing_modules(module_manager, - decoder_lib, - vpr_device_ctx, - openfpga_ctx.vpr_device_annotation(), - openfpga_ctx.device_rr_gsb(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.arch().config_protocol.type(), - sram_model, verbose); + build_unique_routing_modules( + module_manager, decoder_lib, vpr_device_ctx, + openfpga_ctx.vpr_device_annotation(), openfpga_ctx.device_rr_gsb(), + openfpga_ctx.arch().circuit_lib, + openfpga_ctx.arch().config_protocol.type(), sram_model, verbose); } else { VTR_ASSERT_SAFE(false == compress_routing); - build_flatten_routing_modules(module_manager, - decoder_lib, - vpr_device_ctx, - openfpga_ctx.vpr_device_annotation(), - openfpga_ctx.device_rr_gsb(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.arch().config_protocol.type(), - sram_model, verbose); + build_flatten_routing_modules( + module_manager, decoder_lib, vpr_device_ctx, + openfpga_ctx.vpr_device_annotation(), openfpga_ctx.device_rr_gsb(), + openfpga_ctx.arch().circuit_lib, + openfpga_ctx.arch().config_protocol.type(), sram_model, verbose); } /* Build FPGA fabric top-level module */ - status = build_top_module(module_manager, - decoder_lib, - blwl_sr_banks, - openfpga_ctx.arch().circuit_lib, - 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(), - openfpga_ctx.arch().arch_direct, - openfpga_ctx.arch().config_protocol, - sram_model, - frame_view, compress_routing, duplicate_grid_pin, - fabric_key, generate_random_fabric_key); + status = build_top_module( + module_manager, decoder_lib, blwl_sr_banks, openfpga_ctx.arch().circuit_lib, + 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(), + openfpga_ctx.arch().arch_direct, openfpga_ctx.arch().config_protocol, + sram_model, frame_view, compress_routing, duplicate_grid_pin, fabric_key, + generate_random_fabric_key); if (CMD_EXEC_FATAL_ERROR == status) { return status; } /* Now a critical correction has to be done! - * In the module construction, we always use prefix of ports because they are binded - * to the ports in architecture description (logic blocks etc.) - * To interface with standard cell, we should - * rename the ports of primitive modules using lib_name instead of prefix - * (which have no children and are probably linked to a standard cell!) + * In the module construction, we always use prefix of ports because they are + * binded to the ports in architecture description (logic blocks etc.) To + * interface with standard cell, we should rename the ports of primitive + * modules using lib_name instead of prefix (which have no children and are + * probably linked to a standard cell!) */ - rename_primitive_module_port_names(module_manager, openfpga_ctx.arch().circuit_lib); + rename_primitive_module_port_names(module_manager, + openfpga_ctx.arch().circuit_lib); return status; } diff --git a/openfpga/src/fabric/build_device_module.h b/openfpga/src/fabric/build_device_module.h index 1c21fd069..11a28f1f3 100644 --- a/openfpga/src/fabric/build_device_module.h +++ b/openfpga/src/fabric/build_device_module.h @@ -4,9 +4,9 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" -#include "openfpga_context.h" #include "fabric_key.h" +#include "openfpga_context.h" +#include "vpr_context.h" /******************************************************************** * Function declaration @@ -15,17 +15,13 @@ /* begin namespace openfpga */ namespace openfpga { -int build_device_module_graph(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - MemoryBankShiftRegisterBanks& blwl_sr_banks, - const OpenfpgaContext& openfpga_ctx, - const DeviceContext& vpr_device_ctx, - const bool& frame_view, - const bool& compress_routing, - const bool& duplicate_grid_pin, - const FabricKey& fabric_key, - const bool& generate_random_fabric_key, - const bool& verbose); +int build_device_module_graph( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + MemoryBankShiftRegisterBanks& blwl_sr_banks, + const OpenfpgaContext& openfpga_ctx, const DeviceContext& vpr_device_ctx, + const bool& frame_view, const bool& compress_routing, + const bool& duplicate_grid_pin, const FabricKey& fabric_key, + const bool& generate_random_fabric_key, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_essential_modules.cpp b/openfpga/src/fabric/build_essential_modules.cpp index 3623ed259..4b462c3f1 100644 --- a/openfpga/src/fabric/build_essential_modules.cpp +++ b/openfpga/src/fabric/build_essential_modules.cpp @@ -4,44 +4,50 @@ *******************************************************************/ /* Headers from vtrutil library */ +#include "build_essential_modules.h" + +#include "module_manager_utils.h" +#include "openfpga_naming.h" #include "vtr_assert.h" #include "vtr_log.h" #include "vtr_time.h" -#include "openfpga_naming.h" -#include "module_manager_utils.h" -#include "build_essential_modules.h" - /* begin namespace openfpga */ namespace openfpga { /************************************************ - * Build a module of inverter or buffer - * or tapered buffer to a file + * Build a module of inverter or buffer + * or tapered buffer to a file ***********************************************/ -static -void build_invbuf_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model) { +static void build_invbuf_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model) { /* Find the input port, output port and global inputs*/ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); - std::vector global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector global_ports = + circuit_lib.model_global_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); /* Make sure: - * There is only 1 input port and 1 output port, + * There is only 1 input port and 1 output port, * each size of which is 1 */ - VTR_ASSERT( (1 == input_ports.size()) && (1 == circuit_lib.port_size(input_ports[0])) ); - VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + VTR_ASSERT((1 == input_ports.size()) && + (1 == circuit_lib.port_size(input_ports[0]))); + VTR_ASSERT((1 == output_ports.size()) && + (1 == circuit_lib.port_size(output_ports[0]))); /* TODO: move the check codes to check_circuit_library.h */ - /* If the circuit model is power-gated, we need to find at least one global config_enable signals */ - if (true == circuit_lib.is_power_gated(circuit_model)) { + /* If the circuit model is power-gated, we need to find at least one global + * config_enable signals */ + if (true == circuit_lib.is_power_gated(circuit_model)) { /* Check all the ports we have are good for a power-gated circuit model */ size_t num_err = 0; /* We need at least one global port */ - if (0 == global_ports.size()) { + if (0 == global_ports.size()) { num_err++; } /* All the global ports should be config_enable */ @@ -52,14 +58,18 @@ void build_invbuf_module(ModuleManager& module_manager, } /* Report errors if there are any */ if (0 < num_err) { - VTR_LOGF_ERROR(__FILE__, __LINE__, "Inverter/buffer circuit model '%s' is power-gated. At least one config-enable global port is required!\n", - circuit_lib.model_name(circuit_model).c_str()); + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Inverter/buffer circuit model '%s' is power-gated. At " + "least one config-enable global port is required!\n", + circuit_lib.model_name(circuit_model).c_str()); exit(1); } } - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = add_circuit_model_to_module_manager(module_manager, circuit_lib, circuit_model); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = add_circuit_model_to_module_manager( + module_manager, circuit_lib, circuit_model); VTR_ASSERT(true == module_manager.valid_module_id(module_id)); } @@ -67,94 +77,109 @@ void build_invbuf_module(ModuleManager& module_manager, * Build a module of a pass-gate, * either transmission-gate or pass-transistor ***********************************************/ -static -void build_passgate_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model) { +static void build_passgate_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model) { /* Find the input port, output port*/ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); - std::vector global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector global_ports = + circuit_lib.model_global_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); switch (circuit_lib.pass_gate_logic_type(circuit_model)) { - case CIRCUIT_MODEL_PASS_GATE_TRANSMISSION: - /* Make sure: - * There is only 3 input port (in, sel, selb), - * each size of which is 1 - */ - VTR_ASSERT( 3 == input_ports.size() ); - for (const auto& input_port : input_ports) { - VTR_ASSERT(1 == circuit_lib.port_size(input_port)); - } - break; - case CIRCUIT_MODEL_PASS_GATE_TRANSISTOR: - /* Make sure: - * There is only 2 input port (in, sel), - * each size of which is 1 - */ - VTR_ASSERT( 2 == input_ports.size() ); - for (const auto& input_port : input_ports) { - VTR_ASSERT(1 == circuit_lib.port_size(input_port)); - } - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid topology for circuit model '%s'!\n", - circuit_lib.model_name(circuit_model).c_str()); - exit(1); + case CIRCUIT_MODEL_PASS_GATE_TRANSMISSION: + /* Make sure: + * There is only 3 input port (in, sel, selb), + * each size of which is 1 + */ + VTR_ASSERT(3 == input_ports.size()); + for (const auto& input_port : input_ports) { + VTR_ASSERT(1 == circuit_lib.port_size(input_port)); + } + break; + case CIRCUIT_MODEL_PASS_GATE_TRANSISTOR: + /* Make sure: + * There is only 2 input port (in, sel), + * each size of which is 1 + */ + VTR_ASSERT(2 == input_ports.size()); + for (const auto& input_port : input_ports) { + VTR_ASSERT(1 == circuit_lib.port_size(input_port)); + } + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid topology for circuit model '%s'!\n", + circuit_lib.model_name(circuit_model).c_str()); + exit(1); } /* Make sure: - * There is only 1 output port, + * There is only 1 output port, * each size of which is 1 */ - VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + VTR_ASSERT((1 == output_ports.size()) && + (1 == circuit_lib.port_size(output_ports[0]))); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = add_circuit_model_to_module_manager(module_manager, circuit_lib, circuit_model); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = add_circuit_model_to_module_manager( + module_manager, circuit_lib, circuit_model); VTR_ASSERT(true == module_manager.valid_module_id(module_id)); } /************************************************ * Build a module of a logic gate * which are standard cells - * Supported gate types: - * 1. N-input AND + * Supported gate types: + * 1. N-input AND * 2. N-input OR * 3. 2-input MUX ***********************************************/ -static -void build_gate_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model) { +static void build_gate_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model) { /* Find the input port, output port*/ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); - std::vector global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector global_ports = + circuit_lib.model_global_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); /* Make sure: - * There is only 1 output port, + * There is only 1 output port, * each size of which is 1 */ - VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + VTR_ASSERT((1 == output_ports.size()) && + (1 == circuit_lib.port_size(output_ports[0]))); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = add_circuit_model_to_module_manager(module_manager, circuit_lib, circuit_model); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = add_circuit_model_to_module_manager( + module_manager, circuit_lib, circuit_model); VTR_ASSERT(true == module_manager.valid_module_id(module_id)); } - /************************************************ * Generate the modules for essential gates * include inverters, buffers, transmission-gates, * etc. ***********************************************/ -void build_essential_modules(ModuleManager& module_manager, +void build_essential_modules(ModuleManager& module_manager, const CircuitLibrary& circuit_lib) { - vtr::ScopedStartFinishTimer timer("Build essential (inverter/buffer/logic gate) modules"); + vtr::ScopedStartFinishTimer timer( + "Build essential (inverter/buffer/logic gate) modules"); for (const auto& circuit_model : circuit_lib.models()) { - /* Add essential modules upon on demand: only when it is not yet in the module library */ - ModuleId module = module_manager.find_module(circuit_lib.model_name(circuit_model)); + /* Add essential modules upon on demand: only when it is not yet in the + * module library */ + ModuleId module = + module_manager.find_module(circuit_lib.model_name(circuit_model)); if (true == module_manager.valid_module_id(module)) { continue; } @@ -179,44 +204,47 @@ void build_essential_modules(ModuleManager& module_manager, * Walk through the circuit library and add user-defined circuit models * to the module_manager ********************************************************************/ -void build_user_defined_modules(ModuleManager& module_manager, +void build_user_defined_modules(ModuleManager& module_manager, const CircuitLibrary& circuit_lib) { vtr::ScopedStartFinishTimer timer("Build user-defined modules"); /* Iterate over Verilog modules */ for (const auto& model : circuit_lib.models()) { /* We only care about user-defined models */ - if ( (true == circuit_lib.model_verilog_netlist(model).empty()) - && (true == circuit_lib.model_spice_netlist(model).empty()) ) { + if ((true == circuit_lib.model_verilog_netlist(model).empty()) && + (true == circuit_lib.model_spice_netlist(model).empty())) { continue; } - /* Skip Routing channel wire models because they need a different name. Do it later */ + /* Skip Routing channel wire models because they need a different name. Do + * it later */ if (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) { continue; } - /* Reach here, the model requires a user-defined Verilog netlist, - * Register it in the module_manager + /* Reach here, the model requires a user-defined Verilog netlist, + * Register it in the module_manager */ add_circuit_model_to_module_manager(module_manager, circuit_lib, model); } } /********************************************************************* - * This function will build a constant generator modules + * This function will build a constant generator modules * and add it to the module manager * It could be either * 1. VDD or 2. GND * Each module will have only one output port ********************************************************************/ -static -void build_constant_generator_module(ModuleManager& module_manager, - const size_t& const_value) { - ModuleId const_module = module_manager.add_module(generate_const_value_module_name(const_value)); +static void build_constant_generator_module(ModuleManager& module_manager, + const size_t& const_value) { + ModuleId const_module = + module_manager.add_module(generate_const_value_module_name(const_value)); /* Add one output port */ - BasicPort const_output_port(generate_const_value_module_output_port_name(const_value), 1); - module_manager.add_port(const_module, const_output_port, ModuleManager::MODULE_OUTPUT_PORT); + BasicPort const_output_port( + generate_const_value_module_output_port_name(const_value), 1); + module_manager.add_port(const_module, const_output_port, + ModuleManager::MODULE_OUTPUT_PORT); - /* Specify the usage of this module + /* Specify the usage of this module * 1: VDD * 0: GND */ @@ -229,7 +257,7 @@ void build_constant_generator_module(ModuleManager& module_manager, } /********************************************************************* - * This function will add two constant generator modules + * This function will add two constant generator modules * to the module manager * 1. VDD * 2. GND @@ -245,28 +273,29 @@ void build_constant_generator_modules(ModuleManager& module_manager) { } /********************************************************************* - * This function will rename the ports of primitive modules + * This function will rename the ports of primitive modules * using lib_name instead of prefix - * Primitive modules are defined as those modules in the module manager + * Primitive modules are defined as those modules in the module manager * which have user defined netlists ********************************************************************/ -void rename_primitive_module_port_names(ModuleManager& module_manager, +void rename_primitive_module_port_names(ModuleManager& module_manager, const CircuitLibrary& circuit_lib) { for (const CircuitModelId& model : circuit_lib.models()) { /* We only care about user-defined models */ - if ( (true == circuit_lib.model_verilog_netlist(model).empty()) - && (true == circuit_lib.model_spice_netlist(model).empty()) ) { + if ((true == circuit_lib.model_verilog_netlist(model).empty()) && + (true == circuit_lib.model_spice_netlist(model).empty())) { /* Exception circuit models as primitive cells * - Inverter, buffer, pass-gate logic, logic gate * which should be renamed even when auto-generated */ - if ( (CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(model)) - && (CIRCUIT_MODEL_PASSGATE != circuit_lib.model_type(model)) - && (CIRCUIT_MODEL_GATE != circuit_lib.model_type(model)) ) { + if ((CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(model)) && + (CIRCUIT_MODEL_PASSGATE != circuit_lib.model_type(model)) && + (CIRCUIT_MODEL_GATE != circuit_lib.model_type(model))) { continue; } } - /* Skip Routing channel wire models because they need a different name. Do it later */ + /* Skip Routing channel wire models because they need a different name. Do + * it later */ if (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) { continue; } @@ -277,12 +306,16 @@ void rename_primitive_module_port_names(ModuleManager& module_manager, /* Rename all the ports to use lib_name! */ for (const CircuitPortId& model_port : circuit_lib.model_ports(model)) { - /* Find the module port in module manager. We used prefix when creating the ports */ - ModulePortId module_port = module_manager.find_module_port(module, circuit_lib.port_prefix(model_port)); + /* Find the module port in module manager. We used prefix when creating + * the ports */ + ModulePortId module_port = module_manager.find_module_port( + module, circuit_lib.port_prefix(model_port)); /* We must find one! */ - VTR_ASSERT(true == module_manager.valid_module_port_id(module, module_port)); + VTR_ASSERT(true == + module_manager.valid_module_port_id(module, module_port)); /* Name it with lib_name */ - module_manager.set_module_port_name(module, module_port, circuit_lib.port_lib_name(model_port)); + module_manager.set_module_port_name( + module, module_port, circuit_lib.port_lib_name(model_port)); } } } diff --git a/openfpga/src/fabric/build_essential_modules.h b/openfpga/src/fabric/build_essential_modules.h index e7d348bc6..eb0fc2f2f 100644 --- a/openfpga/src/fabric/build_essential_modules.h +++ b/openfpga/src/fabric/build_essential_modules.h @@ -14,15 +14,15 @@ /* begin namespace openfpga */ namespace openfpga { -void build_essential_modules(ModuleManager& module_manager, +void build_essential_modules(ModuleManager& module_manager, const CircuitLibrary& circuit_lib); -void build_user_defined_modules(ModuleManager& module_manager, +void build_user_defined_modules(ModuleManager& module_manager, const CircuitLibrary& circuit_lib); void build_constant_generator_modules(ModuleManager& module_manager); -void rename_primitive_module_port_names(ModuleManager& module_manager, +void rename_primitive_module_port_names(ModuleManager& module_manager, const CircuitLibrary& circuit_lib); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_fabric_global_port_info.cpp b/openfpga/src/fabric/build_fabric_global_port_info.cpp index d439a7fdf..781752434 100644 --- a/openfpga/src/fabric/build_fabric_global_port_info.cpp +++ b/openfpga/src/fabric/build_fabric_global_port_info.cpp @@ -1,20 +1,19 @@ /******************************************************************** * This file includes functions that are used to build the global port * information for the top-level module of the FPGA fabric - * It helps OpenFPGA to build testbenches with the attributes of the global ports + * It helps OpenFPGA to build testbenches with the attributes of the global + *ports *******************************************************************/ -#include #include +#include /* Headers from vtrutil library */ -#include "vtr_assert.h" -#include "vtr_time.h" -#include "vtr_log.h" - -#include "openfpga_naming.h" - -#include "circuit_library_utils.h" #include "build_fabric_global_port_info.h" +#include "circuit_library_utils.h" +#include "openfpga_naming.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" /* begin namespace openfpga */ namespace openfpga { @@ -23,10 +22,9 @@ namespace openfpga { * Find all the GPIO ports in the grid module * and cache their port/pin index in the top-level module *******************************************************************/ -FabricGlobalPortInfo build_fabric_global_port_info(const ModuleManager& module_manager, - const ConfigProtocol& config_protocol, - const TileAnnotation& tile_annotation, - const CircuitLibrary& circuit_lib) { +FabricGlobalPortInfo build_fabric_global_port_info( + const ModuleManager& module_manager, const ConfigProtocol& config_protocol, + const TileAnnotation& tile_annotation, const CircuitLibrary& circuit_lib) { vtr::ScopedStartFinishTimer timer("Create global port info for top module"); FabricGlobalPortInfo fabric_global_port_info; @@ -41,29 +39,43 @@ FabricGlobalPortInfo build_fabric_global_port_info(const ModuleManager& module_m } /* Add the global ports from circuit library */ - for (const CircuitPortId& global_port : find_circuit_library_global_ports(circuit_lib)) { + for (const CircuitPortId& global_port : + find_circuit_library_global_ports(circuit_lib)) { /* We should find a port in the top module */ - ModulePortId module_port = module_manager.find_module_port(top_module, circuit_lib.port_prefix(global_port)); + ModulePortId module_port = module_manager.find_module_port( + top_module, circuit_lib.port_prefix(global_port)); /* Only add those ports have been defined in top-level module */ if (false == module_manager.valid_module_port_id(top_module, module_port)) { continue; } /* Add the port information */ - FabricGlobalPortId fabric_port = fabric_global_port_info.create_global_port(module_port); - fabric_global_port_info.set_global_port_is_clock(fabric_port, CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(global_port)); - fabric_global_port_info.set_global_port_is_reset(fabric_port, circuit_lib.port_is_reset(global_port)); - fabric_global_port_info.set_global_port_is_set(fabric_port, circuit_lib.port_is_set(global_port)); - fabric_global_port_info.set_global_port_is_prog(fabric_port, circuit_lib.port_is_prog(global_port)); - fabric_global_port_info.set_global_port_is_shift_register(fabric_port, circuit_lib.port_is_shift_register(global_port)); - fabric_global_port_info.set_global_port_is_config_enable(fabric_port, circuit_lib.port_is_config_enable(global_port)); - fabric_global_port_info.set_global_port_default_value(fabric_port, circuit_lib.port_default_value(global_port)); + FabricGlobalPortId fabric_port = + fabric_global_port_info.create_global_port(module_port); + fabric_global_port_info.set_global_port_is_clock( + fabric_port, + CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(global_port)); + fabric_global_port_info.set_global_port_is_reset( + fabric_port, circuit_lib.port_is_reset(global_port)); + fabric_global_port_info.set_global_port_is_set( + fabric_port, circuit_lib.port_is_set(global_port)); + fabric_global_port_info.set_global_port_is_prog( + fabric_port, circuit_lib.port_is_prog(global_port)); + fabric_global_port_info.set_global_port_is_shift_register( + fabric_port, circuit_lib.port_is_shift_register(global_port)); + fabric_global_port_info.set_global_port_is_config_enable( + fabric_port, circuit_lib.port_is_config_enable(global_port)); + fabric_global_port_info.set_global_port_default_value( + fabric_port, circuit_lib.port_default_value(global_port)); - /* Special for BL/WL shift register models: we should identify which clock belongs to BL and which clock belongs to WL */ - if (config_protocol.bl_memory_model() == circuit_lib.port_parent_model(global_port)) { + /* Special for BL/WL shift register models: we should identify which clock + * belongs to BL and which clock belongs to WL */ + if (config_protocol.bl_memory_model() == + circuit_lib.port_parent_model(global_port)) { fabric_global_port_info.set_global_port_is_bl(fabric_port, true); } - if (config_protocol.wl_memory_model() == circuit_lib.port_parent_model(global_port)) { + if (config_protocol.wl_memory_model() == + circuit_lib.port_parent_model(global_port)) { fabric_global_port_info.set_global_port_is_wl(fabric_port, true); } } @@ -71,28 +83,35 @@ FabricGlobalPortInfo build_fabric_global_port_info(const ModuleManager& module_m /* Add the global ports from tile annotation */ for (const TileGlobalPortId& global_port : tile_annotation.global_ports()) { /* We should find a port in the top module */ - ModulePortId module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(global_port)); + ModulePortId module_port = module_manager.find_module_port( + top_module, tile_annotation.global_port_name(global_port)); /* Only add those ports have been defined in top-level module */ if (false == module_manager.valid_module_port_id(top_module, module_port)) { continue; } /* Avoid adding redundant ports */ bool already_in_list = false; - for (const FabricGlobalPortId& port : fabric_global_port_info.global_ports()) { + for (const FabricGlobalPortId& port : + fabric_global_port_info.global_ports()) { if (module_port == fabric_global_port_info.global_module_port(port)) { already_in_list = true; break; } - } + } if (true == already_in_list) { continue; } /* Add the port information */ - FabricGlobalPortId fabric_port = fabric_global_port_info.create_global_port(module_port); - fabric_global_port_info.set_global_port_is_clock(fabric_port, tile_annotation.global_port_is_clock(global_port)); - fabric_global_port_info.set_global_port_is_reset(fabric_port, tile_annotation.global_port_is_reset(global_port)); - fabric_global_port_info.set_global_port_is_set(fabric_port, tile_annotation.global_port_is_set(global_port)); - fabric_global_port_info.set_global_port_default_value(fabric_port, tile_annotation.global_port_default_value(global_port)); + FabricGlobalPortId fabric_port = + fabric_global_port_info.create_global_port(module_port); + fabric_global_port_info.set_global_port_is_clock( + fabric_port, tile_annotation.global_port_is_clock(global_port)); + fabric_global_port_info.set_global_port_is_reset( + fabric_port, tile_annotation.global_port_is_reset(global_port)); + fabric_global_port_info.set_global_port_is_set( + fabric_port, tile_annotation.global_port_is_set(global_port)); + fabric_global_port_info.set_global_port_default_value( + fabric_port, tile_annotation.global_port_default_value(global_port)); } return fabric_global_port_info; diff --git a/openfpga/src/fabric/build_fabric_global_port_info.h b/openfpga/src/fabric/build_fabric_global_port_info.h index 6852a0249..e8cff31e0 100644 --- a/openfpga/src/fabric/build_fabric_global_port_info.h +++ b/openfpga/src/fabric/build_fabric_global_port_info.h @@ -6,10 +6,11 @@ *******************************************************************/ #include -#include "tile_annotation.h" + #include "circuit_library.h" #include "fabric_global_port_info.h" #include "module_manager.h" +#include "tile_annotation.h" /******************************************************************** * Function declaration @@ -18,10 +19,9 @@ /* begin namespace openfpga */ namespace openfpga { -FabricGlobalPortInfo build_fabric_global_port_info(const ModuleManager& module_manager, - const ConfigProtocol& config_protocol, - const TileAnnotation& tile_annotation, - const CircuitLibrary& circuit_lib); +FabricGlobalPortInfo build_fabric_global_port_info( + const ModuleManager& module_manager, const ConfigProtocol& config_protocol, + const TileAnnotation& tile_annotation, const CircuitLibrary& circuit_lib); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_fabric_io_location_map.cpp b/openfpga/src/fabric/build_fabric_io_location_map.cpp index 50f56dc25..710ce4e5d 100644 --- a/openfpga/src/fabric/build_fabric_io_location_map.cpp +++ b/openfpga/src/fabric/build_fabric_io_location_map.cpp @@ -4,23 +4,21 @@ * It helps OpenFPGA to link the I/O port index in top-level module * to the VPR I/O mapping results *******************************************************************/ -#include #include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from vpr library */ -#include "vpr_utils.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" - +#include "build_fabric_io_location_map.h" #include "module_manager_utils.h" #include "openfpga_device_grid_utils.h" -#include "build_fabric_io_location_map.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "vpr_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -29,11 +27,14 @@ namespace openfpga { * Find all the GPIO ports in the grid module * and cache their port/pin index in the top-level module * - * .. note:: The I/O sequence(indexing) is already determined in the io_children() list of top-level module. Here we just build a fast lookup from (x, y, z) coordinate to the actual indices + * .. note:: The I/O sequence(indexing) is already determined in the + *io_children() list of top-level module. Here we just build a fast lookup from + *(x, y, z) coordinate to the actual indices *******************************************************************/ IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager, const DeviceGrid& grids) { - vtr::ScopedStartFinishTimer timer("Create I/O location mapping for top module"); + vtr::ScopedStartFinishTimer timer( + "Create I/O location mapping for top module"); IoLocationMap io_location_map; @@ -44,18 +45,20 @@ IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager, VTR_ASSERT(true == module_manager.valid_module_id(top_module)); /* Walk through the I/O child list */ - for (size_t ichild = 0; ichild < module_manager.io_children(top_module).size(); ++ichild) { + for (size_t ichild = 0; + ichild < module_manager.io_children(top_module).size(); ++ichild) { ModuleId child = module_manager.io_children(top_module)[ichild]; - vtr::Point coord = module_manager.io_child_coordinates(top_module)[ichild]; + vtr::Point coord = + module_manager.io_child_coordinates(top_module)[ichild]; /* Bypass EMPTY grid */ if (true == is_empty_type(grids[coord.x()][coord.y()].type)) { continue; - } + } /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ - if ( (0 < grids[coord.x()][coord.y()].width_offset) - || (0 < grids[coord.x()][coord.y()].height_offset)) { + if ((0 < grids[coord.x()][coord.y()].width_offset) || + (0 < grids[coord.x()][coord.y()].height_offset)) { continue; } @@ -66,20 +69,32 @@ IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager, /* MUST DO: register in io location mapping! * I/O location mapping is a critical look-up for testbench generators */ - if (size_t(grids[coord.x()][coord.y()].type->capacity) != module_manager.io_children(child).size()) { - VTR_LOG("%s[%ld][%ld] capacity: %d while io_child number is %d", grids[coord.x()][coord.y()].type->name, coord.x(), coord.y(), grids[coord.x()][coord.y()].type->capacity, module_manager.io_children(child).size()); + if (size_t(grids[coord.x()][coord.y()].type->capacity) != + module_manager.io_children(child).size()) { + VTR_LOG("%s[%ld][%ld] capacity: %d while io_child number is %d", + grids[coord.x()][coord.y()].type->name, coord.x(), coord.y(), + grids[coord.x()][coord.y()].type->capacity, + module_manager.io_children(child).size()); } - VTR_ASSERT(size_t(grids[coord.x()][coord.y()].type->capacity) == module_manager.io_children(child).size()); - for (size_t isubchild = 0; isubchild < module_manager.io_children(child).size(); ++isubchild) { - vtr::Point subchild_coord = module_manager.io_child_coordinates(child)[isubchild]; + VTR_ASSERT(size_t(grids[coord.x()][coord.y()].type->capacity) == + module_manager.io_children(child).size()); + for (size_t isubchild = 0; + isubchild < module_manager.io_children(child).size(); ++isubchild) { + vtr::Point subchild_coord = + module_manager.io_child_coordinates(child)[isubchild]; - for (const ModuleManager::e_module_port_type& module_io_port_type : MODULE_IO_PORT_TYPES) { - for (const ModulePortId& gpio_port_id : module_manager.module_port_ids_by_type(child, module_io_port_type)) { + for (const ModuleManager::e_module_port_type& module_io_port_type : + MODULE_IO_PORT_TYPES) { + for (const ModulePortId& gpio_port_id : + module_manager.module_port_ids_by_type(child, + module_io_port_type)) { /* Only care mappable I/O */ - if (false == module_manager.port_is_mappable_io(child, gpio_port_id)) { + if (false == + module_manager.port_is_mappable_io(child, gpio_port_id)) { continue; } - const BasicPort& gpio_port = module_manager.module_port(child, gpio_port_id); + const BasicPort& gpio_port = + module_manager.module_port(child, gpio_port_id); auto curr_io_index = io_counter.find(gpio_port.get_name()); /* Index always start from zero */ @@ -96,14 +111,19 @@ IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager, } /* Check all the GPIO ports in the top-level module has been mapped */ - for (const ModuleManager::e_module_port_type& module_io_port_type : MODULE_IO_PORT_TYPES) { - for (const ModulePortId& gpio_port_id : module_manager.module_port_ids_by_type(top_module, module_io_port_type)) { + for (const ModuleManager::e_module_port_type& module_io_port_type : + MODULE_IO_PORT_TYPES) { + for (const ModulePortId& gpio_port_id : + module_manager.module_port_ids_by_type(top_module, + module_io_port_type)) { /* Only care mappable I/O */ - if (false == module_manager.port_is_mappable_io(top_module, gpio_port_id)) { + if (false == + module_manager.port_is_mappable_io(top_module, gpio_port_id)) { continue; } - - const BasicPort& gpio_port = module_manager.module_port(top_module, gpio_port_id); + + const BasicPort& gpio_port = + module_manager.module_port(top_module, gpio_port_id); VTR_ASSERT(io_counter[gpio_port.get_name()] == gpio_port.get_width()); } } diff --git a/openfpga/src/fabric/build_fabric_io_location_map.h b/openfpga/src/fabric/build_fabric_io_location_map.h index 32482667f..d84060390 100644 --- a/openfpga/src/fabric/build_fabric_io_location_map.h +++ b/openfpga/src/fabric/build_fabric_io_location_map.h @@ -6,6 +6,7 @@ *******************************************************************/ #include + #include "device_grid.h" #include "io_location_map.h" #include "module_manager.h" diff --git a/openfpga/src/fabric/build_grid_module_duplicated_pins.cpp b/openfpga/src/fabric/build_grid_module_duplicated_pins.cpp index 01988adb7..451500c0e 100644 --- a/openfpga/src/fabric/build_grid_module_duplicated_pins.cpp +++ b/openfpga/src/fabric/build_grid_module_duplicated_pins.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * This file includes functions that are used to add duplicated + * This file includes functions that are used to add duplicated * pins to each side of a grid * * These functions are located in this file, being separated from @@ -14,15 +14,12 @@ #include "vtr_assert.h" /* Headers from vpr library */ -#include "vpr_utils.h" - -#include "openfpga_naming.h" -#include "openfpga_interconnect_types.h" - -#include "openfpga_physical_tile_utils.h" - -#include "build_grid_module_utils.h" #include "build_grid_module_duplicated_pins.h" +#include "build_grid_module_utils.h" +#include "openfpga_interconnect_types.h" +#include "openfpga_naming.h" +#include "openfpga_physical_tile_utils.h" +#include "vpr_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -33,14 +30,15 @@ namespace openfpga { * They are driven by the same pin, e.g., pinA in the child module * But in this top module, we will create two pins, each of which indicates * the physical location of pin. - * Take the following example: + * Take the following example: * One is called pinA_upper which is located close to the top side of this grid - * The other is called pinA_lower which is located close to the bottom side of this grid + * The other is called pinA_lower which is located close to the bottom side of + *this grid * * Similarly, we duplicate pins at TOP, RIGHT, BOTTOM and LEFT sides. - * For LEFT side, upper and lower pins carry the indication in physical location as RIGHT side. - * For TOP and BOTTOM side, upper pin is located close to the left side of a grid, while lower - * pin is located close to the right side of a grid + * For LEFT side, upper and lower pins carry the indication in physical location + *as RIGHT side. For TOP and BOTTOM side, upper pin is located close to the left + *side of a grid, while lower pin is located close to the right side of a grid * * pinB_upper pinB_lower * ^ ^ @@ -48,28 +46,28 @@ namespace openfpga { * ---------------+ * |--->pinA_upper * | - * Grid | + * Grid | * | * |--->pinA_lower * ---------------+ *******************************************************************/ -void add_grid_module_duplicated_pb_type_ports(ModuleManager& module_manager, - const ModuleId& grid_module, - const VprDeviceAnnotation& vpr_device_annotation, - t_physical_tile_type_ptr grid_type_descriptor, - const e_side& border_side) { +void add_grid_module_duplicated_pb_type_ports( + ModuleManager& module_manager, const ModuleId& grid_module, + const VprDeviceAnnotation& vpr_device_annotation, + t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side) { /* Ensure that we have a valid grid_type_descriptor */ VTR_ASSERT(false == is_empty_type(grid_type_descriptor)); /* Find the pin side for I/O grids*/ std::vector grid_pin_sides; /* For I/O grids, we care only one side - * Otherwise, we will iterate all the 4 sides + * Otherwise, we will iterate all the 4 sides */ if (true == is_io_type(grid_type_descriptor)) { - grid_pin_sides = find_grid_module_pin_sides(grid_type_descriptor, border_side); + grid_pin_sides = + find_grid_module_pin_sides(grid_type_descriptor, border_side); } else { - grid_pin_sides = {TOP, RIGHT, BOTTOM, LEFT}; + grid_pin_sides = {TOP, RIGHT, BOTTOM, LEFT}; } /* Create a map between pin class type and grid pin direction */ @@ -82,45 +80,61 @@ void add_grid_module_duplicated_pb_type_ports(ModuleManager& module_manager, for (int iwidth = 0; iwidth < grid_type_descriptor->width; ++iwidth) { for (int iheight = 0; iheight < grid_type_descriptor->height; ++iheight) { for (int ipin = 0; ipin < grid_type_descriptor->num_pins; ++ipin) { - if (true != grid_type_descriptor->pinloc[iwidth][iheight][side][ipin]) { + if (true != + grid_type_descriptor->pinloc[iwidth][iheight][side][ipin]) { continue; } /* Reach here, it means this pin is on this side */ int class_id = grid_type_descriptor->pin_class[ipin]; - e_pin_type pin_class_type = grid_type_descriptor->class_inf[class_id].type; + e_pin_type pin_class_type = + grid_type_descriptor->class_inf[class_id].type; - BasicPort pin_info = vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor, ipin); + BasicPort pin_info = + vpr_device_annotation.physical_tile_pin_port_info( + grid_type_descriptor, ipin); VTR_ASSERT(true == pin_info.is_valid()); - int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(grid_type_descriptor, ipin); - VTR_ASSERT(OPEN != subtile_index && subtile_index < grid_type_descriptor->capacity); - /* Generate the pin name - * For each RECEIVER PIN or DRIVER PIN for direct connection, + int subtile_index = + vpr_device_annotation.physical_tile_pin_subtile_index( + grid_type_descriptor, ipin); + VTR_ASSERT(OPEN != subtile_index && + subtile_index < grid_type_descriptor->capacity); + /* Generate the pin name + * For each RECEIVER PIN or DRIVER PIN for direct connection, * we do not duplicate in these cases */ - if ( (RECEIVER == pin_class_type) - /* Xifan: I assume that each direct connection pin must have Fc=0. */ - || ( (DRIVER == pin_class_type) - && (0. == find_physical_tile_pin_Fc(grid_type_descriptor, ipin)) ) ) { - std::string port_name = generate_grid_port_name(iwidth, iheight, subtile_index, side, pin_info); + if ((RECEIVER == pin_class_type) + /* Xifan: I assume that each direct connection pin must have Fc=0. + */ + || + ((DRIVER == pin_class_type) && + (0. == find_physical_tile_pin_Fc(grid_type_descriptor, ipin)))) { + std::string port_name = generate_grid_port_name( + iwidth, iheight, subtile_index, side, pin_info); BasicPort grid_port(port_name, 0, 0); /* Add the port to the module */ - module_manager.add_port(grid_module, grid_port, pin_type2type_map[pin_class_type]); + module_manager.add_port(grid_module, grid_port, + pin_type2type_map[pin_class_type]); } else { /* For each DRIVER pin, we create two copies. - * One with a postfix of upper, indicating it is located on the upper part of a side - * The other with a postfix of lower, indicating it is located on the lower part of a side + * One with a postfix of upper, indicating it is located on the + * upper part of a side The other with a postfix of lower, + * indicating it is located on the lower part of a side */ VTR_ASSERT(DRIVER == pin_class_type); - std::string upper_port_name = generate_grid_duplicated_port_name(iwidth, iheight, subtile_index, side, pin_info, true); + std::string upper_port_name = generate_grid_duplicated_port_name( + iwidth, iheight, subtile_index, side, pin_info, true); BasicPort grid_upper_port(upper_port_name, 0, 0); /* Add the port to the module */ - module_manager.add_port(grid_module, grid_upper_port, pin_type2type_map[pin_class_type]); + module_manager.add_port(grid_module, grid_upper_port, + pin_type2type_map[pin_class_type]); - std::string lower_port_name = generate_grid_duplicated_port_name(iwidth, iheight, subtile_index, side, pin_info, false); + std::string lower_port_name = generate_grid_duplicated_port_name( + iwidth, iheight, subtile_index, side, pin_info, false); BasicPort grid_lower_port(lower_port_name, 0, 0); /* Add the port to the module */ - module_manager.add_port(grid_module, grid_lower_port, pin_type2type_map[pin_class_type]); + module_manager.add_port(grid_module, grid_lower_port, + pin_type2type_map[pin_class_type]); } - } + } } } } @@ -128,174 +142,199 @@ void add_grid_module_duplicated_pb_type_ports(ModuleManager& module_manager, /******************************************************************** * Add module nets to connect a port of child pb_module - * to the duplicated pins of grid module - * Note: This function SHOULD be ONLY applied to pb_graph output pins + * to the duplicated pins of grid module + * Note: This function SHOULD be ONLY applied to pb_graph output pins * of the child module. * For each such pin, we connect it to two outputs of the grid module * one is named after "upper", and the other is named after "lower" *******************************************************************/ -static -void add_grid_module_net_connect_duplicated_pb_graph_pin(ModuleManager& module_manager, - const ModuleId& grid_module, - const ModuleId& child_module, - const size_t& child_instance, - const VprDeviceAnnotation& vpr_device_annotation, - t_physical_tile_type_ptr grid_type_descriptor, - t_pb_graph_pin* pb_graph_pin, - const e_side& border_side, - const e_pin2pin_interc_type& pin2pin_interc_type) { +static void add_grid_module_net_connect_duplicated_pb_graph_pin( + ModuleManager& module_manager, const ModuleId& grid_module, + const ModuleId& child_module, const size_t& child_instance, + const VprDeviceAnnotation& vpr_device_annotation, + t_physical_tile_type_ptr grid_type_descriptor, t_pb_graph_pin* pb_graph_pin, + const e_side& border_side, const e_pin2pin_interc_type& pin2pin_interc_type) { /* Make sure this is ONLY applied to output pins */ VTR_ASSERT(OUTPUT2OUTPUT_INTERC == pin2pin_interc_type); - + /* Find the pin side for I/O grids*/ std::vector grid_pin_sides; /* For I/O grids, we care only one side - * Otherwise, we will iterate all the 4 sides + * Otherwise, we will iterate all the 4 sides */ if (true == is_io_type(grid_type_descriptor)) { - grid_pin_sides = find_grid_module_pin_sides(grid_type_descriptor, border_side); + grid_pin_sides = + find_grid_module_pin_sides(grid_type_descriptor, border_side); } else { - grid_pin_sides = {TOP, RIGHT, BOTTOM, LEFT}; + grid_pin_sides = {TOP, RIGHT, BOTTOM, LEFT}; } /* num_pins/capacity = the number of pins that each type_descriptor has. * Capacity defines the number of type_descriptors in each grid - * so the pin index at grid level = pin_index_in_type_descriptor - * + type_descriptor_index_in_capacity * num_pins_per_type_descriptor + * so the pin index at grid level = pin_index_in_type_descriptor + * + type_descriptor_index_in_capacity * + * num_pins_per_type_descriptor */ - size_t grid_pin_index = pb_graph_pin->pin_count_in_cluster - + child_instance * grid_type_descriptor->num_pins / grid_type_descriptor->capacity; + size_t grid_pin_index = pb_graph_pin->pin_count_in_cluster + + child_instance * grid_type_descriptor->num_pins / + grid_type_descriptor->capacity; int pin_width = grid_type_descriptor->pin_width_offset[grid_pin_index]; int pin_height = grid_type_descriptor->pin_height_offset[grid_pin_index]; - BasicPort pin_info = vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor, grid_pin_index); + BasicPort pin_info = vpr_device_annotation.physical_tile_pin_port_info( + grid_type_descriptor, grid_pin_index); VTR_ASSERT(true == pin_info.is_valid()); - int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(grid_type_descriptor, grid_pin_index); - VTR_ASSERT(OPEN != subtile_index && subtile_index < grid_type_descriptor->capacity); + int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index( + grid_type_descriptor, grid_pin_index); + VTR_ASSERT(OPEN != subtile_index && + subtile_index < grid_type_descriptor->capacity); for (const e_side& side : grid_pin_sides) { - if (true != grid_type_descriptor->pinloc[pin_width][pin_height][side][grid_pin_index]) { + if (true != grid_type_descriptor + ->pinloc[pin_width][pin_height][side][grid_pin_index]) { continue; } /* Pins for direct connection are NOT duplicated. - * Follow the traditional recipe when adding nets! - * Xifan: I assume that each direct connection pin must have Fc=0. + * Follow the traditional recipe when adding nets! + * Xifan: I assume that each direct connection pin must have Fc=0. */ if (0. == find_physical_tile_pin_Fc(grid_type_descriptor, grid_pin_index)) { /* Create a net to connect the grid pin to child module pin */ ModuleNetId net = module_manager.create_module_net(grid_module); /* Find the port in grid_module */ - std::string grid_port_name = generate_grid_port_name(pin_width, pin_height, subtile_index, side, pin_info); - ModulePortId grid_module_port_id = module_manager.find_module_port(grid_module, grid_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(grid_module, grid_module_port_id)); + std::string grid_port_name = generate_grid_port_name( + pin_width, pin_height, subtile_index, side, pin_info); + ModulePortId grid_module_port_id = + module_manager.find_module_port(grid_module, grid_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id( + grid_module, grid_module_port_id)); - /* Grid port always has only 1 pin, it is assumed when adding these ports to the module - * if you need a change, please also change the port adding codes + /* Grid port always has only 1 pin, it is assumed when adding these ports + * to the module if you need a change, please also change the port adding + * codes */ size_t grid_module_pin_id = 0; /* Find the port in child module */ - std::string child_module_port_name = generate_pb_type_port_name(pb_graph_pin->port); - ModulePortId child_module_port_id = module_manager.find_module_port(child_module, child_module_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(child_module, child_module_port_id)); + std::string child_module_port_name = + generate_pb_type_port_name(pb_graph_pin->port); + ModulePortId child_module_port_id = + module_manager.find_module_port(child_module, child_module_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id( + child_module, child_module_port_id)); size_t child_module_pin_id = pb_graph_pin->pin_number; /* Add net sources and sinks: - * For output-to-output connection, net_source is pb_graph_pin, while net_sink is grid pin + * For output-to-output connection, net_source is pb_graph_pin, while + * net_sink is grid pin */ - module_manager.add_module_net_source(grid_module, net, child_module, child_instance, child_module_port_id, child_module_pin_id); - module_manager.add_module_net_sink(grid_module, net, grid_module, 0, grid_module_port_id, grid_module_pin_id); + module_manager.add_module_net_source(grid_module, net, child_module, + child_instance, child_module_port_id, + child_module_pin_id); + module_manager.add_module_net_sink(grid_module, net, grid_module, 0, + grid_module_port_id, + grid_module_pin_id); continue; } /* Reach here, it means this pin is on this side */ /* Create a net to connect the grid pin to child module pin */ ModuleNetId net = module_manager.create_module_net(grid_module); /* Find the upper port in grid_module */ - std::string grid_upper_port_name = generate_grid_duplicated_port_name(pin_width, pin_height, subtile_index, side, pin_info, true); - ModulePortId grid_module_upper_port_id = module_manager.find_module_port(grid_module, grid_upper_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(grid_module, grid_module_upper_port_id)); + std::string grid_upper_port_name = generate_grid_duplicated_port_name( + pin_width, pin_height, subtile_index, side, pin_info, true); + ModulePortId grid_module_upper_port_id = + module_manager.find_module_port(grid_module, grid_upper_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id( + grid_module, grid_module_upper_port_id)); /* Find the lower port in grid_module */ - std::string grid_lower_port_name = generate_grid_duplicated_port_name(pin_width, pin_height, subtile_index, side, pin_info, false); - ModulePortId grid_module_lower_port_id = module_manager.find_module_port(grid_module, grid_lower_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(grid_module, grid_module_lower_port_id)); + std::string grid_lower_port_name = generate_grid_duplicated_port_name( + pin_width, pin_height, subtile_index, side, pin_info, false); + ModulePortId grid_module_lower_port_id = + module_manager.find_module_port(grid_module, grid_lower_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id( + grid_module, grid_module_lower_port_id)); - /* Grid port always has only 1 pin, it is assumed when adding these ports to the module - * if you need a change, please also change the port adding codes + /* Grid port always has only 1 pin, it is assumed when adding these ports to + * the module if you need a change, please also change the port adding codes */ size_t grid_module_pin_id = 0; /* Find the port in child module */ - std::string child_module_port_name = generate_pb_type_port_name(pb_graph_pin->port); - ModulePortId child_module_port_id = module_manager.find_module_port(child_module, child_module_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(child_module, child_module_port_id)); + std::string child_module_port_name = + generate_pb_type_port_name(pb_graph_pin->port); + ModulePortId child_module_port_id = + module_manager.find_module_port(child_module, child_module_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id( + child_module, child_module_port_id)); size_t child_module_pin_id = pb_graph_pin->pin_number; /* Add net sources and sinks: - * For output-to-output connection, - * net_source is pb_graph_pin, + * For output-to-output connection, + * net_source is pb_graph_pin, * while net_sinks are grid upper pin and grid lower pin */ - module_manager.add_module_net_source(grid_module, net, child_module, child_instance, child_module_port_id, child_module_pin_id); - module_manager.add_module_net_sink(grid_module, net, grid_module, 0, grid_module_upper_port_id, grid_module_pin_id); - module_manager.add_module_net_sink(grid_module, net, grid_module, 0, grid_module_lower_port_id, grid_module_pin_id); + module_manager.add_module_net_source(grid_module, net, child_module, + child_instance, child_module_port_id, + child_module_pin_id); + module_manager.add_module_net_sink(grid_module, net, grid_module, 0, + grid_module_upper_port_id, + grid_module_pin_id); + module_manager.add_module_net_sink(grid_module, net, grid_module, 0, + grid_module_lower_port_id, + grid_module_pin_id); } } /******************************************************************** * Add module nets to connect a port of child pb_module - * to the duplicated ports of grid module + * to the duplicated ports of grid module *******************************************************************/ -void add_grid_module_nets_connect_duplicated_pb_type_ports(ModuleManager& module_manager, - const ModuleId& grid_module, - const ModuleId& child_module, - const size_t& child_instance, - const VprDeviceAnnotation& vpr_device_annotation, - t_physical_tile_type_ptr grid_type_descriptor, - const e_side& border_side) { +void add_grid_module_nets_connect_duplicated_pb_type_ports( + ModuleManager& module_manager, const ModuleId& grid_module, + const ModuleId& child_module, const size_t& child_instance, + const VprDeviceAnnotation& vpr_device_annotation, + t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side) { /* Ensure that we have a valid grid_type_descriptor */ VTR_ASSERT(false == is_empty_type(grid_type_descriptor)); - /* FIXME: Currently support only 1 equivalent site! Should clarify this limitation in documentation! */ + /* FIXME: Currently support only 1 equivalent site! Should clarify this + * limitation in documentation! */ for (const t_sub_tile& sub_tile : grid_type_descriptor->sub_tiles) { t_logical_block_type_ptr lb_type = sub_tile.equivalent_sites[0]; t_pb_graph_node* top_pb_graph_node = lb_type->pb_graph_head; - VTR_ASSERT(nullptr != top_pb_graph_node); + VTR_ASSERT(nullptr != top_pb_graph_node); for (int iport = 0; iport < top_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < top_pb_graph_node->num_input_pins[iport]; ++ipin) { - add_grid_module_net_connect_pb_graph_pin(module_manager, grid_module, - child_module, child_instance, - vpr_device_annotation, - grid_type_descriptor, - &(top_pb_graph_node->input_pins[iport][ipin]), - border_side, - INPUT2INPUT_INTERC); - + for (int ipin = 0; ipin < top_pb_graph_node->num_input_pins[iport]; + ++ipin) { + add_grid_module_net_connect_pb_graph_pin( + module_manager, grid_module, child_module, child_instance, + vpr_device_annotation, grid_type_descriptor, + &(top_pb_graph_node->input_pins[iport][ipin]), border_side, + INPUT2INPUT_INTERC); } } for (int iport = 0; iport < top_pb_graph_node->num_output_ports; ++iport) { - for (int ipin = 0; ipin < top_pb_graph_node->num_output_pins[iport]; ++ipin) { - add_grid_module_net_connect_duplicated_pb_graph_pin(module_manager, grid_module, - child_module, child_instance, - vpr_device_annotation, - grid_type_descriptor, - &(top_pb_graph_node->output_pins[iport][ipin]), - border_side, - OUTPUT2OUTPUT_INTERC); + for (int ipin = 0; ipin < top_pb_graph_node->num_output_pins[iport]; + ++ipin) { + add_grid_module_net_connect_duplicated_pb_graph_pin( + module_manager, grid_module, child_module, child_instance, + vpr_device_annotation, grid_type_descriptor, + &(top_pb_graph_node->output_pins[iport][ipin]), border_side, + OUTPUT2OUTPUT_INTERC); } } for (int iport = 0; iport < top_pb_graph_node->num_clock_ports; ++iport) { - for (int ipin = 0; ipin < top_pb_graph_node->num_clock_pins[iport]; ++ipin) { - add_grid_module_net_connect_pb_graph_pin(module_manager, grid_module, - child_module, child_instance, - vpr_device_annotation, - grid_type_descriptor, - &(top_pb_graph_node->clock_pins[iport][ipin]), - border_side, - INPUT2INPUT_INTERC); - } + for (int ipin = 0; ipin < top_pb_graph_node->num_clock_pins[iport]; + ++ipin) { + add_grid_module_net_connect_pb_graph_pin( + module_manager, grid_module, child_module, child_instance, + vpr_device_annotation, grid_type_descriptor, + &(top_pb_graph_node->clock_pins[iport][ipin]), border_side, + INPUT2INPUT_INTERC); + } } } } diff --git a/openfpga/src/fabric/build_grid_module_duplicated_pins.h b/openfpga/src/fabric/build_grid_module_duplicated_pins.h index f60aaf1c7..82067f2d0 100644 --- a/openfpga/src/fabric/build_grid_module_duplicated_pins.h +++ b/openfpga/src/fabric/build_grid_module_duplicated_pins.h @@ -4,10 +4,10 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "physical_types.h" #include "module_manager.h" -#include "vpr_device_annotation.h" #include "openfpga_side_manager.h" +#include "physical_types.h" +#include "vpr_device_annotation.h" /******************************************************************** * Function declaration @@ -16,19 +16,16 @@ /* begin namespace openfpga */ namespace openfpga { -void add_grid_module_duplicated_pb_type_ports(ModuleManager& module_manager, - const ModuleId& grid_module, - const VprDeviceAnnotation& vpr_device_annotation, - t_physical_tile_type_ptr grid_type_descriptor, - const e_side& border_side); +void add_grid_module_duplicated_pb_type_ports( + ModuleManager& module_manager, const ModuleId& grid_module, + const VprDeviceAnnotation& vpr_device_annotation, + t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side); -void add_grid_module_nets_connect_duplicated_pb_type_ports(ModuleManager& module_manager, - const ModuleId& grid_module, - const ModuleId& child_module, - const size_t& child_instance, - const VprDeviceAnnotation& vpr_device_annotation, - t_physical_tile_type_ptr grid_type_descriptor, - const e_side& border_side); +void add_grid_module_nets_connect_duplicated_pb_type_ports( + ModuleManager& module_manager, const ModuleId& grid_module, + const ModuleId& child_module, const size_t& child_instance, + const VprDeviceAnnotation& vpr_device_annotation, + t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_grid_module_utils.cpp b/openfpga/src/fabric/build_grid_module_utils.cpp index fb1844133..5a5f2c76e 100644 --- a/openfpga/src/fabric/build_grid_module_utils.cpp +++ b/openfpga/src/fabric/build_grid_module_utils.cpp @@ -8,11 +8,9 @@ #include "openfpga_side_manager.h" /* Headers from vpr library */ -#include "vpr_utils.h" - -#include "openfpga_naming.h" - #include "build_grid_module_utils.h" +#include "openfpga_naming.h" +#include "vpr_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -25,91 +23,115 @@ namespace openfpga { * 4. I/O grids on the left side of FPGA only have ports on its right side * 5. I/O grids in the center part of FPGA can have ports on any side *******************************************************************/ -std::vector find_grid_module_pin_sides(t_physical_tile_type_ptr grid_type_descriptor, - const e_side& border_side) { +std::vector find_grid_module_pin_sides( + t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side) { /* We must have an regular (non-I/O) type here */ VTR_ASSERT(true == is_io_type(grid_type_descriptor)); SideManager side_manager(border_side); if (NUM_SIDES == border_side) { - return {TOP, RIGHT, BOTTOM, LEFT}; + return {TOP, RIGHT, BOTTOM, LEFT}; } - return std::vector(1, side_manager.get_opposite()); + return std::vector(1, side_manager.get_opposite()); } /******************************************************************** * Add module nets to connect a port of child pb_module - * to the grid module + * to the grid module *******************************************************************/ -void add_grid_module_net_connect_pb_graph_pin(ModuleManager& module_manager, - const ModuleId& grid_module, - const ModuleId& child_module, - const size_t& child_instance, - const VprDeviceAnnotation& vpr_device_annotation, - t_physical_tile_type_ptr grid_type_descriptor, - t_pb_graph_pin* pb_graph_pin, - const e_side& border_side, - const e_pin2pin_interc_type& pin2pin_interc_type) { +void add_grid_module_net_connect_pb_graph_pin( + ModuleManager& module_manager, const ModuleId& grid_module, + const ModuleId& child_module, const size_t& child_instance, + const VprDeviceAnnotation& vpr_device_annotation, + t_physical_tile_type_ptr grid_type_descriptor, t_pb_graph_pin* pb_graph_pin, + const e_side& border_side, const e_pin2pin_interc_type& pin2pin_interc_type) { /* Find the pin side for I/O grids*/ std::vector grid_pin_sides; /* For I/O grids, we care only one side - * Otherwise, we will iterate all the 4 sides + * Otherwise, we will iterate all the 4 sides */ if (true == is_io_type(grid_type_descriptor)) { - grid_pin_sides = find_grid_module_pin_sides(grid_type_descriptor, border_side); + grid_pin_sides = + find_grid_module_pin_sides(grid_type_descriptor, border_side); } else { - grid_pin_sides = {TOP, RIGHT, BOTTOM, LEFT}; + grid_pin_sides = {TOP, RIGHT, BOTTOM, LEFT}; } - /* Note that each grid may contain a number of sub tiles, each type of which may a different capacity and number of pins - * We need to find the start pin index for a given z offset (instance id), denotes the index of the first pin regarding the current instance. - * The variable 'pin_count_in_cluster' represent the pin index in the context of current instance only. - * With the information above, we can then calculate the absolute pin index at grid-level (considering all the sub tiles). + /* Note that each grid may contain a number of sub tiles, each type of which + * may a different capacity and number of pins We need to find the start pin + * index for a given z offset (instance id), denotes the index of the first + * pin regarding the current instance. The variable 'pin_count_in_cluster' + * represent the pin index in the context of current instance only. With the + * information above, we can then calculate the absolute pin index at + * grid-level (considering all the sub tiles). */ - size_t grid_pin_index = pb_graph_pin->pin_count_in_cluster + vpr_device_annotation.physical_tile_z_to_start_pin_index(grid_type_descriptor, child_instance); + size_t grid_pin_index = + pb_graph_pin->pin_count_in_cluster + + vpr_device_annotation.physical_tile_z_to_start_pin_index( + grid_type_descriptor, child_instance); int pin_height = grid_type_descriptor->pin_height_offset[grid_pin_index]; int pin_width = grid_type_descriptor->pin_width_offset[grid_pin_index]; for (const e_side& side : grid_pin_sides) { - if (true != grid_type_descriptor->pinloc[pin_width][pin_height][side][grid_pin_index]) { + if (true != grid_type_descriptor + ->pinloc[pin_width][pin_height][side][grid_pin_index]) { continue; } /* Reach here, it means this pin is on this side */ /* Create a net to connect the grid pin to child module pin */ ModuleNetId net = module_manager.create_module_net(grid_module); /* Find the port in grid_module */ - BasicPort pin_info = vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor, grid_pin_index); + BasicPort pin_info = vpr_device_annotation.physical_tile_pin_port_info( + grid_type_descriptor, grid_pin_index); VTR_ASSERT(true == pin_info.is_valid()); - int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(grid_type_descriptor, grid_pin_index); - VTR_ASSERT(OPEN != subtile_index && subtile_index < grid_type_descriptor->capacity); - std::string grid_port_name = generate_grid_port_name(pin_width, pin_height, subtile_index, side, pin_info); - ModulePortId grid_module_port_id = module_manager.find_module_port(grid_module, grid_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(grid_module, grid_module_port_id)); - /* Grid port always has only 1 pin, it is assumed when adding these ports to the module - * if you need a change, please also change the port adding codes + int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index( + grid_type_descriptor, grid_pin_index); + VTR_ASSERT(OPEN != subtile_index && + subtile_index < grid_type_descriptor->capacity); + std::string grid_port_name = generate_grid_port_name( + pin_width, pin_height, subtile_index, side, pin_info); + ModulePortId grid_module_port_id = + module_manager.find_module_port(grid_module, grid_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id( + grid_module, grid_module_port_id)); + /* Grid port always has only 1 pin, it is assumed when adding these ports to + * the module if you need a change, please also change the port adding codes */ size_t grid_module_pin_id = 0; /* Find the port in child module */ - std::string child_module_port_name = generate_pb_type_port_name(pb_graph_pin->port); - ModulePortId child_module_port_id = module_manager.find_module_port(child_module, child_module_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(child_module, child_module_port_id)); + std::string child_module_port_name = + generate_pb_type_port_name(pb_graph_pin->port); + ModulePortId child_module_port_id = + module_manager.find_module_port(child_module, child_module_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id( + child_module, child_module_port_id)); size_t child_module_pin_id = pb_graph_pin->pin_number; /* Add net sources and sinks: - * For input-to-input connection, net_source is grid pin, while net_sink is pb_graph_pin - * For output-to-output connection, net_source is pb_graph_pin, while net_sink is grid pin + * For input-to-input connection, net_source is grid pin, while net_sink is + * pb_graph_pin For output-to-output connection, net_source is pb_graph_pin, + * while net_sink is grid pin */ switch (pin2pin_interc_type) { - case INPUT2INPUT_INTERC: - module_manager.add_module_net_source(grid_module, net, grid_module, 0, grid_module_port_id, grid_module_pin_id); - module_manager.add_module_net_sink(grid_module, net, child_module, child_instance, child_module_port_id, child_module_pin_id); - break; - case OUTPUT2OUTPUT_INTERC: - module_manager.add_module_net_source(grid_module, net, child_module, child_instance, child_module_port_id, child_module_pin_id); - module_manager.add_module_net_sink(grid_module, net, grid_module, 0, grid_module_port_id, grid_module_pin_id); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid pin-to-pin interconnection type!\n"); - exit(1); + case INPUT2INPUT_INTERC: + module_manager.add_module_net_source(grid_module, net, grid_module, 0, + grid_module_port_id, + grid_module_pin_id); + module_manager.add_module_net_sink(grid_module, net, child_module, + child_instance, child_module_port_id, + child_module_pin_id); + break; + case OUTPUT2OUTPUT_INTERC: + module_manager.add_module_net_source( + grid_module, net, child_module, child_instance, child_module_port_id, + child_module_pin_id); + module_manager.add_module_net_sink(grid_module, net, grid_module, 0, + grid_module_port_id, + grid_module_pin_id); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid pin-to-pin interconnection type!\n"); + exit(1); } } } diff --git a/openfpga/src/fabric/build_grid_module_utils.h b/openfpga/src/fabric/build_grid_module_utils.h index 5a2a17490..d93fc43ee 100644 --- a/openfpga/src/fabric/build_grid_module_utils.h +++ b/openfpga/src/fabric/build_grid_module_utils.h @@ -5,10 +5,9 @@ * Include header files that are required by function declaration *******************************************************************/ /* Headers from readarch library */ -#include "physical_types.h" - -#include "openfpga_interconnect_types.h" #include "module_manager.h" +#include "openfpga_interconnect_types.h" +#include "physical_types.h" #include "vpr_device_annotation.h" /******************************************************************** @@ -18,18 +17,16 @@ /* begin namespace openfpga */ namespace openfpga { -std::vector find_grid_module_pin_sides(t_physical_tile_type_ptr grid_type_descriptor, - const e_side& border_side); +std::vector find_grid_module_pin_sides( + t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side); -void add_grid_module_net_connect_pb_graph_pin(ModuleManager& module_manager, - const ModuleId& grid_module, - const ModuleId& child_module, - const size_t& child_instance, - const VprDeviceAnnotation& vpr_device_annotation, - t_physical_tile_type_ptr grid_type_descriptor, - t_pb_graph_pin* pb_graph_pin, - const e_side& border_side, - const enum e_pin2pin_interc_type& pin2pin_interc_type); +void add_grid_module_net_connect_pb_graph_pin( + ModuleManager& module_manager, const ModuleId& grid_module, + const ModuleId& child_module, const size_t& child_instance, + const VprDeviceAnnotation& vpr_device_annotation, + t_physical_tile_type_ptr grid_type_descriptor, t_pb_graph_pin* pb_graph_pin, + const e_side& border_side, + const enum e_pin2pin_interc_type& pin2pin_interc_type); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_grid_modules.cpp b/openfpga/src/fabric/build_grid_modules.cpp index 465b7db99..6773273f7 100644 --- a/openfpga/src/fabric/build_grid_modules.cpp +++ b/openfpga/src/fabric/build_grid_modules.cpp @@ -1,61 +1,58 @@ /******************************************************************** * This file includes functions to print Verilog modules for a Grid - * (CLBs, I/Os, heterogeneous blocks etc.) + * (CLBs, I/Os, heterogeneous blocks etc.) *******************************************************************/ #include #include /* Headers from vtrutil library */ +#include "vtr_assert.h" #include "vtr_geometry.h" #include "vtr_log.h" -#include "vtr_assert.h" #include "vtr_time.h" /* Headers from vpr library */ -#include "vpr_utils.h" - -#include "circuit_library_utils.h" -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" -#include "openfpga_interconnect_types.h" -#include "openfpga_physical_tile_utils.h" -#include "pb_type_utils.h" -#include "pb_graph_utils.h" -#include "module_manager_utils.h" - -#include "build_grid_module_utils.h" #include "build_grid_module_duplicated_pins.h" +#include "build_grid_module_utils.h" #include "build_grid_modules.h" +#include "circuit_library_utils.h" +#include "module_manager_utils.h" +#include "openfpga_interconnect_types.h" +#include "openfpga_naming.h" +#include "openfpga_physical_tile_utils.h" +#include "openfpga_reserved_words.h" +#include "pb_graph_utils.h" +#include "pb_type_utils.h" +#include "vpr_utils.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * Add ports/pins to a grid module - * This function will iterate over all the pins that are defined + * Add ports/pins to a grid module + * This function will iterate over all the pins that are defined * in type_descripter and give a name by its height, side and index * * In particular, for I/O grid, only part of the ports on required * on a specific side. *******************************************************************/ -static -void add_grid_module_pb_type_ports(ModuleManager& module_manager, - const ModuleId& grid_module, - const VprDeviceAnnotation& vpr_device_annotation, - t_physical_tile_type_ptr grid_type_descriptor, - const e_side& border_side) { +static void add_grid_module_pb_type_ports( + ModuleManager& module_manager, const ModuleId& grid_module, + const VprDeviceAnnotation& vpr_device_annotation, + t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side) { /* Ensure that we have a valid grid_type_descriptor */ VTR_ASSERT(nullptr != grid_type_descriptor); /* Find the pin side for I/O grids*/ std::vector grid_pin_sides; /* For I/O grids, we care only one side - * Otherwise, we will iterate all the 4 sides + * Otherwise, we will iterate all the 4 sides */ if (true == is_io_type(grid_type_descriptor)) { - grid_pin_sides = find_grid_module_pin_sides(grid_type_descriptor, border_side); + grid_pin_sides = + find_grid_module_pin_sides(grid_type_descriptor, border_side); } else { - grid_pin_sides = {TOP, RIGHT, BOTTOM, LEFT}; + grid_pin_sides = {TOP, RIGHT, BOTTOM, LEFT}; } /* Create a map between pin class type and grid pin direction */ @@ -68,89 +65,93 @@ void add_grid_module_pb_type_ports(ModuleManager& module_manager, for (int iwidth = 0; iwidth < grid_type_descriptor->width; ++iwidth) { for (int iheight = 0; iheight < grid_type_descriptor->height; ++iheight) { for (int ipin = 0; ipin < grid_type_descriptor->num_pins; ++ipin) { - if (true != grid_type_descriptor->pinloc[iwidth][iheight][side][ipin]) { + if (true != + grid_type_descriptor->pinloc[iwidth][iheight][side][ipin]) { continue; } /* Reach here, it means this pin is on this side */ int class_id = grid_type_descriptor->pin_class[ipin]; - e_pin_type pin_class_type = grid_type_descriptor->class_inf[class_id].type; - /* Generate the pin name, - * we give a empty coordinate but it will not be used (see details in the function + e_pin_type pin_class_type = + grid_type_descriptor->class_inf[class_id].type; + /* Generate the pin name, + * we give a empty coordinate but it will not be used (see details in + * the function */ - BasicPort pin_info = vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor, ipin); + BasicPort pin_info = + vpr_device_annotation.physical_tile_pin_port_info( + grid_type_descriptor, ipin); VTR_ASSERT(true == pin_info.is_valid()); - int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(grid_type_descriptor, ipin); - VTR_ASSERT(OPEN != subtile_index && subtile_index < grid_type_descriptor->capacity); - std::string port_name = generate_grid_port_name(iwidth, iheight, subtile_index, side, pin_info); + int subtile_index = + vpr_device_annotation.physical_tile_pin_subtile_index( + grid_type_descriptor, ipin); + VTR_ASSERT(OPEN != subtile_index && + subtile_index < grid_type_descriptor->capacity); + std::string port_name = generate_grid_port_name( + iwidth, iheight, subtile_index, side, pin_info); BasicPort grid_port(port_name, 0, 0); /* Add the port to the module */ - module_manager.add_port(grid_module, grid_port, pin_type2type_map[pin_class_type]); - } + module_manager.add_port(grid_module, grid_port, + pin_type2type_map[pin_class_type]); + } } } } } /******************************************************************** - * Add module nets to connect ports/pins of a grid module + * Add module nets to connect ports/pins of a grid module * to its child modules - * This function will iterate over all the pins that are defined + * This function will iterate over all the pins that are defined * in type_descripter and find the corresponding pin in the top - * pb_graph_node of the grid + * pb_graph_node of the grid *******************************************************************/ -static -void add_grid_module_nets_connect_pb_type_ports(ModuleManager& module_manager, - const ModuleId& grid_module, - const ModuleId& child_module, - const size_t& child_instance, - const VprDeviceAnnotation& vpr_device_annotation, - t_physical_tile_type_ptr grid_type_descriptor, - const e_side& border_side) { +static void add_grid_module_nets_connect_pb_type_ports( + ModuleManager& module_manager, const ModuleId& grid_module, + const ModuleId& child_module, const size_t& child_instance, + const VprDeviceAnnotation& vpr_device_annotation, + t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side) { /* Ensure that we have a valid grid_type_descriptor */ VTR_ASSERT(nullptr != grid_type_descriptor); - /* FIXME: Currently support only 1 equivalent site! Should clarify this limitation in documentation! */ + /* FIXME: Currently support only 1 equivalent site! Should clarify this + * limitation in documentation! */ for (const t_sub_tile& sub_tile : grid_type_descriptor->sub_tiles) { VTR_ASSERT(sub_tile.equivalent_sites.size() == 1); t_logical_block_type_ptr lb_type = sub_tile.equivalent_sites[0]; t_pb_graph_node* top_pb_graph_node = lb_type->pb_graph_head; - VTR_ASSERT(nullptr != top_pb_graph_node); + VTR_ASSERT(nullptr != top_pb_graph_node); for (int iport = 0; iport < top_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < top_pb_graph_node->num_input_pins[iport]; ++ipin) { - add_grid_module_net_connect_pb_graph_pin(module_manager, grid_module, - child_module, child_instance, - vpr_device_annotation, - grid_type_descriptor, - &(top_pb_graph_node->input_pins[iport][ipin]), - border_side, - INPUT2INPUT_INTERC); - + for (int ipin = 0; ipin < top_pb_graph_node->num_input_pins[iport]; + ++ipin) { + add_grid_module_net_connect_pb_graph_pin( + module_manager, grid_module, child_module, child_instance, + vpr_device_annotation, grid_type_descriptor, + &(top_pb_graph_node->input_pins[iport][ipin]), border_side, + INPUT2INPUT_INTERC); } } for (int iport = 0; iport < top_pb_graph_node->num_output_ports; ++iport) { - for (int ipin = 0; ipin < top_pb_graph_node->num_output_pins[iport]; ++ipin) { - add_grid_module_net_connect_pb_graph_pin(module_manager, grid_module, - child_module, child_instance, - vpr_device_annotation, - grid_type_descriptor, - &(top_pb_graph_node->output_pins[iport][ipin]), - border_side, - OUTPUT2OUTPUT_INTERC); + for (int ipin = 0; ipin < top_pb_graph_node->num_output_pins[iport]; + ++ipin) { + add_grid_module_net_connect_pb_graph_pin( + module_manager, grid_module, child_module, child_instance, + vpr_device_annotation, grid_type_descriptor, + &(top_pb_graph_node->output_pins[iport][ipin]), border_side, + OUTPUT2OUTPUT_INTERC); } } for (int iport = 0; iport < top_pb_graph_node->num_clock_ports; ++iport) { - for (int ipin = 0; ipin < top_pb_graph_node->num_clock_pins[iport]; ++ipin) { - add_grid_module_net_connect_pb_graph_pin(module_manager, grid_module, - child_module, child_instance, - vpr_device_annotation, - grid_type_descriptor, - &(top_pb_graph_node->clock_pins[iport][ipin]), - border_side, - INPUT2INPUT_INTERC); - } + for (int ipin = 0; ipin < top_pb_graph_node->num_clock_pins[iport]; + ++ipin) { + add_grid_module_net_connect_pb_graph_pin( + module_manager, grid_module, child_module, child_instance, + vpr_device_annotation, grid_type_descriptor, + &(top_pb_graph_node->clock_pins[iport][ipin]), border_side, + INPUT2INPUT_INTERC); + } } } } @@ -159,46 +160,60 @@ void add_grid_module_nets_connect_pb_type_ports(ModuleManager& module_manager, * Add module nets between primitive module and its internal circuit module * This is only applicable to the primitive module of a grid *******************************************************************/ -static -void add_primitive_module_fpga_global_io_port(ModuleManager& module_manager, - const ModuleId& primitive_module, - const ModuleId& logic_module, - const size_t& logic_instance_id, - const ModuleManager::e_module_port_type& module_io_port_type, - const CircuitLibrary& circuit_lib, - const CircuitModelId& primitive_model, - const CircuitPortId& circuit_port) { - BasicPort module_port(generate_fpga_global_io_port_name(std::string(GIO_INOUT_PREFIX), circuit_lib, primitive_model, circuit_port), circuit_lib.port_size(circuit_port)); - ModulePortId primitive_io_port_id = module_manager.add_port(primitive_module, module_port, module_io_port_type); +static void add_primitive_module_fpga_global_io_port( + ModuleManager& module_manager, const ModuleId& primitive_module, + const ModuleId& logic_module, const size_t& logic_instance_id, + const ModuleManager::e_module_port_type& module_io_port_type, + const CircuitLibrary& circuit_lib, const CircuitModelId& primitive_model, + const CircuitPortId& circuit_port) { + BasicPort module_port(generate_fpga_global_io_port_name( + std::string(GIO_INOUT_PREFIX), circuit_lib, + primitive_model, circuit_port), + circuit_lib.port_size(circuit_port)); + ModulePortId primitive_io_port_id = + module_manager.add_port(primitive_module, module_port, module_io_port_type); /* Set if the port is mappable or not */ - if (true == circuit_lib.port_is_data_io(circuit_port)) { - module_manager.set_port_is_mappable_io(primitive_module, primitive_io_port_id, true); + if (true == circuit_lib.port_is_data_io(circuit_port)) { + module_manager.set_port_is_mappable_io(primitive_module, + primitive_io_port_id, true); } - ModulePortId logic_io_port_id = module_manager.find_module_port(logic_module, circuit_lib.port_prefix(circuit_port)); - BasicPort logic_io_port = module_manager.module_port(logic_module, logic_io_port_id); + ModulePortId logic_io_port_id = module_manager.find_module_port( + logic_module, circuit_lib.port_prefix(circuit_port)); + BasicPort logic_io_port = + module_manager.module_port(logic_module, logic_io_port_id); VTR_ASSERT(logic_io_port.get_width() == module_port.get_width()); /* Wire the GPIO port from primitive_module to the logic module!*/ - for (size_t pin_id = 0; pin_id < module_port.pins().size(); ++pin_id) { - if ( (ModuleManager::MODULE_GPIO_PORT == module_io_port_type) - || (ModuleManager::MODULE_GPIN_PORT == module_io_port_type) ) { + for (size_t pin_id = 0; pin_id < module_port.pins().size(); ++pin_id) { + if ((ModuleManager::MODULE_GPIO_PORT == module_io_port_type) || + (ModuleManager::MODULE_GPIN_PORT == module_io_port_type)) { bool net_exist = true; - /* If the source port has already a net to drive, we just update the net sinks */ - ModuleNetId net = module_manager.module_instance_port_net(primitive_module, primitive_module, 0, primitive_io_port_id, module_port.pins()[pin_id]); + /* If the source port has already a net to drive, we just update the net + * sinks */ + ModuleNetId net = module_manager.module_instance_port_net( + primitive_module, primitive_module, 0, primitive_io_port_id, + module_port.pins()[pin_id]); if (net == ModuleNetId::INVALID()) { net_exist = false; net = module_manager.create_module_net(primitive_module); } if (false == net_exist) { - module_manager.add_module_net_source(primitive_module, net, primitive_module, 0, primitive_io_port_id, module_port.pins()[pin_id]); + module_manager.add_module_net_source( + primitive_module, net, primitive_module, 0, primitive_io_port_id, + module_port.pins()[pin_id]); } - module_manager.add_module_net_sink(primitive_module, net, logic_module, logic_instance_id, logic_io_port_id, logic_io_port.pins()[pin_id]); + module_manager.add_module_net_sink(primitive_module, net, logic_module, + logic_instance_id, logic_io_port_id, + logic_io_port.pins()[pin_id]); } else { bool net_exist = true; - /* If the source port has already a net to drive, we just update the net sinks */ - ModuleNetId net = module_manager.module_instance_port_net(primitive_module, logic_module, logic_instance_id, logic_io_port_id, logic_io_port.pins()[pin_id]); + /* If the source port has already a net to drive, we just update the net + * sinks */ + ModuleNetId net = module_manager.module_instance_port_net( + primitive_module, logic_module, logic_instance_id, logic_io_port_id, + logic_io_port.pins()[pin_id]); if (net == ModuleNetId::INVALID()) { net_exist = false; net = module_manager.create_module_net(primitive_module); @@ -207,9 +222,13 @@ void add_primitive_module_fpga_global_io_port(ModuleManager& module_manager, VTR_ASSERT(ModuleManager::MODULE_GPOUT_PORT == module_io_port_type); if (false == net_exist) { - module_manager.add_module_net_source(primitive_module, net, logic_module, logic_instance_id, logic_io_port_id, logic_io_port.pins()[pin_id]); + module_manager.add_module_net_source( + primitive_module, net, logic_module, logic_instance_id, + logic_io_port_id, logic_io_port.pins()[pin_id]); } - module_manager.add_module_net_sink(primitive_module, net, primitive_module, 0, primitive_io_port_id, module_port.pins()[pin_id]); + module_manager.add_module_net_sink( + primitive_module, net, primitive_module, 0, primitive_io_port_id, + module_port.pins()[pin_id]); } } } @@ -217,7 +236,8 @@ void add_primitive_module_fpga_global_io_port(ModuleManager& module_manager, /******************************************************************** * Print Verilog modules of a primitive node in the pb_graph_node graph * This generic function can support all the different types of primitive nodes - * i.e., Look-Up Tables (LUTs), Flip-flops (FFs) and hard logic blocks such as adders. + * i.e., Look-Up Tables (LUTs), Flip-flops (FFs) and hard logic blocks such as + *adders. * * The Verilog module will consist of two parts: * 1. Logic module of the primitive node @@ -230,37 +250,35 @@ void add_primitive_module_fpga_global_io_port(ModuleManager& module_manager, * * Primitive block * +---------------------------------------+ - * | | + * | | * | +---------+ +---------+ | * in |----->| |--->| |<------|configuration lines * | | Logic |... | Memory | | * out|<-----| |--->| | | * | +---------+ +---------+ | - * | | + * | | * +---------------------------------------+ * *******************************************************************/ -static -void build_primitive_block_module(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const VprDeviceAnnotation& device_annotation, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - t_pb_graph_node* primitive_pb_graph_node, - const bool& verbose) { - /* Ensure a valid pb_graph_node */ +static void build_primitive_block_module( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const VprDeviceAnnotation& device_annotation, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, t_pb_graph_node* primitive_pb_graph_node, + const bool& verbose) { + /* Ensure a valid pb_graph_node */ VTR_ASSERT(nullptr != primitive_pb_graph_node); /* Find the circuit model id linked to the pb_graph_node */ - const CircuitModelId& primitive_model = device_annotation.pb_type_circuit_model(primitive_pb_graph_node->pb_type); + const CircuitModelId& primitive_model = + device_annotation.pb_type_circuit_model(primitive_pb_graph_node->pb_type); /* Generate the module name for this primitive pb_graph_node*/ - std::string primitive_module_name = generate_physical_block_module_name(primitive_pb_graph_node->pb_type); + std::string primitive_module_name = + generate_physical_block_module_name(primitive_pb_graph_node->pb_type); - VTR_LOGV(verbose, - "Building module '%s'...", - primitive_module_name.c_str()); + VTR_LOGV(verbose, "Building module '%s'...", primitive_module_name.c_str()); /* Create a module of the primitive LUT and register it to module manager */ ModuleId primitive_module = module_manager.add_module(primitive_module_name); @@ -270,26 +288,31 @@ void build_primitive_block_module(ModuleManager& module_manager, /* Label module usage */ module_manager.set_module_usage(primitive_module, ModuleManager::MODULE_GRID); - /* Note: to cooperate with the pb_type hierarchy and connections, we add the port of primitive pb_type here. - * Since we have linked pb_type ports to circuit models when setting up FPGA-X2P, - * no ports of the circuit model will be missing here + /* Note: to cooperate with the pb_type hierarchy and connections, we add the + * port of primitive pb_type here. Since we have linked pb_type ports to + * circuit models when setting up FPGA-X2P, no ports of the circuit model will + * be missing here */ - add_primitive_pb_type_ports_to_module_manager(module_manager, primitive_module, - primitive_pb_graph_node->pb_type, device_annotation); + add_primitive_pb_type_ports_to_module_manager( + module_manager, primitive_module, primitive_pb_graph_node->pb_type, + device_annotation); /* Add configuration ports */ /* Shared SRAM ports*/ - size_t num_shared_config_bits = find_circuit_num_shared_config_bits(circuit_lib, primitive_model, sram_orgz_type); + size_t num_shared_config_bits = find_circuit_num_shared_config_bits( + circuit_lib, primitive_model, sram_orgz_type); if (0 < num_shared_config_bits) { /* Check: this SRAM organization type must be memory-bank ! */ - VTR_ASSERT( CONFIG_MEM_MEMORY_BANK == sram_orgz_type || CONFIG_MEM_QL_MEMORY_BANK == sram_orgz_type ); + VTR_ASSERT(CONFIG_MEM_MEMORY_BANK == sram_orgz_type || + CONFIG_MEM_QL_MEMORY_BANK == sram_orgz_type); /* Generate a list of ports */ - add_reserved_sram_ports_to_module_manager(module_manager, primitive_module, - num_shared_config_bits); + add_reserved_sram_ports_to_module_manager(module_manager, primitive_module, + num_shared_config_bits); } /* Regular (independent) SRAM ports */ - size_t num_config_bits = find_circuit_num_config_bits(sram_orgz_type, circuit_lib, primitive_model); + size_t num_config_bits = + find_circuit_num_config_bits(sram_orgz_type, circuit_lib, primitive_model); if (0 < num_config_bits) { add_sram_ports_to_module_manager(module_manager, primitive_module, circuit_lib, sram_model, sram_orgz_type, @@ -297,80 +320,83 @@ void build_primitive_block_module(ModuleManager& module_manager, } /* Find the module id in the module manager */ - ModuleId logic_module = module_manager.find_module(circuit_lib.model_name(primitive_model)); + ModuleId logic_module = + module_manager.find_module(circuit_lib.model_name(primitive_model)); VTR_ASSERT(ModuleId::INVALID() != logic_module); - size_t logic_instance_id = module_manager.num_instance(primitive_module, logic_module); + size_t logic_instance_id = + module_manager.num_instance(primitive_module, logic_module); /* Add the logic module as a child of primitive module */ module_manager.add_child_module(primitive_module, logic_module); /* Add nets to connect the logic model ports to pb_type ports */ - add_primitive_pb_type_module_nets(module_manager, primitive_module, - logic_module, logic_instance_id, - circuit_lib, primitive_pb_graph_node->pb_type, - device_annotation); + add_primitive_pb_type_module_nets( + module_manager, primitive_module, logic_module, logic_instance_id, + circuit_lib, primitive_pb_graph_node->pb_type, device_annotation); /* Add the associated memory module as a child of primitive module */ - std::string memory_module_name = generate_memory_module_name(circuit_lib, primitive_model, sram_model, std::string(MEMORY_MODULE_POSTFIX)); + std::string memory_module_name = + generate_memory_module_name(circuit_lib, primitive_model, sram_model, + std::string(MEMORY_MODULE_POSTFIX)); ModuleId memory_module = module_manager.find_module(memory_module_name); - /* If there is no memory module required, we can skip the assocated net addition */ + /* If there is no memory module required, we can skip the assocated net + * addition */ if (ModuleId::INVALID() != memory_module) { - size_t memory_instance_id = module_manager.num_instance(primitive_module, memory_module); + size_t memory_instance_id = + module_manager.num_instance(primitive_module, memory_module); /* Add the memory module as a child of primitive module */ module_manager.add_child_module(primitive_module, memory_module); /* Set an instance name to bind to a block in bitstream generation */ - module_manager.set_child_instance_name(primitive_module, memory_module, memory_instance_id, memory_module_name); - - /* Add nets to connect regular and mode-select SRAM ports to the SRAM port of memory module */ - add_module_nets_between_logic_and_memory_sram_bus(module_manager, primitive_module, - logic_module, logic_instance_id, - memory_module, memory_instance_id, - circuit_lib, primitive_model); + module_manager.set_child_instance_name( + primitive_module, memory_module, memory_instance_id, memory_module_name); + + /* Add nets to connect regular and mode-select SRAM ports to the SRAM port + * of memory module */ + add_module_nets_between_logic_and_memory_sram_bus( + module_manager, primitive_module, logic_module, logic_instance_id, + memory_module, memory_instance_id, circuit_lib, primitive_model); /* Record memory-related information */ - module_manager.add_configurable_child(primitive_module, memory_module, memory_instance_id); + module_manager.add_configurable_child(primitive_module, memory_module, + memory_instance_id); } - /* Add all the nets to connect configuration ports from memory module to primitive modules - * This is a one-shot addition that covers all the memory modules in this primitive module! + /* Add all the nets to connect configuration ports from memory module to + * primitive modules This is a one-shot addition that covers all the memory + * modules in this primitive module! */ if (0 < module_manager.configurable_children(primitive_module).size()) { - add_module_nets_memory_config_bus(module_manager, decoder_lib, primitive_module, - sram_orgz_type, circuit_lib.design_tech_type(sram_model)); + add_module_nets_memory_config_bus(module_manager, decoder_lib, + primitive_module, sram_orgz_type, + circuit_lib.design_tech_type(sram_model)); } /* Add global ports to the pb_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 a list of it + * 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 + * a list of it */ add_module_global_ports_from_child_modules(module_manager, primitive_module); - /* Find the inout ports required by the primitive node, and add them to the module - * This is mainly due to the I/O blocks, which have inout ports for the top-level fabric + /* Find the inout ports required by the primitive node, and add them to the + * module This is mainly due to the I/O blocks, which have inout ports for the + * top-level fabric */ - for (const auto& port : circuit_lib.model_global_ports(primitive_model, false)) { - if ( (CIRCUIT_MODEL_PORT_INOUT == circuit_lib.port_type(port)) - && (true == circuit_lib.port_is_io(port)) ) { - add_primitive_module_fpga_global_io_port(module_manager, primitive_module, - logic_module, logic_instance_id, - ModuleManager::MODULE_GPIO_PORT, - circuit_lib, - primitive_model, - port); - } else if ( (CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(port)) - && (true == circuit_lib.port_is_io(port)) ) { - add_primitive_module_fpga_global_io_port(module_manager, primitive_module, - logic_module, logic_instance_id, - ModuleManager::MODULE_GPIN_PORT, - circuit_lib, - primitive_model, - port); + for (const auto& port : + circuit_lib.model_global_ports(primitive_model, false)) { + if ((CIRCUIT_MODEL_PORT_INOUT == circuit_lib.port_type(port)) && + (true == circuit_lib.port_is_io(port))) { + add_primitive_module_fpga_global_io_port( + module_manager, primitive_module, logic_module, logic_instance_id, + ModuleManager::MODULE_GPIO_PORT, circuit_lib, primitive_model, port); + } else if ((CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(port)) && + (true == circuit_lib.port_is_io(port))) { + add_primitive_module_fpga_global_io_port( + module_manager, primitive_module, logic_module, logic_instance_id, + ModuleManager::MODULE_GPIN_PORT, circuit_lib, primitive_model, port); } else if (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port)) { - add_primitive_module_fpga_global_io_port(module_manager, primitive_module, - logic_module, logic_instance_id, - ModuleManager::MODULE_GPOUT_PORT, - circuit_lib, - primitive_model, - port); + add_primitive_module_fpga_global_io_port( + module_manager, primitive_module, logic_module, logic_instance_id, + ModuleManager::MODULE_GPOUT_PORT, circuit_lib, primitive_model, port); } } @@ -380,347 +406,387 @@ void build_primitive_block_module(ModuleManager& module_manager, /******************************************************************** * This function add a net for a pin-to-pin connection defined in pb_graph * It supports two cases for the pin-to-pin connection - * 1. The net source is a pb_graph_pin while the net sink is a pin of an interconnection - * 2. The net source is a pin of an interconnection while the net sink a pb_graph_pin - * The type is enabled by an argument pin2pin_interc_type + * 1. The net source is a pb_graph_pin while the net sink is a pin of an + *interconnection + * 2. The net source is a pin of an interconnection while the net sink a + *pb_graph_pin The type is enabled by an argument pin2pin_interc_type *******************************************************************/ -static -void add_module_pb_graph_pin2pin_net(ModuleManager& module_manager, - const ModuleId& pb_module, - const ModuleId& interc_module, - const size_t& interc_instance, - const std::string& interc_port_name, - const size_t& interc_pin_id, - t_pb_graph_pin* pb_graph_pin, - const enum e_pin2pin_interc_type& pin2pin_interc_type) { - +static void add_module_pb_graph_pin2pin_net( + ModuleManager& module_manager, const ModuleId& pb_module, + const ModuleId& interc_module, const size_t& interc_instance, + const std::string& interc_port_name, const size_t& interc_pin_id, + t_pb_graph_pin* pb_graph_pin, + const enum e_pin2pin_interc_type& pin2pin_interc_type) { ModuleNetId pin2pin_net = module_manager.create_module_net(pb_module); - /* Find port and pin ids for the module, which is the parent of pb_graph_pin */ + /* Find port and pin ids for the module, which is the parent of pb_graph_pin + */ t_pb_type* pin_pb_type = pb_graph_pin->parent_node->pb_type; /* Find the module contains the source pin */ - ModuleId pin_pb_type_module = module_manager.find_module(generate_physical_block_module_name(pin_pb_type)); + ModuleId pin_pb_type_module = module_manager.find_module( + generate_physical_block_module_name(pin_pb_type)); VTR_ASSERT(true == module_manager.valid_module_id(pin_pb_type_module)); - size_t pin_pb_type_instance = 0; /* Deposite the instance with a zero, which is the default value is the source module is actually pb_module itself */ + size_t pin_pb_type_instance = + 0; /* Deposite the instance with a zero, which is the default value is the + source module is actually pb_module itself */ if (pin_pb_type_module != pb_module) { pin_pb_type_instance = pb_graph_pin->parent_node->placement_index; /* Ensure this is an valid instance */ - VTR_ASSERT(pin_pb_type_instance < module_manager.num_instance(pb_module, pin_pb_type_module)); + VTR_ASSERT(pin_pb_type_instance < + module_manager.num_instance(pb_module, pin_pb_type_module)); } - ModulePortId pin_module_port_id = module_manager.find_module_port(pin_pb_type_module, generate_pb_type_port_name(pb_graph_pin->port)); - VTR_ASSERT(true == module_manager.valid_module_port_id(pin_pb_type_module, pin_module_port_id)); + ModulePortId pin_module_port_id = module_manager.find_module_port( + pin_pb_type_module, generate_pb_type_port_name(pb_graph_pin->port)); + VTR_ASSERT(true == module_manager.valid_module_port_id(pin_pb_type_module, + pin_module_port_id)); size_t pin_module_pin_id = pb_graph_pin->pin_number; /* Ensure this is an valid pin index */ - VTR_ASSERT(pin_module_pin_id < module_manager.module_port(pin_pb_type_module, pin_module_port_id).get_width()); + VTR_ASSERT(pin_module_pin_id < + module_manager.module_port(pin_pb_type_module, pin_module_port_id) + .get_width()); /* Find port and pin ids for the interconnection module */ - ModulePortId interc_port_id = module_manager.find_module_port(interc_module, interc_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(interc_module, interc_port_id)); + ModulePortId interc_port_id = + module_manager.find_module_port(interc_module, interc_port_name); + VTR_ASSERT( + true == module_manager.valid_module_port_id(interc_module, interc_port_id)); /* Ensure this is an valid pin index */ - VTR_ASSERT(interc_pin_id < module_manager.module_port(interc_module, interc_port_id).get_width()); - + VTR_ASSERT( + interc_pin_id < + module_manager.module_port(interc_module, interc_port_id).get_width()); + /* Add net sources and sinks: - * For input-to-input connection, net_source is pin_graph_pin, while net_sink is interc pin - * For output-to-output connection, net_source is interc pin, while net_sink is pin_graph pin + * For input-to-input connection, net_source is pin_graph_pin, while net_sink + * is interc pin For output-to-output connection, net_source is interc pin, + * while net_sink is pin_graph pin */ switch (pin2pin_interc_type) { - case INPUT2INPUT_INTERC: - module_manager.add_module_net_source(pb_module, pin2pin_net, pin_pb_type_module, pin_pb_type_instance, pin_module_port_id, pin_module_pin_id); - module_manager.add_module_net_sink(pb_module, pin2pin_net, interc_module, interc_instance, interc_port_id, interc_pin_id); - break; - case OUTPUT2OUTPUT_INTERC: - module_manager.add_module_net_source(pb_module, pin2pin_net, interc_module, interc_instance, interc_port_id, interc_pin_id); - module_manager.add_module_net_sink(pb_module, pin2pin_net, pin_pb_type_module, pin_pb_type_instance, pin_module_port_id, pin_module_pin_id); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid pin-to-pin interconnection type!\n"); - exit(1); + case INPUT2INPUT_INTERC: + module_manager.add_module_net_source( + pb_module, pin2pin_net, pin_pb_type_module, pin_pb_type_instance, + pin_module_port_id, pin_module_pin_id); + module_manager.add_module_net_sink(pb_module, pin2pin_net, interc_module, + interc_instance, interc_port_id, + interc_pin_id); + break; + case OUTPUT2OUTPUT_INTERC: + module_manager.add_module_net_source(pb_module, pin2pin_net, + interc_module, interc_instance, + interc_port_id, interc_pin_id); + module_manager.add_module_net_sink( + pb_module, pin2pin_net, pin_pb_type_module, pin_pb_type_instance, + pin_module_port_id, pin_module_pin_id); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid pin-to-pin interconnection type!\n"); + exit(1); } } /******************************************************************** * We check output_pins of cur_pb_graph_node and its the input_edges - * Built the interconnections between outputs of cur_pb_graph_node and outputs of child_pb_graph_node - * src_pb_graph_node.[in|out]_pins -----------------> des_pb_graph_node.[in|out]pins + * Built the interconnections between outputs of cur_pb_graph_node and outputs + *of child_pb_graph_node src_pb_graph_node.[in|out]_pins -----------------> + *des_pb_graph_node.[in|out]pins * /|\ * | * input_pins, edges, output_pins * * This function does the following task: - * 1. identify pin interconnection type, - * 2. Identify the number of fan-in (Consider interconnection edges of only selected mode) + * 1. identify pin interconnection type, + * 2. Identify the number of fan-in (Consider interconnection edges of only + *selected mode) * 3. Add mux/direct connection as a child module to pb_module - * 4. Add nets related to the mux/direction + * 4. Add nets related to the mux/direction *******************************************************************/ -static -void add_module_pb_graph_pin_interc(ModuleManager& module_manager, - const ModuleId& pb_module, - std::vector& memory_modules, - std::vector& memory_instances, - const VprDeviceAnnotation& device_annotation, - const CircuitLibrary& circuit_lib, - t_pb_graph_pin* des_pb_graph_pin, - t_mode* physical_mode) { - /* Find the number of fan-in and detailed interconnection information - * related to the destination pb_graph_pin +static void add_module_pb_graph_pin_interc( + ModuleManager& module_manager, const ModuleId& pb_module, + std::vector& memory_modules, std::vector& memory_instances, + const VprDeviceAnnotation& device_annotation, + const CircuitLibrary& circuit_lib, t_pb_graph_pin* des_pb_graph_pin, + t_mode* physical_mode) { + /* Find the number of fan-in and detailed interconnection information + * related to the destination pb_graph_pin */ - t_interconnect* cur_interc = pb_graph_pin_interc(des_pb_graph_pin, physical_mode); + t_interconnect* cur_interc = + pb_graph_pin_interc(des_pb_graph_pin, physical_mode); size_t fan_in = pb_graph_pin_inputs(des_pb_graph_pin, cur_interc).size(); - + /* If no interconnection is needed, we can return early */ - if ((nullptr == cur_interc) || (0 == fan_in)) { + if ((nullptr == cur_interc) || (0 == fan_in)) { return; } - /* Initialize the interconnection type that will be physically implemented in module */ - enum e_interconnect interc_type = device_annotation.interconnect_physical_type(cur_interc); - const CircuitModelId& interc_circuit_model = device_annotation.interconnect_circuit_model(cur_interc); + /* Initialize the interconnection type that will be physically implemented in + * module */ + enum e_interconnect interc_type = + device_annotation.interconnect_physical_type(cur_interc); + const CircuitModelId& interc_circuit_model = + device_annotation.interconnect_circuit_model(cur_interc); /* Find input ports of the wire module */ - std::vector interc_model_inputs = circuit_lib.model_ports_by_type(interc_circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); /* the last argument to guarantee that we ignore any global inputs */ + std::vector interc_model_inputs = + circuit_lib.model_ports_by_type( + interc_circuit_model, CIRCUIT_MODEL_PORT_INPUT, + true); /* the last argument to guarantee that we ignore any global inputs + */ /* Find output ports of the wire module */ - std::vector interc_model_outputs = circuit_lib.model_ports_by_type(interc_circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); /* the last argument to guarantee that we ignore any global ports */ + std::vector interc_model_outputs = + circuit_lib.model_ports_by_type(interc_circuit_model, + CIRCUIT_MODEL_PORT_OUTPUT, + true); /* the last argument to guarantee + that we ignore any global ports */ - /* Ensure that we have only 1 input port and 1 output port, this is valid for both wire and MUX */ + /* Ensure that we have only 1 input port and 1 output port, this is valid for + * both wire and MUX */ VTR_ASSERT(1 == interc_model_inputs.size()); VTR_ASSERT(1 == interc_model_outputs.size()); /* Branch on the type of physical implementation, - * We add instances of programmable interconnection - */ + * We add instances of programmable interconnection + */ switch (interc_type) { - case DIRECT_INTERC: { - /* Ensure direct interc has only one fan-in */ - VTR_ASSERT(1 == fan_in); + case DIRECT_INTERC: { + /* Ensure direct interc has only one fan-in */ + VTR_ASSERT(1 == fan_in); - /* For more than one mode defined, the direct interc has more than one input_edge , - * We need to find which edge is connected the pin we want - */ - t_pb_graph_pin* src_pb_graph_pin = pb_graph_pin_inputs(des_pb_graph_pin, cur_interc)[0]; + /* For more than one mode defined, the direct interc has more than one + * input_edge , We need to find which edge is connected the pin we want + */ + t_pb_graph_pin* src_pb_graph_pin = + pb_graph_pin_inputs(des_pb_graph_pin, cur_interc)[0]; - /* Ensure that circuit model is a wire */ - VTR_ASSERT(CIRCUIT_MODEL_WIRE == circuit_lib.model_type(interc_circuit_model)); - /* Find the wire module in the module manager */ - ModuleId wire_module = module_manager.find_module(circuit_lib.model_name(interc_circuit_model)); - VTR_ASSERT(true == module_manager.valid_module_id(wire_module)); - /* Get the instance id and add an instance of wire */ - size_t wire_instance = module_manager.num_instance(pb_module, wire_module); - module_manager.add_child_module(pb_module, wire_module); + /* Ensure that circuit model is a wire */ + VTR_ASSERT(CIRCUIT_MODEL_WIRE == + circuit_lib.model_type(interc_circuit_model)); + /* Find the wire module in the module manager */ + ModuleId wire_module = module_manager.find_module( + circuit_lib.model_name(interc_circuit_model)); + VTR_ASSERT(true == module_manager.valid_module_id(wire_module)); + /* Get the instance id and add an instance of wire */ + size_t wire_instance = + module_manager.num_instance(pb_module, wire_module); + module_manager.add_child_module(pb_module, wire_module); - /* Give an instance name: this name should be consistent with the block name given in SDC generator, - * If you want to bind the SDC generation to modules - */ - std::string wire_instance_name = generate_instance_name(module_manager.module_name(wire_module), wire_instance); - module_manager.set_child_instance_name(pb_module, wire_module, wire_instance, wire_instance_name); + /* Give an instance name: this name should be consistent with the block + * name given in SDC generator, If you want to bind the SDC generation to + * modules + */ + std::string wire_instance_name = generate_instance_name( + module_manager.module_name(wire_module), wire_instance); + module_manager.set_child_instance_name(pb_module, wire_module, + wire_instance, wire_instance_name); - /* Ensure input and output ports of the wire model has only 1 pin respectively */ - VTR_ASSERT(1 == circuit_lib.port_size(interc_model_inputs[0])); - VTR_ASSERT(1 == circuit_lib.port_size(interc_model_outputs[0])); + /* Ensure input and output ports of the wire model has only 1 pin + * respectively */ + VTR_ASSERT(1 == circuit_lib.port_size(interc_model_inputs[0])); + VTR_ASSERT(1 == circuit_lib.port_size(interc_model_outputs[0])); - /* Add nets to connect the wires to ports of pb_module */ - /* First net is to connect input of src_pb_graph_node to input of the wire module */ - add_module_pb_graph_pin2pin_net(module_manager, pb_module, - wire_module, wire_instance, - circuit_lib.port_prefix(interc_model_inputs[0]), - 0, /* wire input port has only 1 pin */ - src_pb_graph_pin, - INPUT2INPUT_INTERC); + /* Add nets to connect the wires to ports of pb_module */ + /* First net is to connect input of src_pb_graph_node to input of the wire + * module */ + add_module_pb_graph_pin2pin_net( + module_manager, pb_module, wire_module, wire_instance, + circuit_lib.port_prefix(interc_model_inputs[0]), + 0, /* wire input port has only 1 pin */ + src_pb_graph_pin, INPUT2INPUT_INTERC); - /* Second net is to connect output of the wire module to output of des_pb_graph_pin */ - add_module_pb_graph_pin2pin_net(module_manager, pb_module, - wire_module, wire_instance, - circuit_lib.port_prefix(interc_model_outputs[0]), - 0, /* wire output port has only 1 pin */ - des_pb_graph_pin, - OUTPUT2OUTPUT_INTERC); - break; - } - case COMPLETE_INTERC: - case MUX_INTERC: { - /* Check: MUX should have at least 2 fan_in */ - VTR_ASSERT((2 == fan_in)||(2 < fan_in)); - /* Ensure that circuit model is a MUX */ - VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(interc_circuit_model)); - /* Find the wire module in the module manager */ - ModuleId mux_module = module_manager.find_module(generate_mux_subckt_name(circuit_lib, interc_circuit_model, fan_in, std::string())); - VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); - - /* Instanciate the MUX */ - size_t mux_instance = module_manager.num_instance(pb_module, mux_module); - module_manager.add_child_module(pb_module, mux_module); - /* Give an instance name: this name should be consistent with the block name given in SDC generator, - * If you want to bind the SDC generation to modules - */ - std::string mux_instance_name = generate_pb_mux_instance_name(GRID_MUX_INSTANCE_PREFIX, des_pb_graph_pin, std::string("")); - module_manager.set_child_instance_name(pb_module, mux_module, mux_instance, mux_instance_name); - - /* Instanciate a memory module for the MUX */ - std::string mux_mem_module_name = generate_mux_subckt_name(circuit_lib, - interc_circuit_model, - fan_in, - std::string(MEMORY_MODULE_POSTFIX)); - ModuleId mux_mem_module = module_manager.find_module(mux_mem_module_name); - VTR_ASSERT(true == module_manager.valid_module_id(mux_mem_module)); - size_t mux_mem_instance = module_manager.num_instance(pb_module, mux_mem_module); - module_manager.add_child_module(pb_module, mux_mem_module); - /* Give an instance name: this name should be consistent with the block name given in bitstream manager, - * If you want to bind the bitstream generation to modules - */ - std::string mux_mem_instance_name = generate_pb_memory_instance_name(GRID_MEM_INSTANCE_PREFIX, des_pb_graph_pin, std::string("")); - module_manager.set_child_instance_name(pb_module, mux_mem_module, mux_mem_instance, mux_mem_instance_name); - /* Add this MUX as a configurable child to the pb_module */ - module_manager.add_configurable_child(pb_module, mux_mem_module, mux_mem_instance); - - /* Add nets to connect SRAM ports of the MUX to the SRAM port of memory module */ - add_module_nets_between_logic_and_memory_sram_bus(module_manager, pb_module, - mux_module, mux_instance, - mux_mem_module, mux_mem_instance, - circuit_lib, interc_circuit_model); - - /* Update memory modules and memory instance list */ - memory_modules.push_back(mux_mem_module); - memory_instances.push_back(mux_mem_instance); - - /* Ensure output port of the MUX model has only 1 pin, - * while the input port size is dependent on the architecture conext, - * no constaints on the circuit model definition - */ - VTR_ASSERT(1 == circuit_lib.port_size(interc_model_outputs[0])); - - /* Create nets to wire between the MUX and PB module */ - /* Add a net to wire the inputs of the multiplexer to its source pb_graph_pin inside pb_module - * Here is a tricky part. - * Not every input edges from the destination pb_graph_pin is used in the physical_model of pb_type - * So, we will skip these input edges when building nets - */ - size_t mux_input_pin_id = 0; - for (t_pb_graph_pin* src_pb_graph_pin : pb_graph_pin_inputs(des_pb_graph_pin, cur_interc)) { - /* Add a net, set its source and sink */ - add_module_pb_graph_pin2pin_net(module_manager, pb_module, - mux_module, mux_instance, - circuit_lib.port_prefix(interc_model_inputs[0]), - mux_input_pin_id, - src_pb_graph_pin, - INPUT2INPUT_INTERC); - mux_input_pin_id++; + /* Second net is to connect output of the wire module to output of + * des_pb_graph_pin */ + add_module_pb_graph_pin2pin_net( + module_manager, pb_module, wire_module, wire_instance, + circuit_lib.port_prefix(interc_model_outputs[0]), + 0, /* wire output port has only 1 pin */ + des_pb_graph_pin, OUTPUT2OUTPUT_INTERC); + break; } - /* Ensure all the fan_in has been covered */ - VTR_ASSERT(mux_input_pin_id == fan_in); + case COMPLETE_INTERC: + case MUX_INTERC: { + /* Check: MUX should have at least 2 fan_in */ + VTR_ASSERT((2 == fan_in) || (2 < fan_in)); + /* Ensure that circuit model is a MUX */ + VTR_ASSERT(CIRCUIT_MODEL_MUX == + circuit_lib.model_type(interc_circuit_model)); + /* Find the wire module in the module manager */ + ModuleId mux_module = module_manager.find_module(generate_mux_subckt_name( + circuit_lib, interc_circuit_model, fan_in, std::string())); + VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); - /* Add a net to wire the output of the multiplexer to des_pb_graph_pin */ - add_module_pb_graph_pin2pin_net(module_manager, pb_module, - mux_module, mux_instance, - circuit_lib.port_prefix(interc_model_outputs[0]), - 0, /* MUX should have only 1 pin in its output port */ - des_pb_graph_pin, - OUTPUT2OUTPUT_INTERC); - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid interconnection type for %s [at Architecture XML LINE%d]!\n", - cur_interc->name, cur_interc->line_num); - exit(1); + /* Instanciate the MUX */ + size_t mux_instance = module_manager.num_instance(pb_module, mux_module); + module_manager.add_child_module(pb_module, mux_module); + /* Give an instance name: this name should be consistent with the block + * name given in SDC generator, If you want to bind the SDC generation to + * modules + */ + std::string mux_instance_name = generate_pb_mux_instance_name( + GRID_MUX_INSTANCE_PREFIX, des_pb_graph_pin, std::string("")); + module_manager.set_child_instance_name(pb_module, mux_module, + mux_instance, mux_instance_name); + + /* Instanciate a memory module for the MUX */ + std::string mux_mem_module_name = + generate_mux_subckt_name(circuit_lib, interc_circuit_model, fan_in, + std::string(MEMORY_MODULE_POSTFIX)); + ModuleId mux_mem_module = module_manager.find_module(mux_mem_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(mux_mem_module)); + size_t mux_mem_instance = + module_manager.num_instance(pb_module, mux_mem_module); + module_manager.add_child_module(pb_module, mux_mem_module); + /* Give an instance name: this name should be consistent with the block + * name given in bitstream manager, If you want to bind the bitstream + * generation to modules + */ + std::string mux_mem_instance_name = generate_pb_memory_instance_name( + GRID_MEM_INSTANCE_PREFIX, des_pb_graph_pin, std::string("")); + module_manager.set_child_instance_name( + pb_module, mux_mem_module, mux_mem_instance, mux_mem_instance_name); + /* Add this MUX as a configurable child to the pb_module */ + module_manager.add_configurable_child(pb_module, mux_mem_module, + mux_mem_instance); + + /* Add nets to connect SRAM ports of the MUX to the SRAM port of memory + * module */ + add_module_nets_between_logic_and_memory_sram_bus( + module_manager, pb_module, mux_module, mux_instance, mux_mem_module, + mux_mem_instance, circuit_lib, interc_circuit_model); + + /* Update memory modules and memory instance list */ + memory_modules.push_back(mux_mem_module); + memory_instances.push_back(mux_mem_instance); + + /* Ensure output port of the MUX model has only 1 pin, + * while the input port size is dependent on the architecture conext, + * no constaints on the circuit model definition + */ + VTR_ASSERT(1 == circuit_lib.port_size(interc_model_outputs[0])); + + /* Create nets to wire between the MUX and PB module */ + /* Add a net to wire the inputs of the multiplexer to its source + * pb_graph_pin inside pb_module Here is a tricky part. Not every input + * edges from the destination pb_graph_pin is used in the physical_model + * of pb_type So, we will skip these input edges when building nets + */ + size_t mux_input_pin_id = 0; + for (t_pb_graph_pin* src_pb_graph_pin : + pb_graph_pin_inputs(des_pb_graph_pin, cur_interc)) { + /* Add a net, set its source and sink */ + add_module_pb_graph_pin2pin_net( + module_manager, pb_module, mux_module, mux_instance, + circuit_lib.port_prefix(interc_model_inputs[0]), mux_input_pin_id, + src_pb_graph_pin, INPUT2INPUT_INTERC); + mux_input_pin_id++; + } + /* Ensure all the fan_in has been covered */ + VTR_ASSERT(mux_input_pin_id == fan_in); + + /* Add a net to wire the output of the multiplexer to des_pb_graph_pin */ + add_module_pb_graph_pin2pin_net( + module_manager, pb_module, mux_module, mux_instance, + circuit_lib.port_prefix(interc_model_outputs[0]), + 0, /* MUX should have only 1 pin in its output port */ + des_pb_graph_pin, OUTPUT2OUTPUT_INTERC); + break; + } + default: + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Invalid interconnection type for %s [at Architecture XML LINE%d]!\n", + cur_interc->name, cur_interc->line_num); + exit(1); } } /******************************************************************** - * Add modules and nets for programmable/non-programmable interconnections + * Add modules and nets for programmable/non-programmable interconnections * which end to a port of pb_module * This function will add the following elements to a module * 1. Instances of direct connections * 2. Instances of programmable routing multiplexers - * 3. nets to connect direct connections/multiplexer + * 3. nets to connect direct connections/multiplexer * * +-----------------------------------------+ - * | + * | * | +--------------+ +------------+ * |--->| |--->| | * |... | Multiplexers |... | | * |--->| |--->| | - * | +--------------+ | des_pb_ | - * | | graph_node | + * | +--------------+ | des_pb_ | + * | | graph_node | * | +--------------+ | | * |--->| |--->| | * | ...| Direct |... | | * |--->| Connections |--->| | * | +--------------+ +------------+ - * | + * | * +----------------------------------------+ * * Note: this function should be run after ALL the child pb_modules - * have been added to the pb_module and ALL the ports defined + * have been added to the pb_module and ALL the ports defined * in pb_type have been added to the pb_module!!! * ********************************************************************/ -static -void add_module_pb_graph_port_interc(ModuleManager& module_manager, - const ModuleId& pb_module, - std::vector& memory_modules, - std::vector& memory_instances, - const VprDeviceAnnotation& device_annotation, - const CircuitLibrary& circuit_lib, - t_pb_graph_node* des_pb_graph_node, - const e_circuit_pb_port_type& pb_port_type, - t_mode* physical_mode) { +static void add_module_pb_graph_port_interc( + ModuleManager& module_manager, const ModuleId& pb_module, + std::vector& memory_modules, std::vector& memory_instances, + const VprDeviceAnnotation& device_annotation, + const CircuitLibrary& circuit_lib, t_pb_graph_node* des_pb_graph_node, + const e_circuit_pb_port_type& pb_port_type, t_mode* physical_mode) { switch (pb_port_type) { - case CIRCUIT_PB_PORT_INPUT: { - for (int iport = 0; iport < des_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < des_pb_graph_node->num_input_pins[iport]; ++ipin) { - /* Get the selected edge of current pin*/ - add_module_pb_graph_pin_interc(module_manager, pb_module, - memory_modules, memory_instances, - device_annotation, - circuit_lib, - &(des_pb_graph_node->input_pins[iport][ipin]), - physical_mode); + case CIRCUIT_PB_PORT_INPUT: { + for (int iport = 0; iport < des_pb_graph_node->num_input_ports; ++iport) { + for (int ipin = 0; ipin < des_pb_graph_node->num_input_pins[iport]; + ++ipin) { + /* Get the selected edge of current pin*/ + add_module_pb_graph_pin_interc( + module_manager, pb_module, memory_modules, memory_instances, + device_annotation, circuit_lib, + &(des_pb_graph_node->input_pins[iport][ipin]), physical_mode); + } } + break; } - break; - } - case CIRCUIT_PB_PORT_OUTPUT: { - for (int iport = 0; iport < des_pb_graph_node->num_output_ports; ++iport) { - for (int ipin = 0; ipin < des_pb_graph_node->num_output_pins[iport]; ++ipin) { - add_module_pb_graph_pin_interc(module_manager, pb_module, - memory_modules, memory_instances, - device_annotation, - circuit_lib, - &(des_pb_graph_node->output_pins[iport][ipin]), - physical_mode); + case CIRCUIT_PB_PORT_OUTPUT: { + for (int iport = 0; iport < des_pb_graph_node->num_output_ports; + ++iport) { + for (int ipin = 0; ipin < des_pb_graph_node->num_output_pins[iport]; + ++ipin) { + add_module_pb_graph_pin_interc( + module_manager, pb_module, memory_modules, memory_instances, + device_annotation, circuit_lib, + &(des_pb_graph_node->output_pins[iport][ipin]), physical_mode); + } } + break; } - break; - } - case CIRCUIT_PB_PORT_CLOCK: { - for (int iport = 0; iport < des_pb_graph_node->num_clock_ports; ++iport) { - for (int ipin = 0; ipin < des_pb_graph_node->num_clock_pins[iport]; ++ipin) { - add_module_pb_graph_pin_interc(module_manager, pb_module, - memory_modules, memory_instances, - device_annotation, - circuit_lib, - &(des_pb_graph_node->clock_pins[iport][ipin]), - physical_mode); + case CIRCUIT_PB_PORT_CLOCK: { + for (int iport = 0; iport < des_pb_graph_node->num_clock_ports; ++iport) { + for (int ipin = 0; ipin < des_pb_graph_node->num_clock_pins[iport]; + ++ipin) { + add_module_pb_graph_pin_interc( + module_manager, pb_module, memory_modules, memory_instances, + device_annotation, circuit_lib, + &(des_pb_graph_node->clock_pins[iport][ipin]), physical_mode); + } } + break; } - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid pb port type!\n"); - exit(1); + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid pb port type!\n"); + exit(1); } } /******************************************************************** - * TODO: - * Add modules and nets for programmable/non-programmable interconnections + * TODO: + * Add modules and nets for programmable/non-programmable interconnections * inside a module of pb_type * This function will add the following elements to a module * 1. Instances of direct connections * 2. Instances of programmable routing multiplexers - * 3. nets to connect direct connections/multiplexer + * 3. nets to connect direct connections/multiplexer * * Pb_module * +--------------------------------------------------------------+ @@ -740,138 +806,132 @@ void add_module_pb_graph_port_interc(ModuleManager& module_manager, * +--------------------------------------------------------------+ * * Note: this function should be run after ALL the child pb_modules - * have been added to the pb_module and ALL the ports defined + * have been added to the pb_module and ALL the ports defined * in pb_type have been added to the pb_module!!! * ********************************************************************/ -static -void add_module_pb_graph_interc(ModuleManager& module_manager, - const ModuleId& pb_module, - std::vector& memory_modules, - std::vector& memory_instances, - const VprDeviceAnnotation& device_annotation, - const CircuitLibrary& circuit_lib, - t_pb_graph_node* physical_pb_graph_node, - const int& physical_mode_index) { +static void add_module_pb_graph_interc( + ModuleManager& module_manager, const ModuleId& pb_module, + std::vector& memory_modules, std::vector& memory_instances, + const VprDeviceAnnotation& device_annotation, + const CircuitLibrary& circuit_lib, t_pb_graph_node* physical_pb_graph_node, + const int& physical_mode_index) { /* Check cur_pb_graph_node*/ VTR_ASSERT(nullptr != physical_pb_graph_node); - + /* Assign physical mode */ - t_mode* physical_mode = &(physical_pb_graph_node->pb_type->modes[physical_mode_index]); + t_mode* physical_mode = + &(physical_pb_graph_node->pb_type->modes[physical_mode_index]); /* We check output_pins of cur_pb_graph_node and its the input_edges - * Built the interconnections between outputs of cur_pb_graph_node and outputs of child_pb_graph_node - * child_pb_graph_node.output_pins -----------------> cur_pb_graph_node.outpins + * Built the interconnections between outputs of cur_pb_graph_node and outputs + * of child_pb_graph_node child_pb_graph_node.output_pins -----------------> + * cur_pb_graph_node.outpins * /|\ * | * input_pins, edges, output_pins - */ - add_module_pb_graph_port_interc(module_manager, pb_module, - memory_modules, memory_instances, - device_annotation, - circuit_lib, - physical_pb_graph_node, - CIRCUIT_PB_PORT_OUTPUT, - physical_mode); - + */ + add_module_pb_graph_port_interc(module_manager, pb_module, memory_modules, + memory_instances, device_annotation, + circuit_lib, physical_pb_graph_node, + CIRCUIT_PB_PORT_OUTPUT, physical_mode); + /* We check input_pins of child_pb_graph_node and its the input_edges - * Built the interconnections between inputs of cur_pb_graph_node and inputs of child_pb_graph_node - * cur_pb_graph_node.input_pins -----------------> child_pb_graph_node.input_pins + * Built the interconnections between inputs of cur_pb_graph_node and inputs + * of child_pb_graph_node cur_pb_graph_node.input_pins -----------------> + * child_pb_graph_node.input_pins * /|\ * | * input_pins, edges, output_pins - */ - for (int child = 0; child < physical_pb_graph_node->pb_type->modes[physical_mode_index].num_pb_type_children; ++child) { - for (int inst = 0; inst < physical_pb_graph_node->pb_type->modes[physical_mode_index].pb_type_children[child].num_pb; ++inst) { - t_pb_graph_node* child_pb_graph_node = &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode_index][child][inst]); + */ + for (int child = 0; + child < physical_pb_graph_node->pb_type->modes[physical_mode_index] + .num_pb_type_children; + ++child) { + for (int inst = 0; + inst < physical_pb_graph_node->pb_type->modes[physical_mode_index] + .pb_type_children[child] + .num_pb; + ++inst) { + t_pb_graph_node* child_pb_graph_node = + &(physical_pb_graph_node + ->child_pb_graph_nodes[physical_mode_index][child][inst]); /* For each child_pb_graph_node input pins*/ - add_module_pb_graph_port_interc(module_manager, pb_module, - memory_modules, memory_instances, - device_annotation, - circuit_lib, - child_pb_graph_node, - CIRCUIT_PB_PORT_INPUT, - physical_mode); + add_module_pb_graph_port_interc(module_manager, pb_module, memory_modules, + memory_instances, device_annotation, + circuit_lib, child_pb_graph_node, + CIRCUIT_PB_PORT_INPUT, physical_mode); /* For each child_pb_graph_node clock pins*/ - add_module_pb_graph_port_interc(module_manager, pb_module, - memory_modules, memory_instances, - device_annotation, - circuit_lib, - child_pb_graph_node, - CIRCUIT_PB_PORT_CLOCK, - physical_mode); + add_module_pb_graph_port_interc(module_manager, pb_module, memory_modules, + memory_instances, device_annotation, + circuit_lib, child_pb_graph_node, + CIRCUIT_PB_PORT_CLOCK, physical_mode); } } } /******************************************************************** * Print Verilog modules of physical blocks inside a grid (CLB, I/O. etc.) - * This function will traverse the graph of complex logic block (t_pb_graph_node) - * in a recursive way, using a Depth First Search (DFS) algorithm. - * As such, primitive physical blocks (LUTs, FFs, etc.), leaf node of the pb_graph - * will be printed out first, while the top-level will be printed out in the last + * This function will traverse the graph of complex logic block + *(t_pb_graph_node) in a recursive way, using a Depth First Search (DFS) + *algorithm. As such, primitive physical blocks (LUTs, FFs, etc.), leaf node of + *the pb_graph will be printed out first, while the top-level will be printed + *out in the last * - * Note: this function will print a unique Verilog module for each type of - * t_pb_graph_node, i.e., t_pb_type, in the graph, in order to enable highly + * Note: this function will print a unique Verilog module for each type of + * t_pb_graph_node, i.e., t_pb_type, in the graph, in order to enable highly * hierarchical Verilog organization as well as simplify the Verilog file sizes. * * Note: DFS is the right way. Do NOT use BFS. * DFS can guarantee that all the sub-modules can be registered properly - * to its parent in module manager + * to its parent in module manager *******************************************************************/ -static -void rec_build_logical_tile_modules(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const VprDeviceAnnotation& device_annotation, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - t_pb_graph_node* physical_pb_graph_node, - const bool& verbose) { +static void rec_build_logical_tile_modules( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const VprDeviceAnnotation& device_annotation, + const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, t_pb_graph_node* physical_pb_graph_node, + const bool& verbose) { /* Check cur_pb_graph_node*/ VTR_ASSERT(nullptr != physical_pb_graph_node); /* Get the pb_type definition related to the node */ - t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; + t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; /* Find the mode that physical implementation of a pb_type */ t_mode* physical_mode = device_annotation.physical_mode(physical_pb_type); - /* For non-leaf node in the pb_type graph: - * Recursively Depth-First Generate all the child pb_type at the level + /* For non-leaf node in the pb_type graph: + * Recursively Depth-First Generate all the child pb_type at the level */ - if (false == is_primitive_pb_type(physical_pb_type)) { + if (false == is_primitive_pb_type(physical_pb_type)) { for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) { /* Go recursive to visit the children */ - rec_build_logical_tile_modules(module_manager, decoder_lib, - device_annotation, - circuit_lib, mux_lib, - sram_orgz_type, sram_model, - &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][0]), - verbose); + rec_build_logical_tile_modules( + module_manager, decoder_lib, device_annotation, circuit_lib, mux_lib, + sram_orgz_type, sram_model, + &(physical_pb_graph_node + ->child_pb_graph_nodes[physical_mode->index][ipb][0]), + verbose); } } /* For leaf node, a primitive Verilog module will be generated */ - if (true == is_primitive_pb_type(physical_pb_type)) { - build_primitive_block_module(module_manager, decoder_lib, - device_annotation, - circuit_lib, - sram_orgz_type, sram_model, - physical_pb_graph_node, - verbose); + if (true == is_primitive_pb_type(physical_pb_type)) { + build_primitive_block_module(module_manager, decoder_lib, device_annotation, + circuit_lib, sram_orgz_type, sram_model, + physical_pb_graph_node, verbose); /* Finish for primitive node, return */ return; } /* Generate the name of the Verilog module for this pb_type */ - std::string pb_module_name = generate_physical_block_module_name(physical_pb_type); + std::string pb_module_name = + generate_physical_block_module_name(physical_pb_type); - VTR_LOGV(verbose, - "Building module '%s'...", - pb_module_name.c_str()); + VTR_LOGV(verbose, "Building module '%s'...", pb_module_name.c_str()); /* Register the Verilog module in module manager */ ModuleId pb_module = module_manager.add_module(pb_module_name); @@ -881,7 +941,8 @@ void rec_build_logical_tile_modules(ModuleManager& module_manager, module_manager.set_module_usage(pb_module, ModuleManager::MODULE_GRID); /* Add ports to the Verilog module */ - add_pb_type_ports_to_module_manager(module_manager, pb_module, physical_pb_type); + add_pb_type_ports_to_module_manager(module_manager, pb_module, + physical_pb_type); /* Vectors to record all the memory modules have been added * They are used to add module nets of configuration bus @@ -892,124 +953,144 @@ void rec_build_logical_tile_modules(ModuleManager& module_manager, /* Add all the child Verilog modules as instances */ for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { /* Get the name and module id for this child pb_type */ - std::string child_pb_module_name = generate_physical_block_module_name(&(physical_mode->pb_type_children[ichild])); + std::string child_pb_module_name = generate_physical_block_module_name( + &(physical_mode->pb_type_children[ichild])); ModuleId child_pb_module = module_manager.find_module(child_pb_module_name); /* We must have one valid id! */ VTR_ASSERT(true == module_manager.valid_module_id(child_pb_module)); /* Each child may exist multiple times in the hierarchy*/ - for (int inst = 0; inst < physical_mode->pb_type_children[ichild].num_pb; ++inst) { - size_t child_instance_id = module_manager.num_instance(pb_module, child_pb_module); - /* Ensure the instance of this child module is the same as placement index, - * This check is necessary because placement_index is used to identify instance id for children - * when adding local interconnection for this pb_type + for (int inst = 0; inst < physical_mode->pb_type_children[ichild].num_pb; + ++inst) { + size_t child_instance_id = + module_manager.num_instance(pb_module, child_pb_module); + /* Ensure the instance of this child module is the same as placement + * index, This check is necessary because placement_index is used to + * identify instance id for children when adding local interconnection for + * this pb_type */ - VTR_ASSERT(child_instance_id == (size_t)physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ichild][inst].placement_index); + VTR_ASSERT(child_instance_id == + (size_t)physical_pb_graph_node + ->child_pb_graph_nodes[physical_mode->index][ichild][inst] + .placement_index); /* Add the memory module as a child of primitive module */ - module_manager.add_child_module(pb_module, child_pb_module); + module_manager.add_child_module(pb_module, child_pb_module); - /* Set an instance name to bind to a block in bitstream generation and SDC generation! */ - std::string child_pb_instance_name = generate_physical_block_instance_name(&(physical_pb_type->modes[physical_mode->index].pb_type_children[ichild]), inst); - module_manager.set_child_instance_name(pb_module, child_pb_module, child_instance_id, child_pb_instance_name); + /* Set an instance name to bind to a block in bitstream generation and SDC + * generation! */ + std::string child_pb_instance_name = + generate_physical_block_instance_name( + &(physical_pb_type->modes[physical_mode->index] + .pb_type_children[ichild]), + inst); + module_manager.set_child_instance_name( + pb_module, child_pb_module, child_instance_id, child_pb_instance_name); - /* Identify if this sub module includes configuration bits, + /* Identify if this sub module includes configuration bits, * we will update the memory module and instance list */ if (0 < find_module_num_config_bits(module_manager, child_pb_module, - circuit_lib, sram_model, + circuit_lib, sram_model, sram_orgz_type)) { - module_manager.add_configurable_child(pb_module, child_pb_module, child_instance_id); + module_manager.add_configurable_child(pb_module, child_pb_module, + child_instance_id); } } } - /* Add modules and nets for programmable/non-programmable interconnections - * inside the Verilog module + /* Add modules and nets for programmable/non-programmable interconnections + * inside the Verilog module */ - add_module_pb_graph_interc(module_manager, pb_module, - memory_modules, memory_instances, - device_annotation, - circuit_lib, physical_pb_graph_node, - physical_mode->index); + add_module_pb_graph_interc(module_manager, pb_module, memory_modules, + memory_instances, device_annotation, circuit_lib, + physical_pb_graph_node, physical_mode->index); /* Add global ports to the pb_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 a list of it + * 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 + * a list of it */ add_module_global_ports_from_child_modules(module_manager, pb_module); - /* Count GPIO ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it + /* Count GPIO ports from the sub-modules under this Verilog module + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it */ add_module_gpio_ports_from_child_modules(module_manager, pb_module); /* Count shared SRAM ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it */ - size_t module_num_shared_config_bits = find_module_num_shared_config_bits_from_child_modules(module_manager, pb_module); + size_t module_num_shared_config_bits = + find_module_num_shared_config_bits_from_child_modules(module_manager, + pb_module); if (0 < module_num_shared_config_bits) { - add_reserved_sram_ports_to_module_manager(module_manager, pb_module, module_num_shared_config_bits); + add_reserved_sram_ports_to_module_manager(module_manager, pb_module, + module_num_shared_config_bits); } /* Count SRAM ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it */ - size_t module_num_config_bits = find_module_num_config_bits_from_child_modules(module_manager, pb_module, circuit_lib, sram_model, sram_orgz_type); + size_t module_num_config_bits = + find_module_num_config_bits_from_child_modules( + module_manager, pb_module, circuit_lib, sram_model, sram_orgz_type); if (0 < module_num_config_bits) { - add_sram_ports_to_module_manager(module_manager, pb_module, circuit_lib, sram_model, sram_orgz_type, module_num_config_bits); + add_sram_ports_to_module_manager(module_manager, pb_module, circuit_lib, + sram_model, sram_orgz_type, + module_num_config_bits); } /* Add module nets to connect memory cells inside - * This is a one-shot addition that covers all the memory modules in this pb module! + * This is a one-shot addition that covers all the memory modules in this pb + * module! */ if (0 < module_manager.configurable_children(pb_module).size()) { - add_module_nets_memory_config_bus(module_manager, decoder_lib, pb_module, - sram_orgz_type, circuit_lib.design_tech_type(sram_model)); + add_module_nets_memory_config_bus(module_manager, decoder_lib, pb_module, + sram_orgz_type, + circuit_lib.design_tech_type(sram_model)); } VTR_LOGV(verbose, "Done\n"); } /***************************************************************************** - * This function will create a Verilog file and print out a Verilog netlist - * for a type of physical block + * This function will create a Verilog file and print out a Verilog netlist + * for a type of physical block * - * For IO blocks: + * For IO blocks: * The param 'border_side' is required, which is specify which side of fabric * the I/O block locates at. *****************************************************************************/ -static -void build_physical_tile_module(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const VprDeviceAnnotation& vpr_device_annotation, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - t_physical_tile_type_ptr phy_block_type, - const e_side& border_side, - const bool& duplicate_grid_pin, - const bool& verbose) { - /* Create a Module for the top-level physical block, and add to module manager */ - std::string grid_module_name = generate_grid_block_module_name(std::string(GRID_MODULE_NAME_PREFIX), - std::string(phy_block_type->name), - is_io_type(phy_block_type), - border_side); - VTR_LOGV(verbose, - "Building physical tile '%s'...", - grid_module_name.c_str()); +static void build_physical_tile_module( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const VprDeviceAnnotation& vpr_device_annotation, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, t_physical_tile_type_ptr phy_block_type, + const e_side& border_side, const bool& duplicate_grid_pin, + const bool& verbose) { + /* Create a Module for the top-level physical block, and add to module manager + */ + std::string grid_module_name = generate_grid_block_module_name( + std::string(GRID_MODULE_NAME_PREFIX), std::string(phy_block_type->name), + is_io_type(phy_block_type), border_side); + VTR_LOGV(verbose, "Building physical tile '%s'...", grid_module_name.c_str()); - ModuleId grid_module = module_manager.add_module(grid_module_name); + ModuleId grid_module = module_manager.add_module(grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); /* Now each physical tile may have a number of logical blocks * OpenFPGA only considers the physical implementation of the tiles. - * So, we do not allow multiple equivalent sites to be defined - * under a physical tile type. - * If you need different equivalent sites, you can always define + * So, we do not allow multiple equivalent sites to be defined + * under a physical tile type. + * If you need different equivalent sites, you can always define * it as a mode under a */ for (const t_sub_tile& sub_tile : phy_block_type->sub_tiles) { @@ -1020,28 +1101,34 @@ void build_physical_tile_module(ModuleManager& module_manager, if (nullptr == lb_type->pb_graph_head) { continue; } - std::string pb_module_name = generate_physical_block_module_name(lb_type->pb_graph_head->pb_type); + std::string pb_module_name = + generate_physical_block_module_name(lb_type->pb_graph_head->pb_type); ModuleId pb_module = module_manager.find_module(pb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); /* Add all the sub modules */ - size_t pb_instance_id = module_manager.num_instance(grid_module, pb_module); + size_t pb_instance_id = + module_manager.num_instance(grid_module, pb_module); module_manager.add_child_module(grid_module, pb_module, false); /* Add a custom I/O child with coordinate 'z' */ - module_manager.add_io_child(grid_module, pb_module, pb_instance_id, vtr::Point(iz, 0)); + module_manager.add_io_child(grid_module, pb_module, pb_instance_id, + vtr::Point(iz, 0)); /* Give the child module with a unique instance name */ - std::string instance_name = generate_physical_block_instance_name(lb_type->pb_graph_head->pb_type, iz); + std::string instance_name = generate_physical_block_instance_name( + lb_type->pb_graph_head->pb_type, iz); /* Set an instance name to bind to a block in bitstream generation */ - module_manager.set_child_instance_name(grid_module, pb_module, pb_instance_id, instance_name); + module_manager.set_child_instance_name(grid_module, pb_module, + pb_instance_id, instance_name); - /* Identify if this sub module includes configuration bits, + /* Identify if this sub module includes configuration bits, * we will update the memory module and instance list */ if (0 < find_module_num_config_bits(module_manager, pb_module, - circuit_lib, sram_model, + circuit_lib, sram_model, sram_orgz_type)) { - module_manager.add_configurable_child(grid_module, pb_module, pb_instance_id); + module_manager.add_configurable_child(grid_module, pb_module, + pb_instance_id); } } } @@ -1050,8 +1137,8 @@ void build_physical_tile_module(ModuleManager& module_manager, if (false == duplicate_grid_pin) { /* Default way to add these ports by following the definition in pb_types */ add_grid_module_pb_type_ports(module_manager, grid_module, - vpr_device_annotation, - phy_block_type, border_side); + vpr_device_annotation, phy_block_type, + border_side); /* Add module nets to connect the pb_type ports to sub modules */ for (const t_sub_tile& sub_tile : phy_block_type->sub_tiles) { VTR_ASSERT(sub_tile.equivalent_sites.size() == 1); @@ -1060,14 +1147,15 @@ void build_physical_tile_module(ModuleManager& module_manager, if (nullptr == lb_type->pb_graph_head) { continue; } - std::string pb_module_name = generate_physical_block_module_name(lb_type->pb_graph_head->pb_type); + std::string pb_module_name = + generate_physical_block_module_name(lb_type->pb_graph_head->pb_type); ModuleId pb_module = module_manager.find_module(pb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); - for (const size_t& child_instance : module_manager.child_module_instances(grid_module, pb_module)) { - add_grid_module_nets_connect_pb_type_ports(module_manager, grid_module, - pb_module, child_instance, - vpr_device_annotation, - phy_block_type, border_side); + for (const size_t& child_instance : + module_manager.child_module_instances(grid_module, pb_module)) { + add_grid_module_nets_connect_pb_type_ports( + module_manager, grid_module, pb_module, child_instance, + vpr_device_annotation, phy_block_type, border_side); } } } else { @@ -1076,7 +1164,7 @@ void build_physical_tile_module(ModuleManager& module_manager, add_grid_module_duplicated_pb_type_ports(module_manager, grid_module, vpr_device_annotation, phy_block_type, border_side); - + /* Add module nets to connect the duplicated pb_type ports to sub modules */ for (const t_sub_tile& sub_tile : phy_block_type->sub_tiles) { VTR_ASSERT(sub_tile.equivalent_sites.size() == 1); @@ -1085,54 +1173,68 @@ void build_physical_tile_module(ModuleManager& module_manager, if (nullptr == lb_type->pb_graph_head) { continue; } - std::string pb_module_name = generate_physical_block_module_name(lb_type->pb_graph_head->pb_type); + std::string pb_module_name = + generate_physical_block_module_name(lb_type->pb_graph_head->pb_type); ModuleId pb_module = module_manager.find_module(pb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); - for (const size_t& child_instance : module_manager.child_module_instances(grid_module, pb_module)) { - add_grid_module_nets_connect_duplicated_pb_type_ports(module_manager, grid_module, - pb_module, child_instance, - vpr_device_annotation, - phy_block_type, border_side); + for (const size_t& child_instance : + module_manager.child_module_instances(grid_module, pb_module)) { + add_grid_module_nets_connect_duplicated_pb_type_ports( + module_manager, grid_module, pb_module, child_instance, + vpr_device_annotation, phy_block_type, border_side); } } } /* Add global ports to the pb_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 a list of it + * 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 + * a list of it */ add_module_global_ports_from_child_modules(module_manager, grid_module); - /* Count GPIO ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it + /* Count GPIO ports from the sub-modules under this Verilog module + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it */ add_module_gpio_ports_from_child_modules(module_manager, grid_module); /* Count shared SRAM ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it */ - size_t module_num_shared_config_bits = find_module_num_shared_config_bits_from_child_modules(module_manager, grid_module); + size_t module_num_shared_config_bits = + find_module_num_shared_config_bits_from_child_modules(module_manager, + grid_module); if (0 < module_num_shared_config_bits) { - add_reserved_sram_ports_to_module_manager(module_manager, grid_module, module_num_shared_config_bits); + add_reserved_sram_ports_to_module_manager(module_manager, grid_module, + module_num_shared_config_bits); } /* Count SRAM ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it */ - size_t module_num_config_bits = find_module_num_config_bits_from_child_modules(module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type); + size_t module_num_config_bits = + find_module_num_config_bits_from_child_modules( + module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type); if (0 < module_num_config_bits) { - add_pb_sram_ports_to_module_manager(module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type, module_num_config_bits); + add_pb_sram_ports_to_module_manager(module_manager, grid_module, + circuit_lib, sram_model, sram_orgz_type, + module_num_config_bits); } /* Add module nets to connect memory cells inside - * This is a one-shot addition that covers all the memory modules in this pb module! + * This is a one-shot addition that covers all the memory modules in this pb + * module! */ if (0 < module_manager.configurable_children(grid_module).size()) { - add_pb_module_nets_memory_config_bus(module_manager, decoder_lib, grid_module, - sram_orgz_type, circuit_lib.design_tech_type(sram_model)); + add_pb_module_nets_memory_config_bus( + module_manager, decoder_lib, grid_module, sram_orgz_type, + circuit_lib.design_tech_type(sram_model)); } VTR_LOGV(verbose, "Done\n"); @@ -1143,9 +1245,10 @@ void build_physical_tile_module(ModuleManager& module_manager, * This function will achieve this goal in two step: * - Build the modules for each logical tile which is based on pb_graph * Note that there the pin/port does not carry any fixed physical location - * - Build the modules for each physical tile which is based on physical_tile_type_ptr - * Here, multiple logical tiles can be considered and each port/pin has a fixed - * physical location. This is where the feature of duplicate_pin_pin will be applied + * - Build the modules for each physical tile which is based on + *physical_tile_type_ptr Here, multiple logical tiles can be considered and each + *port/pin has a fixed physical location. This is where the feature of + *duplicate_pin_pin will be applied * - Only one module for each I/O on each border side (IO_TYPE) * - Only one module for each CLB (FILL_TYPE) * - Only one module for each heterogeneous block @@ -1158,32 +1261,30 @@ void build_grid_modules(ModuleManager& module_manager, const MuxLibrary& mux_lib, const e_config_protocol_type& sram_orgz_type, const CircuitModelId& sram_model, - const bool& duplicate_grid_pin, - const bool& verbose) { + const bool& duplicate_grid_pin, const bool& verbose) { /* Start time count */ vtr::ScopedStartFinishTimer timer("Build grid modules"); - /* Enumerate the types of logical tiles, and build a module for each + /* Enumerate the types of logical tiles, and build a module for each * Build modules for all the pb_types/pb_graph_nodes - * use a Depth-First Search Algorithm to print the sub-modules + * use a Depth-First Search Algorithm to print the sub-modules * Note: DFS is the right way. Do NOT use BFS. * DFS can guarantee that all the sub-modules can be registered properly - * to its parent in module manager + * to its parent in module manager */ - /* Build modules starting from the top-level pb_type/pb_graph_node, and traverse the graph in a recursive way */ + /* Build modules starting from the top-level pb_type/pb_graph_node, and + * traverse the graph in a recursive way */ VTR_LOG("Building logical tiles..."); VTR_LOGV(verbose, "\n"); - for (const t_logical_block_type& logical_tile : device_ctx.logical_block_types) { + for (const t_logical_block_type& logical_tile : + device_ctx.logical_block_types) { /* Bypass empty pb_graph */ if (nullptr == logical_tile.pb_graph_head) { continue; } - rec_build_logical_tile_modules(module_manager, decoder_lib, - device_annotation, - circuit_lib, mux_lib, - sram_orgz_type, sram_model, - logical_tile.pb_graph_head, - verbose); + rec_build_logical_tile_modules( + module_manager, decoder_lib, device_annotation, circuit_lib, mux_lib, + sram_orgz_type, sram_model, logical_tile.pb_graph_head, verbose); } VTR_LOG("Done\n"); @@ -1192,7 +1293,8 @@ void build_grid_modules(ModuleManager& module_manager, */ VTR_LOG("Building physical tiles..."); VTR_LOGV(verbose, "\n"); - for (const t_physical_tile_type& physical_tile : device_ctx.physical_tile_types) { + for (const t_physical_tile_type& physical_tile : + device_ctx.physical_tile_types) { /* Bypass empty type or nullptr */ if (true == is_empty_type(&physical_tile)) { continue; @@ -1201,31 +1303,24 @@ void build_grid_modules(ModuleManager& module_manager, * We will search the grids and see where the I/O blocks are located: * - If a I/O block locates on border sides of FPGA fabric: * i.e., one or more from {TOP, RIGHT, BOTTOM, LEFT}, - * we will generate one module for each border side + * we will generate one module for each border side * - If a I/O block locates in the center of FPGA fabric: - * we will generate one module with NUM_SIDES (same treatment as regular grids) + * we will generate one module with NUM_SIDES (same treatment as regular + * grids) */ - std::set io_type_sides = find_physical_io_tile_located_sides(device_ctx.grid, - &physical_tile); + std::set io_type_sides = + find_physical_io_tile_located_sides(device_ctx.grid, &physical_tile); for (const e_side& io_type_side : io_type_sides) { build_physical_tile_module(module_manager, decoder_lib, - device_annotation, - circuit_lib, - sram_orgz_type, sram_model, - &physical_tile, - io_type_side, - duplicate_grid_pin, - verbose); - } + device_annotation, circuit_lib, + sram_orgz_type, sram_model, &physical_tile, + io_type_side, duplicate_grid_pin, verbose); + } } else { /* For CLB and heterogenenous blocks */ - build_physical_tile_module(module_manager, decoder_lib, - device_annotation, - circuit_lib, - sram_orgz_type, sram_model, - &physical_tile, - NUM_SIDES, - duplicate_grid_pin, + build_physical_tile_module(module_manager, decoder_lib, device_annotation, + circuit_lib, sram_orgz_type, sram_model, + &physical_tile, NUM_SIDES, duplicate_grid_pin, verbose); } } diff --git a/openfpga/src/fabric/build_grid_modules.h b/openfpga/src/fabric/build_grid_modules.h index 53e7f92cd..61c0963c3 100644 --- a/openfpga/src/fabric/build_grid_modules.h +++ b/openfpga/src/fabric/build_grid_modules.h @@ -4,11 +4,11 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" -#include "vpr_device_annotation.h" +#include "decoder_library.h" #include "module_manager.h" #include "mux_library.h" -#include "decoder_library.h" +#include "vpr_context.h" +#include "vpr_device_annotation.h" /******************************************************************** * Function declaration @@ -25,8 +25,7 @@ void build_grid_modules(ModuleManager& module_manager, const MuxLibrary& mux_lib, const e_config_protocol_type& sram_orgz_type, const CircuitModelId& sram_model, - const bool& duplicate_grid_pin, - const bool& verbose); + const bool& duplicate_grid_pin, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_lut_modules.cpp b/openfpga/src/fabric/build_lut_modules.cpp index a8442f62f..a48616486 100644 --- a/openfpga/src/fabric/build_lut_modules.cpp +++ b/openfpga/src/fabric/build_lut_modules.cpp @@ -1,23 +1,21 @@ -/******************************************************************** - * This file include functions that create modules for - * the Look-Up Tables (LUTs) +/******************************************************************** + * This file include functions that create modules for + * the Look-Up Tables (LUTs) ********************************************************************/ #include #include /* Headers from vtrutil library */ -#include "vtr_assert.h" -#include "vtr_log.h" -#include "vtr_time.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" +#include "build_lut_modules.h" +#include "build_module_graph_utils.h" #include "circuit_library_utils.h" #include "module_manager.h" #include "module_manager_utils.h" - -#include "build_module_graph_utils.h" -#include "build_lut_modules.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" /* begin namespace openfpga */ namespace openfpga { @@ -27,66 +25,76 @@ namespace openfpga { * This function supports both single-output and fracturable LUTs * The module will be organized in a connected graph of the following instances: * 1. Multiplexer used inside LUT - * 2. Input buffers + * 2. Input buffers * 3. Input inverters * 4. Output buffers. * 6. AND/OR gates to tri-state LUT inputs ********************************************************************/ -static -void build_lut_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const CircuitModelId& lut_model) { +static void build_lut_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const CircuitModelId& lut_model) { /* Get the global ports required by LUT - * Note that this function will only add global ports from LUT circuit model definition itself - * We should NOT go recursively here. - * The global ports of sub module will be handled by another function !!! + * Note that this function will only add global ports from LUT circuit model + * definition itself We should NOT go recursively here. The global ports of + * sub module will be handled by another function !!! * add_module_global_ports_from_child_modules(module_manager, lut_module); */ - std::vector lut_global_ports = circuit_lib.model_global_ports_by_type(lut_model, CIRCUIT_MODEL_PORT_INPUT, false, true); + std::vector lut_global_ports = + circuit_lib.model_global_ports_by_type(lut_model, CIRCUIT_MODEL_PORT_INPUT, + false, true); /* Get the input ports from the mux */ - std::vector lut_input_ports = circuit_lib.model_ports_by_type(lut_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector lut_input_ports = + circuit_lib.model_ports_by_type(lut_model, CIRCUIT_MODEL_PORT_INPUT, true); /* Find the inputs that drive the internal LUT MUX */ - std::vector lut_mux_input_ports = find_lut_circuit_model_input_port(circuit_lib, lut_model, false); + std::vector lut_mux_input_ports = + find_lut_circuit_model_input_port(circuit_lib, lut_model, false); /* Get the output ports from the mux */ - std::vector lut_output_ports = circuit_lib.model_ports_by_type(lut_model, CIRCUIT_MODEL_PORT_OUTPUT, false); + std::vector lut_output_ports = circuit_lib.model_ports_by_type( + lut_model, CIRCUIT_MODEL_PORT_OUTPUT, false); /* Find the outputs that are driven the internal LUT MUX */ - std::vector lut_mux_output_ports = find_lut_circuit_model_output_port(circuit_lib, lut_model, false); + std::vector lut_mux_output_ports = + find_lut_circuit_model_output_port(circuit_lib, lut_model, false); - /* Classify SRAM ports into two categories: regular (not for mode select) and mode-select */ - std::vector lut_regular_sram_ports = find_circuit_regular_sram_ports(circuit_lib, lut_model); - std::vector lut_mode_select_sram_ports = find_circuit_mode_select_sram_ports(circuit_lib, lut_model); + /* Classify SRAM ports into two categories: regular (not for mode select) and + * mode-select */ + std::vector lut_regular_sram_ports = + find_circuit_regular_sram_ports(circuit_lib, lut_model); + std::vector lut_mode_select_sram_ports = + find_circuit_mode_select_sram_ports(circuit_lib, lut_model); - /*********************************************** + /*********************************************** * Model Port Sanity Check - ***********************************************/ + ***********************************************/ /* Make sure that the number of ports and sizes of ports are what we want */ if (false == circuit_lib.is_lut_fracturable(lut_model)) { - /* Single-output LUTs: + /* Single-output LUTs: * We should have only 1 input port, 1 output port and 1 SRAM port */ - VTR_ASSERT (1 == lut_mux_input_ports.size()); - VTR_ASSERT (1 == lut_mux_output_ports.size()); - VTR_ASSERT (1 == lut_regular_sram_ports.size()); - VTR_ASSERT (0 == lut_mode_select_sram_ports.size()); + VTR_ASSERT(1 == lut_mux_input_ports.size()); + VTR_ASSERT(1 == lut_mux_output_ports.size()); + VTR_ASSERT(1 == lut_regular_sram_ports.size()); + VTR_ASSERT(0 == lut_mode_select_sram_ports.size()); } else { - VTR_ASSERT (true == circuit_lib.is_lut_fracturable(lut_model)); + VTR_ASSERT(true == circuit_lib.is_lut_fracturable(lut_model)); /* Fracturable LUT: - * We should have only 1 input port, a few output ports (fracturable outputs) - * and two SRAM ports + * We should have only 1 input port, a few output ports (fracturable + * outputs) and two SRAM ports */ - VTR_ASSERT (1 == lut_mux_input_ports.size()); - VTR_ASSERT (1 <= lut_mux_output_ports.size()); - VTR_ASSERT (1 == lut_regular_sram_ports.size()); - VTR_ASSERT ( (0 == lut_mode_select_sram_ports.size()) - || (1 == lut_mode_select_sram_ports.size())); + VTR_ASSERT(1 == lut_mux_input_ports.size()); + VTR_ASSERT(1 <= lut_mux_output_ports.size()); + VTR_ASSERT(1 == lut_regular_sram_ports.size()); + VTR_ASSERT((0 == lut_mode_select_sram_ports.size()) || + (1 == lut_mode_select_sram_ports.size())); } - /*********************************************** + /*********************************************** * Module Port addition - ***********************************************/ - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId lut_module = module_manager.add_module(circuit_lib.model_name(lut_model)); + ***********************************************/ + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId lut_module = + module_manager.add_module(circuit_lib.model_name(lut_model)); VTR_ASSERT(true == module_manager.valid_module_id(lut_module)); /* Label module usage */ @@ -96,45 +104,62 @@ void build_lut_module(ModuleManager& module_manager, /* Add each global port */ for (const auto& port : lut_global_ports) { /* Configure each global port */ - BasicPort global_port(circuit_lib.port_prefix(port), circuit_lib.port_size(port)); - module_manager.add_port(lut_module, global_port, ModuleManager::MODULE_GLOBAL_PORT); + BasicPort global_port(circuit_lib.port_prefix(port), + circuit_lib.port_size(port)); + module_manager.add_port(lut_module, global_port, + ModuleManager::MODULE_GLOBAL_PORT); } /* Add each input port */ for (const auto& port : lut_input_ports) { - BasicPort input_port(circuit_lib.port_prefix(port), circuit_lib.port_size(port)); - module_manager.add_port(lut_module, input_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort input_port(circuit_lib.port_prefix(port), + circuit_lib.port_size(port)); + module_manager.add_port(lut_module, input_port, + ModuleManager::MODULE_INPUT_PORT); /* Set the port to be wire-connection */ module_manager.set_port_is_wire(lut_module, input_port.get_name(), true); } /* Add each output port */ for (const auto& port : lut_output_ports) { - BasicPort output_port(circuit_lib.port_prefix(port), circuit_lib.port_size(port)); - module_manager.add_port(lut_module, output_port, ModuleManager::MODULE_OUTPUT_PORT); + BasicPort output_port(circuit_lib.port_prefix(port), + circuit_lib.port_size(port)); + module_manager.add_port(lut_module, output_port, + ModuleManager::MODULE_OUTPUT_PORT); /* Set the port to be wire-connection */ module_manager.set_port_is_wire(lut_module, output_port.get_name(), true); } /* Add each regular (not mode select) SRAM port */ for (const auto& port : lut_regular_sram_ports) { - BasicPort mem_port(circuit_lib.port_prefix(port), circuit_lib.port_size(port)); - module_manager.add_port(lut_module, mem_port, ModuleManager::MODULE_INPUT_PORT); - BasicPort mem_inv_port(std::string(circuit_lib.port_prefix(port) + INV_PORT_POSTFIX), circuit_lib.port_size(port)); - module_manager.add_port(lut_module, mem_inv_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort mem_port(circuit_lib.port_prefix(port), + circuit_lib.port_size(port)); + module_manager.add_port(lut_module, mem_port, + ModuleManager::MODULE_INPUT_PORT); + BasicPort mem_inv_port( + std::string(circuit_lib.port_prefix(port) + INV_PORT_POSTFIX), + circuit_lib.port_size(port)); + module_manager.add_port(lut_module, mem_inv_port, + ModuleManager::MODULE_INPUT_PORT); } /* Add each mode-select SRAM port */ for (const auto& port : lut_mode_select_sram_ports) { - BasicPort mem_port(circuit_lib.port_prefix(port), circuit_lib.port_size(port)); - module_manager.add_port(lut_module, mem_port, ModuleManager::MODULE_INPUT_PORT); - BasicPort mem_inv_port(std::string(circuit_lib.port_prefix(port) + INV_PORT_POSTFIX), circuit_lib.port_size(port)); - module_manager.add_port(lut_module, mem_inv_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort mem_port(circuit_lib.port_prefix(port), + circuit_lib.port_size(port)); + module_manager.add_port(lut_module, mem_port, + ModuleManager::MODULE_INPUT_PORT); + BasicPort mem_inv_port( + std::string(circuit_lib.port_prefix(port) + INV_PORT_POSTFIX), + circuit_lib.port_size(port)); + module_manager.add_port(lut_module, mem_inv_port, + ModuleManager::MODULE_INPUT_PORT); } - /*********************************************** + /*********************************************** * Child module addition: Model-select gates - ***********************************************/ - /* Module nets after the mode-selection circuit, this could include LUT inputs */ + ***********************************************/ + /* Module nets after the mode-selection circuit, this could include LUT inputs + */ std::vector mode_selected_nets; - /* Instanciate mode selecting circuit: AND/OR gate + /* Instanciate mode selecting circuit: AND/OR gate * By following the tri-state map of LUT input port * The wiring of input ports will be organized as follows * @@ -160,178 +185,230 @@ void build_lut_module(ModuleManager& module_manager, * +--------------------------------------+ */ /* Get the tri-state port map for the input ports*/ - std::string tri_state_map = circuit_lib.port_tri_state_map(lut_mux_input_ports[0]); + std::string tri_state_map = + circuit_lib.port_tri_state_map(lut_mux_input_ports[0]); size_t mode_select_port_lsb = 0; for (const auto& pin : circuit_lib.pins(lut_mux_input_ports[0])) { - ModulePortId lut_module_input_port_id = module_manager.find_module_port(lut_module, circuit_lib.port_prefix(lut_mux_input_ports[0])); - VTR_ASSERT(true == module_manager.valid_module_port_id(lut_module, lut_module_input_port_id)); + ModulePortId lut_module_input_port_id = module_manager.find_module_port( + lut_module, circuit_lib.port_prefix(lut_mux_input_ports[0])); + VTR_ASSERT(true == module_manager.valid_module_port_id( + lut_module, lut_module_input_port_id)); /* Create a module net for the connection */ ModuleNetId net = module_manager.create_module_net(lut_module); /* Set the source of the net to an lut input port */ - module_manager.add_module_net_source(lut_module, net, lut_module, 0, lut_module_input_port_id, pin); - - /* For an empty tri-state map or a '-' sign in tri-state map, we can short-wire mode select_output_ports */ - if (tri_state_map.empty() || ('-' == tri_state_map[pin]) ) { + module_manager.add_module_net_source(lut_module, net, lut_module, 0, + lut_module_input_port_id, pin); + + /* For an empty tri-state map or a '-' sign in tri-state map, we can + * short-wire mode select_output_ports */ + if (tri_state_map.empty() || ('-' == tri_state_map[pin])) { /* Update the output nets of the mode-select layer */ - mode_selected_nets.push_back(net); + mode_selected_nets.push_back(net); continue; /* Finish here */ } e_circuit_model_gate_type required_gate_type = NUM_CIRCUIT_MODEL_GATE_TYPES; /* Reach here, it means that we need a circuit for mode selection */ if ('0' == tri_state_map[pin]) { - /* We need a 2-input AND gate, in order to tri-state the input + /* We need a 2-input AND gate, in order to tri-state the input * Detailed circuit is as follow: * +---------+ * SRAM --->| 2-input |----> mode_select_output_port * LUT input--->| AND | * +---------+ * When SRAM is set to logic 0, the LUT input is tri-stated - * When SRAM is set to logic 1, the LUT input is effective to the downstream circuits + * When SRAM is set to logic 1, the LUT input is effective to the + * downstream circuits */ - required_gate_type = CIRCUIT_MODEL_GATE_AND; + required_gate_type = CIRCUIT_MODEL_GATE_AND; } else { - VTR_ASSERT ('1' == tri_state_map[pin]); - /* We need a 2-input OR gate, in order to tri-state the input + VTR_ASSERT('1' == tri_state_map[pin]); + /* We need a 2-input OR gate, in order to tri-state the input * Detailed circuit is as follow: * +---------+ * SRAM --->| 2-input |----> mode_select_output_port * LUT input--->| OR | * +---------+ * When SRAM is set to logic 1, the LUT input is tri-stated - * When SRAM is set to logic 0, the LUT input is effective to the downstream circuits + * When SRAM is set to logic 0, the LUT input is effective to the + * downstream circuits */ - required_gate_type = CIRCUIT_MODEL_GATE_OR; - } + required_gate_type = CIRCUIT_MODEL_GATE_OR; + } /* Get the circuit model of the gate */ - CircuitModelId gate_model = circuit_lib.port_tri_state_model(lut_mux_input_ports[0]); + CircuitModelId gate_model = + circuit_lib.port_tri_state_model(lut_mux_input_ports[0]); /* Check this is the gate we want ! */ - VTR_ASSERT (required_gate_type == circuit_lib.gate_type(gate_model)); + VTR_ASSERT(required_gate_type == circuit_lib.gate_type(gate_model)); /* Prepare for the gate instanciation */ /* Get the input ports from the gate */ - std::vector gate_input_ports = circuit_lib.model_ports_by_type(gate_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector gate_input_ports = + circuit_lib.model_ports_by_type(gate_model, CIRCUIT_MODEL_PORT_INPUT, + true); /* Get the output ports from the gate */ - std::vector gate_output_ports = circuit_lib.model_ports_by_type(gate_model, CIRCUIT_MODEL_PORT_OUTPUT, true); - /* Check the port sizes and width: - * we should have only 2 input ports, each of which has a size of 1 - * we should have only 1 output port, each of which has a size of 1 + std::vector gate_output_ports = + circuit_lib.model_ports_by_type(gate_model, CIRCUIT_MODEL_PORT_OUTPUT, + true); + /* Check the port sizes and width: + * we should have only 2 input ports, each of which has a size of 1 + * we should have only 1 output port, each of which has a size of 1 */ - VTR_ASSERT (2 == gate_input_ports.size()); - VTR_ASSERT (1 == gate_output_ports.size()); + VTR_ASSERT(2 == gate_input_ports.size()); + VTR_ASSERT(1 == gate_output_ports.size()); /* Find the module id of gate_model in the module manager */ - ModuleId gate_module = module_manager.find_module(circuit_lib.model_name(gate_model)); + ModuleId gate_module = + module_manager.find_module(circuit_lib.model_name(gate_model)); /* We must have a valid id */ - VTR_ASSERT (true == module_manager.valid_module_id(gate_module)); + VTR_ASSERT(true == module_manager.valid_module_id(gate_module)); size_t gate_instance = module_manager.num_instance(lut_module, gate_module); module_manager.add_child_module(lut_module, gate_module); /* Create a port-to-port net connection: - * Input[0] of the gate is wired to a SRAM mode-select port + * Input[0] of the gate is wired to a SRAM mode-select port * Input[1] of the gate is wired to the input port of LUT - * Output[0] of the gate is wired to the mode_select_output_port + * Output[0] of the gate is wired to the mode_select_output_port */ /* Create a module net for the connection */ ModuleNetId gate_sram_net = module_manager.create_module_net(lut_module); /* Find the module port id of the SRAM port of LUT module */ - ModulePortId lut_module_mode_select_port_id = module_manager.find_module_port(lut_module, circuit_lib.port_prefix(lut_mode_select_sram_ports[0])); - VTR_ASSERT(true == module_manager.valid_module_port_id(lut_module, lut_module_mode_select_port_id)); - /* Set the source of the net to an mode-select SRAM port of the LUT module */ - module_manager.add_module_net_source(lut_module, gate_sram_net, lut_module, 0, lut_module_mode_select_port_id, mode_select_port_lsb); + ModulePortId lut_module_mode_select_port_id = + module_manager.find_module_port( + lut_module, circuit_lib.port_prefix(lut_mode_select_sram_ports[0])); + VTR_ASSERT(true == module_manager.valid_module_port_id( + lut_module, lut_module_mode_select_port_id)); + /* Set the source of the net to an mode-select SRAM port of the LUT module + */ + module_manager.add_module_net_source(lut_module, gate_sram_net, lut_module, + 0, lut_module_mode_select_port_id, + mode_select_port_lsb); /* Find the module port id of the SRAM port of LUT module */ - ModulePortId gate_module_input0_port_id = module_manager.find_module_port(gate_module, circuit_lib.port_prefix(gate_input_ports[0])); - VTR_ASSERT(true == module_manager.valid_module_port_id(gate_module, gate_module_input0_port_id)); + ModulePortId gate_module_input0_port_id = module_manager.find_module_port( + gate_module, circuit_lib.port_prefix(gate_input_ports[0])); + VTR_ASSERT(true == module_manager.valid_module_port_id( + gate_module, gate_module_input0_port_id)); /* Set the sink of the net to an input[0] port of the gate module */ - VTR_ASSERT(1 == module_manager.module_port(gate_module, gate_module_input0_port_id).get_width()); - for (const size_t& gate_pin : module_manager.module_port(gate_module, gate_module_input0_port_id).pins()) { - module_manager.add_module_net_sink(lut_module, gate_sram_net, gate_module, gate_instance, gate_module_input0_port_id, gate_pin); + VTR_ASSERT( + 1 == module_manager.module_port(gate_module, gate_module_input0_port_id) + .get_width()); + for (const size_t& gate_pin : + module_manager.module_port(gate_module, gate_module_input0_port_id) + .pins()) { + module_manager.add_module_net_sink(lut_module, gate_sram_net, gate_module, + gate_instance, + gate_module_input0_port_id, gate_pin); } - /* Use the existing net to connect to the input[1] port of the gate module */ - ModulePortId gate_module_input1_port_id = module_manager.find_module_port(gate_module, circuit_lib.port_prefix(gate_input_ports[1])); - VTR_ASSERT(true == module_manager.valid_module_port_id(gate_module, gate_module_input1_port_id)); - VTR_ASSERT(1 == module_manager.module_port(gate_module, gate_module_input1_port_id).get_width()); - for (const size_t& gate_pin : module_manager.module_port(gate_module, gate_module_input1_port_id).pins()) { - module_manager.add_module_net_sink(lut_module, net, gate_module, gate_instance, gate_module_input1_port_id, gate_pin); + /* Use the existing net to connect to the input[1] port of the gate module + */ + ModulePortId gate_module_input1_port_id = module_manager.find_module_port( + gate_module, circuit_lib.port_prefix(gate_input_ports[1])); + VTR_ASSERT(true == module_manager.valid_module_port_id( + gate_module, gate_module_input1_port_id)); + VTR_ASSERT( + 1 == module_manager.module_port(gate_module, gate_module_input1_port_id) + .get_width()); + for (const size_t& gate_pin : + module_manager.module_port(gate_module, gate_module_input1_port_id) + .pins()) { + module_manager.add_module_net_sink(lut_module, net, gate_module, + gate_instance, + gate_module_input1_port_id, gate_pin); } /* Create a module net for the output connection */ ModuleNetId gate_output_net = module_manager.create_module_net(lut_module); - ModulePortId gate_module_output_port_id = module_manager.find_module_port(gate_module, circuit_lib.port_prefix(gate_output_ports[0])); - VTR_ASSERT(true == module_manager.valid_module_port_id(gate_module, gate_module_output_port_id)); - BasicPort gate_module_output_port = module_manager.module_port(gate_module, gate_module_output_port_id); + ModulePortId gate_module_output_port_id = module_manager.find_module_port( + gate_module, circuit_lib.port_prefix(gate_output_ports[0])); + VTR_ASSERT(true == module_manager.valid_module_port_id( + gate_module, gate_module_output_port_id)); + BasicPort gate_module_output_port = + module_manager.module_port(gate_module, gate_module_output_port_id); VTR_ASSERT(1 == gate_module_output_port.get_width()); - module_manager.add_module_net_source(lut_module, gate_output_net, gate_module, gate_instance, gate_module_output_port_id, gate_module_output_port.get_lsb()); + module_manager.add_module_net_source( + lut_module, gate_output_net, gate_module, gate_instance, + gate_module_output_port_id, gate_module_output_port.get_lsb()); /* Update the output nets of the mode-select layer */ - mode_selected_nets.push_back(gate_output_net); + mode_selected_nets.push_back(gate_output_net); /* update the lsb of mode select port size */ mode_select_port_lsb++; } /* Sanitity check */ - if ( (true == circuit_lib.is_lut_fracturable(lut_model)) - && (false == lut_mode_select_sram_ports.empty()) ) { - if (mode_select_port_lsb != circuit_lib.port_size(lut_mode_select_sram_ports[0])) { + if ((true == circuit_lib.is_lut_fracturable(lut_model)) && + (false == lut_mode_select_sram_ports.empty())) { + if (mode_select_port_lsb != + circuit_lib.port_size(lut_mode_select_sram_ports[0])) { VTR_LOGF_ERROR(__FILE__, __LINE__, - "Circuit model '%s' has a unmatched tri-state map '%s' implied by mode_port size='%d'!\n", - circuit_lib.model_name(lut_model).c_str(), - tri_state_map.c_str(), - circuit_lib.port_size(lut_mode_select_sram_ports[0])); + "Circuit model '%s' has a unmatched tri-state map '%s' " + "implied by mode_port size='%d'!\n", + circuit_lib.model_name(lut_model).c_str(), + tri_state_map.c_str(), + circuit_lib.port_size(lut_mode_select_sram_ports[0])); exit(1); } } - /*********************************************** + /*********************************************** * Child module addition: Input inverters - ***********************************************/ + ***********************************************/ /* Find the circuit model of the input inverter */ - CircuitModelId input_inverter_model = circuit_lib.lut_input_inverter_model(lut_model); - VTR_ASSERT( CircuitModelId::INVALID() != input_inverter_model ); + CircuitModelId input_inverter_model = + circuit_lib.lut_input_inverter_model(lut_model); + VTR_ASSERT(CircuitModelId::INVALID() != input_inverter_model); std::vector lut_mux_sram_inv_nets; /* Now we need to add inverters by instanciating the modules */ - for (size_t pin = 0; pin < circuit_lib.port_size(lut_mux_input_ports[0]); ++pin) { - ModuleNetId lut_mux_sram_inv_net = add_inverter_buffer_child_module_and_nets(module_manager, lut_module, - circuit_lib, input_inverter_model, - mode_selected_nets[pin]); - /* Update the net vector */ + for (size_t pin = 0; pin < circuit_lib.port_size(lut_mux_input_ports[0]); + ++pin) { + ModuleNetId lut_mux_sram_inv_net = + add_inverter_buffer_child_module_and_nets( + module_manager, lut_module, circuit_lib, input_inverter_model, + mode_selected_nets[pin]); + /* Update the net vector */ lut_mux_sram_inv_nets.push_back(lut_mux_sram_inv_net); } - /*********************************************** + /*********************************************** * Child module addition: Input buffers - ***********************************************/ + ***********************************************/ /* Add buffers to mode_select output ports */ /* Find the circuit model of the input inverter */ - CircuitModelId input_buffer_model = circuit_lib.lut_input_buffer_model(lut_model); - VTR_ASSERT( CircuitModelId::INVALID() != input_buffer_model ); + CircuitModelId input_buffer_model = + circuit_lib.lut_input_buffer_model(lut_model); + VTR_ASSERT(CircuitModelId::INVALID() != input_buffer_model); std::vector lut_mux_sram_nets; - /* Now we need to add inverters by instanciating the modules and add module nets */ - for (size_t pin = 0; pin < circuit_lib.port_size(lut_mux_input_ports[0]); ++pin) { - ModuleNetId lut_mux_sram_net = add_inverter_buffer_child_module_and_nets(module_manager, lut_module, - circuit_lib, input_buffer_model, - mode_selected_nets[pin]); - /* Update the net vector */ + /* Now we need to add inverters by instanciating the modules and add module + * nets */ + for (size_t pin = 0; pin < circuit_lib.port_size(lut_mux_input_ports[0]); + ++pin) { + ModuleNetId lut_mux_sram_net = add_inverter_buffer_child_module_and_nets( + module_manager, lut_module, circuit_lib, input_buffer_model, + mode_selected_nets[pin]); + /* Update the net vector */ lut_mux_sram_nets.push_back(lut_mux_sram_net); } - /*********************************************** - * Child module addition: LUT MUX - ***********************************************/ - /* Find the name of LUT MUX: no need to provide a mux size, just give an invalid number (=-1) */ - std::string lut_mux_module_name = generate_mux_subckt_name(circuit_lib, lut_model, size_t(-1), std::string("")); + /*********************************************** + * Child module addition: LUT MUX + ***********************************************/ + /* Find the name of LUT MUX: no need to provide a mux size, just give an + * invalid number (=-1) */ + std::string lut_mux_module_name = generate_mux_subckt_name( + circuit_lib, lut_model, size_t(-1), std::string("")); /* Find the module id of LUT MUX in the module manager */ ModuleId lut_mux_module = module_manager.find_module(lut_mux_module_name); /* We must have a valid id */ - VTR_ASSERT (ModuleId::INVALID() != lut_mux_module); + VTR_ASSERT(ModuleId::INVALID() != lut_mux_module); /* Instanciate a LUT MUX as child module */ - size_t lut_mux_instance = module_manager.num_instance(lut_module, lut_mux_module); + size_t lut_mux_instance = + module_manager.num_instance(lut_module, lut_mux_module); module_manager.add_child_module(lut_module, lut_mux_module); /* TODO: Build module nets to connect @@ -340,22 +417,32 @@ void build_lut_module(ModuleManager& module_manager, * 3. Data input of LUT MUX module to SRAM port of LUT * 4. Data output of LUT MUX module to output ports of LUT */ - ModulePortId lut_mux_sram_port_id = module_manager.find_module_port(lut_mux_module, circuit_lib.port_prefix(lut_regular_sram_ports[0])); - BasicPort lut_mux_sram_port = module_manager.module_port(lut_mux_module, lut_mux_sram_port_id); + ModulePortId lut_mux_sram_port_id = module_manager.find_module_port( + lut_mux_module, circuit_lib.port_prefix(lut_regular_sram_ports[0])); + BasicPort lut_mux_sram_port = + module_manager.module_port(lut_mux_module, lut_mux_sram_port_id); VTR_ASSERT(lut_mux_sram_port.get_width() == lut_mux_sram_nets.size()); /* Wire the port to lut_mux_sram_net */ for (const size_t& pin : lut_mux_sram_port.pins()) { - module_manager.add_module_net_sink(lut_module, lut_mux_sram_nets[pin], lut_mux_module, lut_mux_instance, lut_mux_sram_port_id, pin); - } + module_manager.add_module_net_sink(lut_module, lut_mux_sram_nets[pin], + lut_mux_module, lut_mux_instance, + lut_mux_sram_port_id, pin); + } - ModulePortId lut_mux_sram_inv_port_id = module_manager.find_module_port(lut_mux_module, std::string(circuit_lib.port_prefix(lut_regular_sram_ports[0]) + INV_PORT_POSTFIX)); - BasicPort lut_mux_sram_inv_port = module_manager.module_port(lut_mux_module, lut_mux_sram_inv_port_id); + ModulePortId lut_mux_sram_inv_port_id = module_manager.find_module_port( + lut_mux_module, + std::string(circuit_lib.port_prefix(lut_regular_sram_ports[0]) + + INV_PORT_POSTFIX)); + BasicPort lut_mux_sram_inv_port = + module_manager.module_port(lut_mux_module, lut_mux_sram_inv_port_id); VTR_ASSERT(lut_mux_sram_inv_port.get_width() == lut_mux_sram_inv_nets.size()); /* Wire the port to lut_mux_sram_net */ for (const size_t& pin : lut_mux_sram_inv_port.pins()) { - module_manager.add_module_net_sink(lut_module, lut_mux_sram_inv_nets[pin], lut_mux_module, lut_mux_instance, lut_mux_sram_inv_port_id, pin); - } - + module_manager.add_module_net_sink(lut_module, lut_mux_sram_inv_nets[pin], + lut_mux_module, lut_mux_instance, + lut_mux_sram_inv_port_id, pin); + } + /* lut_module * +------------ * | +------ @@ -364,42 +451,59 @@ void build_lut_module(ModuleManager& module_manager, * | | | * | * net - */ - ModulePortId lut_sram_port_id = module_manager.find_module_port(lut_module, circuit_lib.port_prefix(lut_regular_sram_ports[0])); - BasicPort lut_sram_port = module_manager.module_port(lut_module, lut_sram_port_id); - ModulePortId lut_mux_input_port_id = module_manager.find_module_port(lut_mux_module, circuit_lib.port_prefix(lut_mux_input_ports[0])); - BasicPort lut_mux_input_port = module_manager.module_port(lut_mux_module, lut_mux_input_port_id); + */ + ModulePortId lut_sram_port_id = module_manager.find_module_port( + lut_module, circuit_lib.port_prefix(lut_regular_sram_ports[0])); + BasicPort lut_sram_port = + module_manager.module_port(lut_module, lut_sram_port_id); + ModulePortId lut_mux_input_port_id = module_manager.find_module_port( + lut_mux_module, circuit_lib.port_prefix(lut_mux_input_ports[0])); + BasicPort lut_mux_input_port = + module_manager.module_port(lut_mux_module, lut_mux_input_port_id); VTR_ASSERT(lut_mux_input_port.get_width() == lut_sram_port.get_width()); /* Wire the port to lut_mux_sram_net */ for (size_t pin_id = 0; pin_id < lut_mux_input_port.pins().size(); ++pin_id) { ModuleNetId net = module_manager.create_module_net(lut_module); - module_manager.add_module_net_source(lut_module, net, lut_module, 0, lut_sram_port_id, lut_sram_port.pins()[pin_id]); - module_manager.add_module_net_sink(lut_module, net, lut_mux_module, lut_mux_instance, lut_mux_input_port_id, lut_mux_input_port.pins()[pin_id]); - } + module_manager.add_module_net_source(lut_module, net, lut_module, 0, + lut_sram_port_id, + lut_sram_port.pins()[pin_id]); + module_manager.add_module_net_sink(lut_module, net, lut_mux_module, + lut_mux_instance, lut_mux_input_port_id, + lut_mux_input_port.pins()[pin_id]); + } for (const auto& port : lut_mux_output_ports) { - ModulePortId lut_output_port_id = module_manager.find_module_port(lut_module, circuit_lib.port_prefix(port)); - BasicPort lut_output_port = module_manager.module_port(lut_module, lut_output_port_id); - ModulePortId lut_mux_output_port_id = module_manager.find_module_port(lut_mux_module, circuit_lib.port_prefix(port)); - BasicPort lut_mux_output_port = module_manager.module_port(lut_mux_module, lut_mux_output_port_id); + ModulePortId lut_output_port_id = module_manager.find_module_port( + lut_module, circuit_lib.port_prefix(port)); + BasicPort lut_output_port = + module_manager.module_port(lut_module, lut_output_port_id); + ModulePortId lut_mux_output_port_id = module_manager.find_module_port( + lut_mux_module, circuit_lib.port_prefix(port)); + BasicPort lut_mux_output_port = + module_manager.module_port(lut_mux_module, lut_mux_output_port_id); VTR_ASSERT(lut_mux_output_port.get_width() == lut_output_port.get_width()); /* Wire the port to lut_mux_sram_net */ for (size_t pin_id = 0; pin_id < lut_output_port.pins().size(); ++pin_id) { ModuleNetId net = module_manager.create_module_net(lut_module); - module_manager.add_module_net_source(lut_module, net, lut_mux_module, lut_mux_instance, lut_mux_output_port_id, lut_mux_output_port.pins()[pin_id]); - module_manager.add_module_net_sink(lut_module, net, lut_module, 0, lut_output_port_id, lut_output_port.pins()[pin_id]); - } + module_manager.add_module_net_source( + lut_module, net, lut_mux_module, lut_mux_instance, + lut_mux_output_port_id, lut_mux_output_port.pins()[pin_id]); + module_manager.add_module_net_sink(lut_module, net, lut_module, 0, + lut_output_port_id, + lut_output_port.pins()[pin_id]); + } } /* Add global ports to the pb_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 a list of it + * 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 + * a list of it */ add_module_global_ports_from_child_modules(module_manager, lut_module); } -/******************************************************************** - * Print Verilog modules for the Look-Up Tables (LUTs) +/******************************************************************** + * Print Verilog modules for the Look-Up Tables (LUTs) * in the circuit library ********************************************************************/ void build_lut_modules(ModuleManager& module_manager, @@ -413,8 +517,8 @@ void build_lut_modules(ModuleManager& module_manager, continue; } /* We skip user-defined models */ - if ( (false == circuit_lib.model_verilog_netlist(lut_model).empty()) - || (false == circuit_lib.model_spice_netlist(lut_model).empty()) ) { + if ((false == circuit_lib.model_verilog_netlist(lut_model).empty()) || + (false == circuit_lib.model_spice_netlist(lut_model).empty())) { continue; } build_lut_module(module_manager, circuit_lib, lut_model); diff --git a/openfpga/src/fabric/build_memory_modules.cpp b/openfpga/src/fabric/build_memory_modules.cpp index fe6340a8f..9ce406ca6 100644 --- a/openfpga/src/fabric/build_memory_modules.cpp +++ b/openfpga/src/fabric/build_memory_modules.cpp @@ -1,70 +1,71 @@ /********************************************************************* - * This file includes functions to generate Verilog submodules for + * This file includes functions to generate Verilog submodules for * the memories that are affiliated to multiplexers and other programmable * circuit models, such as IOPADs, LUTs, etc. ********************************************************************/ +#include #include #include -#include /* Headers from vtrutil library */ -#include "vtr_log.h" -#include "vtr_time.h" -#include "vtr_assert.h" - -#include "mux_graph.h" -#include "module_manager.h" -#include "circuit_library_utils.h" -#include "decoder_library_utils.h" -#include "module_manager_utils.h" -#include "mux_utils.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" - #include "build_decoder_modules.h" #include "build_memory_modules.h" +#include "circuit_library_utils.h" +#include "decoder_library_utils.h" +#include "module_manager.h" +#include "module_manager_utils.h" +#include "mux_graph.h" +#include "mux_utils.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" /* begin namespace openfpga */ namespace openfpga { /********************************************************************* - * Add module nets to connect an input port of a memory module to + * Add module nets to connect an input port of a memory module to * an input port of its child module * Restriction: this function is really designed for memory modules - * 1. It assumes that input port name of child module is the same as memory module - * 2. It assumes exact pin-to-pin mapping: - * j-th pin of input port of the i-th child module is wired to the j + i*W -th - * pin of input port of the memory module, where W is the size of port + * 1. It assumes that input port name of child module is the same as memory + *module + * 2. It assumes exact pin-to-pin mapping: + * j-th pin of input port of the i-th child module is wired to the j + i*W + *-th pin of input port of the memory module, where W is the size of port ********************************************************************/ -static -void add_module_input_nets_to_mem_modules(ModuleManager& module_manager, - const ModuleId& mem_module, - const ModulePortId& module_port, - const CircuitLibrary& circuit_lib, - const CircuitPortId& circuit_port, - const ModuleId& child_module, - const size_t& child_index, - const size_t& child_instance) { +static void add_module_input_nets_to_mem_modules( + ModuleManager& module_manager, const ModuleId& mem_module, + const ModulePortId& module_port, const CircuitLibrary& circuit_lib, + const CircuitPortId& circuit_port, const ModuleId& child_module, + const size_t& child_index, const size_t& child_instance) { /* Wire inputs of parent module to inputs of child modules */ ModulePortId src_port_id = module_port; - ModulePortId sink_port_id = module_manager.find_module_port(child_module, circuit_lib.port_prefix(circuit_port)); + ModulePortId sink_port_id = module_manager.find_module_port( + child_module, circuit_lib.port_prefix(circuit_port)); /* Source pin is shifted by the number of memories */ - size_t src_pin_id = module_manager.module_port(mem_module, src_port_id).pins()[child_index]; + size_t src_pin_id = + module_manager.module_port(mem_module, src_port_id).pins()[child_index]; - ModuleNetId net = module_manager.module_instance_port_net(mem_module, - mem_module, 0, - src_port_id, src_pin_id); - if (ModuleNetId::INVALID() == net) { + ModuleNetId net = module_manager.module_instance_port_net( + mem_module, mem_module, 0, src_port_id, src_pin_id); + if (ModuleNetId::INVALID() == net) { net = module_manager.create_module_net(mem_module); - module_manager.add_module_net_source(mem_module, net, mem_module, 0, src_port_id, src_pin_id); + module_manager.add_module_net_source(mem_module, net, mem_module, 0, + src_port_id, src_pin_id); } - for (size_t pin_id = 0; pin_id < module_manager.module_port(child_module, sink_port_id).pins().size(); ++pin_id) { + for (size_t pin_id = 0; + pin_id < + module_manager.module_port(child_module, sink_port_id).pins().size(); + ++pin_id) { /* Sink node of the input net is the input of sram module */ - size_t sink_pin_id = module_manager.module_port(child_module, sink_port_id).pins()[pin_id]; - module_manager.add_module_net_sink(mem_module, net, child_module, child_instance, sink_port_id, sink_pin_id); + size_t sink_pin_id = + module_manager.module_port(child_module, sink_port_id).pins()[pin_id]; + module_manager.add_module_net_sink( + mem_module, net, child_module, child_instance, sink_port_id, sink_pin_id); } } @@ -72,34 +73,42 @@ void add_module_input_nets_to_mem_modules(ModuleManager& module_manager, * Add module nets to connect an output port of a configuration-chain * memory module to an output port of its child module * Restriction: this function is really designed for memory modules - * 1. It assumes that output port name of child module is the same as memory module - * 2. It assumes exact pin-to-pin mapping: - * j-th pin of output port of the i-th child module is wired to the j + i*W -th - * pin of output port of the memory module, where W is the size of port + * 1. It assumes that output port name of child module is the same as memory + *module + * 2. It assumes exact pin-to-pin mapping: + * j-th pin of output port of the i-th child module is wired to the j + i*W + *-th pin of output port of the memory module, where W is the size of port * 3. It assumes fixed port name for output ports ********************************************************************/ -std::vector add_module_output_nets_to_chain_mem_modules(ModuleManager& module_manager, - const ModuleId& mem_module, - const std::string& mem_module_output_name, - const CircuitLibrary& circuit_lib, - const CircuitPortId& circuit_port, - const ModuleId& child_module, - const size_t& child_index, - const size_t& child_instance) { +std::vector add_module_output_nets_to_chain_mem_modules( + ModuleManager& module_manager, const ModuleId& mem_module, + const std::string& mem_module_output_name, const CircuitLibrary& circuit_lib, + const CircuitPortId& circuit_port, const ModuleId& child_module, + const size_t& child_index, const size_t& child_instance) { std::vector module_nets; /* Wire inputs of parent module to inputs of child modules */ - ModulePortId src_port_id = module_manager.find_module_port(child_module, circuit_lib.port_prefix(circuit_port)); - ModulePortId sink_port_id = module_manager.find_module_port(mem_module, mem_module_output_name); - for (size_t pin_id = 0; pin_id < module_manager.module_port(child_module, src_port_id).pins().size(); ++pin_id) { + ModulePortId src_port_id = module_manager.find_module_port( + child_module, circuit_lib.port_prefix(circuit_port)); + ModulePortId sink_port_id = + module_manager.find_module_port(mem_module, mem_module_output_name); + for (size_t pin_id = 0; + pin_id < + module_manager.module_port(child_module, src_port_id).pins().size(); + ++pin_id) { ModuleNetId net = module_manager.create_module_net(mem_module); /* Source pin is shifted by the number of memories */ - size_t src_pin_id = module_manager.module_port(child_module, src_port_id).pins()[pin_id]; + size_t src_pin_id = + module_manager.module_port(child_module, src_port_id).pins()[pin_id]; /* Source node of the input net is the input of memory module */ - module_manager.add_module_net_source(mem_module, net, child_module, child_instance, src_port_id, src_pin_id); + module_manager.add_module_net_source( + mem_module, net, child_module, child_instance, src_port_id, src_pin_id); /* Sink node of the input net is the input of sram module */ - size_t sink_pin_id = child_index * circuit_lib.port_size(circuit_port) + module_manager.module_port(mem_module, sink_port_id).pins()[pin_id]; - module_manager.add_module_net_sink(mem_module, net, mem_module, 0, sink_port_id, sink_pin_id); + size_t sink_pin_id = + child_index * circuit_lib.port_size(circuit_port) + + module_manager.module_port(mem_module, sink_port_id).pins()[pin_id]; + module_manager.add_module_net_sink(mem_module, net, mem_module, 0, + sink_port_id, sink_pin_id); /* Cache the nets */ module_nets.push_back(net); @@ -109,44 +118,42 @@ std::vector add_module_output_nets_to_chain_mem_modules(ModuleManag } /********************************************************************* - * Add module nets to connect an output port of a memory module to + * Add module nets to connect an output port of a memory module to * an output port of its child module * Restriction: this function is really designed for memory modules - * 1. It assumes that output port name of child module is the same as memory module - * 2. It assumes exact pin-to-pin mapping: - * j-th pin of output port of the i-th child module is wired to the j + i*W -th - * pin of output port of the memory module, where W is the size of port + * 1. It assumes that output port name of child module is the same as memory + *module + * 2. It assumes exact pin-to-pin mapping: + * j-th pin of output port of the i-th child module is wired to the j + i*W + *-th pin of output port of the memory module, where W is the size of port ********************************************************************/ -static -void add_module_output_nets_to_mem_modules(ModuleManager& module_manager, - const ModuleId& mem_module, - const CircuitLibrary& circuit_lib, - const std::vector& sram_output_ports, - const ModuleId& child_module, - const size_t& child_index, - const size_t& child_instance) { - +static void add_module_output_nets_to_mem_modules( + ModuleManager& module_manager, const ModuleId& mem_module, + const CircuitLibrary& circuit_lib, + const std::vector& sram_output_ports, + const ModuleId& child_module, const size_t& child_index, + const size_t& child_instance) { for (size_t iport = 0; iport < sram_output_ports.size(); ++iport) { std::string port_name; if (0 == iport) { port_name = generate_configurable_memory_data_out_name(); } else { - VTR_ASSERT( 1 == iport); + VTR_ASSERT(1 == iport); port_name = generate_configurable_memory_inverted_data_out_name(); } - add_module_output_nets_to_chain_mem_modules(module_manager, mem_module, - port_name, circuit_lib, sram_output_ports[iport], - child_module, child_index, child_instance); + add_module_output_nets_to_chain_mem_modules( + module_manager, mem_module, port_name, circuit_lib, + sram_output_ports[iport], child_module, child_index, child_instance); } } /******************************************************************** * Connect all the memory modules under the parent module in a chain - * + * * +--------+ +--------+ +--------+ * ccff_head --->| Memory |--->| Memory |--->... --->| Memory |----> ccff_tail * | Module | | Module | | Module | - * | [0] | | [1] | | [N-1] | + * | [0] | | [1] | | [N-1] | * +--------+ +--------+ +--------+ * For the 1st memory module: * net source is the configuration chain head of the primitive module @@ -158,16 +165,16 @@ void add_module_output_nets_to_mem_modules(ModuleManager& module_manager, * * Note that: * This function is designed for memory modules ONLY! - * Do not use it to replace the + * Do not use it to replace the * add_module_nets_cmos_memory_chain_config_bus() !!! *********************************************************************/ -static -void add_module_nets_to_cmos_memory_config_chain_module(ModuleManager& module_manager, - const ModuleId& parent_module, - const CircuitLibrary& circuit_lib, - const CircuitPortId& model_input_port, - const CircuitPortId& model_output_port) { - for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) { +static void add_module_nets_to_cmos_memory_config_chain_module( + ModuleManager& module_manager, const ModuleId& parent_module, + const CircuitLibrary& circuit_lib, const CircuitPortId& model_input_port, + const CircuitPortId& model_output_port) { + for (size_t mem_index = 0; + mem_index < module_manager.configurable_children(parent_module).size(); + ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; ModulePortId net_src_port_id; @@ -179,42 +186,58 @@ void add_module_nets_to_cmos_memory_config_chain_module(ModuleManager& module_ma if (0 == mem_index) { /* Find the port name of configuration chain head */ std::string src_port_name = generate_configuration_chain_head_name(); - net_src_module_id = parent_module; + net_src_module_id = parent_module; net_src_instance_id = 0; - net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; - net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + net_sink_module_id = + module_manager.configurable_children(parent_module)[mem_index]; + net_sink_instance_id = + module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); } else { /* Find the port name of previous memory module */ std::string src_port_name = circuit_lib.port_prefix(model_output_port); - net_src_module_id = module_manager.configurable_children(parent_module)[mem_index - 1]; - net_src_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index - 1]; - net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + net_src_module_id = + module_manager.configurable_children(parent_module)[mem_index - 1]; + net_src_instance_id = module_manager.configurable_child_instances( + parent_module)[mem_index - 1]; + net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; - net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + net_sink_module_id = + module_manager.configurable_children(parent_module)[mem_index]; + net_sink_instance_id = + module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); } /* Get the pin id for source port */ - BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); /* Get the pin id for sink port */ - BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); /* Port sizes of source and sink should match */ VTR_ASSERT(net_src_port.get_width() == net_sink_port.get_width()); - + /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) { /* Create a net and add source and sink to it */ - ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, parent_module, net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[pin_id]); /* Add net sink */ - module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[pin_id]); } } @@ -224,40 +247,50 @@ void add_module_nets_to_cmos_memory_config_chain_module(ModuleManager& module_ma */ /* Find the port name of previous memory module */ std::string src_port_name = circuit_lib.port_prefix(model_output_port); - ModuleId net_src_module_id = module_manager.configurable_children(parent_module).back(); - size_t net_src_instance_id = module_manager.configurable_child_instances(parent_module).back(); - ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + ModuleId net_src_module_id = + module_manager.configurable_children(parent_module).back(); + size_t net_src_instance_id = + module_manager.configurable_child_instances(parent_module).back(); + ModulePortId net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = generate_configuration_chain_tail_name(); - ModuleId net_sink_module_id = parent_module; + ModuleId net_sink_module_id = parent_module; size_t net_sink_instance_id = 0; - ModulePortId net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + ModulePortId net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); /* Get the pin id for source port */ - BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); /* Get the pin id for sink port */ - BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); /* Port sizes of source and sink should match */ VTR_ASSERT(net_src_port.get_width() == net_sink_port.get_width()); - + /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) { /* Create a net and add source and sink to it */ - ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, parent_module, net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[pin_id]); /* Add net sink */ - module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[pin_id]); } } /******************************************************************** - * Connect the scan input of all the memory modules + * Connect the scan input of all the memory modules * under the parent module in a chain - * + * * +--------+ +--------+ +--------+ * ccff_head --->| Memory |--->| Memory |--->... --->| Memory | * | Module | | Module | | Module | - * | [0] | | [1] | | [N-1] | + * | [0] | | [1] | | [N-1] | * +--------+ +--------+ +--------+ * For the 1st memory module: * net source is the configuration chain head of the primitive module @@ -269,16 +302,16 @@ void add_module_nets_to_cmos_memory_config_chain_module(ModuleManager& module_ma * * Note that: * This function is designed for memory modules ONLY! - * Do not use it to replace the + * Do not use it to replace the * add_module_nets_cmos_memory_chain_config_bus() !!! *********************************************************************/ -static -void add_module_nets_to_cmos_memory_scan_chain_module(ModuleManager& module_manager, - const ModuleId& parent_module, - const CircuitLibrary& circuit_lib, - const CircuitPortId& model_input_port, - const CircuitPortId& model_output_port) { - for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) { +static void add_module_nets_to_cmos_memory_scan_chain_module( + ModuleManager& module_manager, const ModuleId& parent_module, + const CircuitLibrary& circuit_lib, const CircuitPortId& model_input_port, + const CircuitPortId& model_output_port) { + for (size_t mem_index = 0; + mem_index < module_manager.configurable_children(parent_module).size(); + ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; ModulePortId net_src_port_id; @@ -290,42 +323,58 @@ void add_module_nets_to_cmos_memory_scan_chain_module(ModuleManager& module_mana if (0 == mem_index) { /* Find the port name of configuration chain head */ std::string src_port_name = generate_configuration_chain_head_name(); - net_src_module_id = parent_module; + net_src_module_id = parent_module; net_src_instance_id = 0; - net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; - net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + net_sink_module_id = + module_manager.configurable_children(parent_module)[mem_index]; + net_sink_instance_id = + module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); } else { /* Find the port name of previous memory module */ std::string src_port_name = circuit_lib.port_prefix(model_output_port); - net_src_module_id = module_manager.configurable_children(parent_module)[mem_index - 1]; - net_src_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index - 1]; - net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + net_src_module_id = + module_manager.configurable_children(parent_module)[mem_index - 1]; + net_src_instance_id = module_manager.configurable_child_instances( + parent_module)[mem_index - 1]; + net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; - net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + net_sink_module_id = + module_manager.configurable_children(parent_module)[mem_index]; + net_sink_instance_id = + module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); } /* Get the pin id for source port */ - BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); /* Get the pin id for sink port */ - BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); /* Port sizes of source and sink should match */ VTR_ASSERT(net_src_port.get_width() == net_sink_port.get_width()); - + /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) { /* Create a net and add source and sink to it */ - ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, parent_module, net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[pin_id]); /* Add net sink */ - module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[pin_id]); } } } @@ -351,50 +400,60 @@ void add_module_nets_to_cmos_memory_scan_chain_module(ModuleManager& module_mana * | Multiplexer Configuration port | * ********************************************************************/ -static -void build_memory_flatten_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const std::string& module_name, - const CircuitModelId& sram_model, - const size_t& num_mems) { +static void build_memory_flatten_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const std::string& module_name, + const CircuitModelId& sram_model, + const size_t& num_mems) { /* Get the global ports required by the SRAM */ std::vector global_port_types; global_port_types.push_back(CIRCUIT_MODEL_PORT_CLOCK); global_port_types.push_back(CIRCUIT_MODEL_PORT_INPUT); - std::vector sram_global_ports = circuit_lib.model_global_ports_by_type(sram_model, global_port_types, true, false); + std::vector sram_global_ports = + circuit_lib.model_global_ports_by_type(sram_model, global_port_types, true, + false); /* Get the BL/WL ports from the SRAM */ - std::vector sram_bl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BL, true); - std::vector sram_wl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WL, true); + std::vector sram_bl_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BL, true); + std::vector sram_wl_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WL, true); /* Optional: Get the WLR ports from the SRAM */ - std::vector sram_wlr_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR, true); + std::vector sram_wlr_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR, true); /* Get the output ports from the SRAM */ - std::vector sram_output_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector sram_output_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, + true); - /* Ensure that we have only 1 BL, 1 WL and 2 output ports, as well as an optional WLR*/ + /* Ensure that we have only 1 BL, 1 WL and 2 output ports, as well as an + * optional WLR*/ VTR_ASSERT(1 == sram_bl_ports.size()); VTR_ASSERT(1 == sram_wl_ports.size()); VTR_ASSERT(2 > sram_wlr_ports.size()); VTR_ASSERT(2 == sram_output_ports.size()); /* Create a module and add to the module manager */ - ModuleId mem_module = module_manager.add_module(module_name); + ModuleId mem_module = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); /* Label module usage */ module_manager.set_module_usage(mem_module, ModuleManager::MODULE_CONFIG); - + /* Add module ports */ /* Input: BL port */ BasicPort bl_port(std::string(MEMORY_BL_PORT_NAME), num_mems); - ModulePortId mem_bl_port = module_manager.add_port(mem_module, bl_port, ModuleManager::MODULE_INPUT_PORT); + ModulePortId mem_bl_port = module_manager.add_port( + mem_module, bl_port, ModuleManager::MODULE_INPUT_PORT); BasicPort wl_port(std::string(MEMORY_WL_PORT_NAME), num_mems); - ModulePortId mem_wl_port = module_manager.add_port(mem_module, wl_port, ModuleManager::MODULE_INPUT_PORT); + ModulePortId mem_wl_port = module_manager.add_port( + mem_module, wl_port, ModuleManager::MODULE_INPUT_PORT); BasicPort wlr_port(std::string(MEMORY_WLR_PORT_NAME), num_mems); ModulePortId mem_wlr_port = ModulePortId::INVALID(); if (!sram_wlr_ports.empty()) { - mem_wlr_port = module_manager.add_port(mem_module, wlr_port, ModuleManager::MODULE_INPUT_PORT); + mem_wlr_port = module_manager.add_port(mem_module, wlr_port, + ModuleManager::MODULE_INPUT_PORT); } /* Add each output port: port width should match the number of memories */ @@ -403,47 +462,60 @@ void build_memory_flatten_module(ModuleManager& module_manager, if (0 == iport) { port_name = generate_configurable_memory_data_out_name(); } else { - VTR_ASSERT( 1 == iport); + VTR_ASSERT(1 == iport); port_name = generate_configurable_memory_inverted_data_out_name(); } BasicPort output_port(port_name, num_mems); - module_manager.add_port(mem_module, output_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(mem_module, output_port, + ModuleManager::MODULE_OUTPUT_PORT); } /* Find the sram module in the module manager */ - ModuleId sram_mem_module = module_manager.find_module(circuit_lib.model_name(sram_model)); + ModuleId sram_mem_module = + module_manager.find_module(circuit_lib.model_name(sram_model)); /* Instanciate each submodule */ for (size_t i = 0; i < num_mems; ++i) { - size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module); + size_t sram_mem_instance = + module_manager.num_instance(mem_module, sram_mem_module); module_manager.add_child_module(mem_module, sram_mem_module); - module_manager.add_configurable_child(mem_module, sram_mem_module, sram_mem_instance); + module_manager.add_configurable_child(mem_module, sram_mem_module, + sram_mem_instance); /* Build module nets */ /* Wire inputs of parent module to inputs of child modules */ for (const CircuitPortId& port : sram_bl_ports) { - add_module_input_nets_to_mem_modules(module_manager, mem_module, mem_bl_port, circuit_lib, port, sram_mem_module, i, sram_mem_instance); + add_module_input_nets_to_mem_modules( + module_manager, mem_module, mem_bl_port, circuit_lib, port, + sram_mem_module, i, sram_mem_instance); } for (const CircuitPortId& port : sram_wl_ports) { - add_module_input_nets_to_mem_modules(module_manager, mem_module, mem_wl_port, circuit_lib, port, sram_mem_module, i, sram_mem_instance); + add_module_input_nets_to_mem_modules( + module_manager, mem_module, mem_wl_port, circuit_lib, port, + sram_mem_module, i, sram_mem_instance); } for (const CircuitPortId& port : sram_wlr_ports) { - add_module_input_nets_to_mem_modules(module_manager, mem_module, mem_wlr_port, circuit_lib, port, sram_mem_module, i, sram_mem_instance); + add_module_input_nets_to_mem_modules( + module_manager, mem_module, mem_wlr_port, circuit_lib, port, + sram_mem_module, i, sram_mem_instance); } /* Wire outputs of child module to outputs of parent module */ - add_module_output_nets_to_mem_modules(module_manager, mem_module, circuit_lib, sram_output_ports, sram_mem_module, i, sram_mem_instance); + add_module_output_nets_to_mem_modules( + module_manager, mem_module, circuit_lib, sram_output_ports, + sram_mem_module, i, sram_mem_instance); } /* Add global ports to the pb_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 a list of it + * 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 + * a list of it */ add_module_global_ports_from_child_modules(module_manager, mem_module); } /********************************************************************* * Scan-chain organization - * + * * +-------+ +-------+ +-------+ * scan-chain--->| CCFF |--->| CCFF |--->... --->| CCFF |---->scan-chain * input&clock | [0] | | [1] | | [N-1] | output @@ -454,65 +526,71 @@ void build_memory_flatten_module(ModuleManager& module_manager, * | Multiplexer Configuration port | * ********************************************************************/ -static -void build_memory_chain_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const std::string& module_name, - const CircuitModelId& sram_model, - const size_t& num_mems) { - +static void build_memory_chain_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const std::string& module_name, + const CircuitModelId& sram_model, + const size_t& num_mems) { /* Get the input ports from the SRAM */ - std::vector sram_input_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector sram_input_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true); /* Should have only 1 or 2 input port */ - VTR_ASSERT( (1 == sram_input_ports.size()) - || (2 == sram_input_ports.size()) ); + VTR_ASSERT((1 == sram_input_ports.size()) || (2 == sram_input_ports.size())); /* Get the output ports from the SRAM */ - std::vector sram_output_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector sram_output_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, + true); /* Should have only 1 or 2 or 3 output port */ - VTR_ASSERT( (1 == sram_output_ports.size()) - || (2 == sram_output_ports.size()) - || (3 == sram_output_ports.size()) ); + VTR_ASSERT((1 == sram_output_ports.size()) || + (2 == sram_output_ports.size()) || + (3 == sram_output_ports.size())); /* Create a module and add to the module manager */ - ModuleId mem_module = module_manager.add_module(module_name); + ModuleId mem_module = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); /* Label module usage */ module_manager.set_module_usage(mem_module, ModuleManager::MODULE_CONFIG); - - /* Add an input port, which is the head of configuration chain in the module */ + + /* Add an input port, which is the head of configuration chain in the module + */ /* TODO: restriction!!! * consider only the first input of the CCFF model as the D port, * which will be connected to the head of the chain */ - BasicPort chain_head_port(generate_configuration_chain_head_name(), + BasicPort chain_head_port(generate_configuration_chain_head_name(), circuit_lib.port_size(sram_input_ports[0])); - module_manager.add_port(mem_module, chain_head_port, ModuleManager::MODULE_INPUT_PORT); - /* Add an output port, which is the tail of configuration chain in the module */ + module_manager.add_port(mem_module, chain_head_port, + ModuleManager::MODULE_INPUT_PORT); + /* Add an output port, which is the tail of configuration chain in the module + */ /* TODO: restriction!!! * consider only the first output of the CCFF model as the Q port, * which will be connected to the tail of the chain */ - BasicPort chain_tail_port(generate_configuration_chain_tail_name(), + BasicPort chain_tail_port(generate_configuration_chain_tail_name(), circuit_lib.port_size(sram_output_ports[0])); - module_manager.add_port(mem_module, chain_tail_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(mem_module, chain_tail_port, + ModuleManager::MODULE_OUTPUT_PORT); /* There could be 3 conditions w.r.t. the number of output ports: * - Only one output port is defined. In this case, the 1st port is the Q * In such case, only Q will be considered as data output ports - * - Two output port is defined. In this case, the 1st port is the Q while the 2nd port is the QN - * In such case, both Q and QN will be considered as data output ports - * - Three output port is defined. - * In this case: - * - the 1st port is the Q (the chain output) + * - Two output port is defined. In this case, the 1st port is the Q while the + * 2nd port is the QN In such case, both Q and QN will be considered as data + * output ports + * - Three output port is defined. + * In this case: + * - the 1st port is the Q (the chain output) * - the 2nd port is the QN (the inverted data output) * - the 3nd port is the configure-enabled Q - * In such case, configure-enabled Q and QN will be considered as data output ports + * In such case, configure-enabled Q and QN will be considered as data + * output ports */ size_t num_data_output_ports = sram_output_ports.size(); if (3 == sram_output_ports.size()) { num_data_output_ports = 2; - } + } for (size_t iport = 0; iport < num_data_output_ports; ++iport) { std::string port_name; if (0 == iport) { @@ -521,25 +599,30 @@ void build_memory_chain_module(ModuleManager& module_manager, port_name = generate_configurable_memory_inverted_data_out_name(); } BasicPort output_port(port_name, num_mems); - module_manager.add_port(mem_module, output_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(mem_module, output_port, + ModuleManager::MODULE_OUTPUT_PORT); } /* Find the sram module in the module manager */ - ModuleId sram_mem_module = module_manager.find_module(circuit_lib.model_name(sram_model)); + ModuleId sram_mem_module = + module_manager.find_module(circuit_lib.model_name(sram_model)); /* Instanciate each submodule */ for (size_t i = 0; i < num_mems; ++i) { - size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module); + size_t sram_mem_instance = + module_manager.num_instance(mem_module, sram_mem_module); module_manager.add_child_module(mem_module, sram_mem_module); - module_manager.add_configurable_child(mem_module, sram_mem_module, sram_mem_instance); + module_manager.add_configurable_child(mem_module, sram_mem_module, + sram_mem_instance); - /* Build module nets to wire outputs of sram modules to outputs of memory module */ + /* Build module nets to wire outputs of sram modules to outputs of memory + * module */ for (size_t iport = 0; iport < num_data_output_ports; ++iport) { std::string port_name; if (0 == iport) { port_name = generate_configurable_memory_data_out_name(); } else { - VTR_ASSERT( 1 == iport); + VTR_ASSERT(1 == iport); port_name = generate_configurable_memory_inverted_data_out_name(); } /* Find the proper data output port @@ -550,28 +633,32 @@ void build_memory_chain_module(ModuleManager& module_manager, if ((3 == sram_output_ports.size()) && (0 == iport)) { data_output_port_to_connect = sram_output_ports.back(); } - - std::vector output_nets = add_module_output_nets_to_chain_mem_modules(module_manager, mem_module, - port_name, circuit_lib, data_output_port_to_connect, - sram_mem_module, i, sram_mem_instance); + + std::vector output_nets = + add_module_output_nets_to_chain_mem_modules( + module_manager, mem_module, port_name, circuit_lib, + data_output_port_to_connect, sram_mem_module, i, sram_mem_instance); } } /* Build module nets to wire the configuration chain */ - add_module_nets_to_cmos_memory_config_chain_module(module_manager, mem_module, - circuit_lib, sram_input_ports[0], sram_output_ports[0]); + add_module_nets_to_cmos_memory_config_chain_module( + module_manager, mem_module, circuit_lib, sram_input_ports[0], + sram_output_ports[0]); - /* If there is a second input defined, - * add nets to short wire the 2nd inputs to the first inputs + /* If there is a second input defined, + * add nets to short wire the 2nd inputs to the first inputs */ if (2 == sram_input_ports.size()) { - add_module_nets_to_cmos_memory_scan_chain_module(module_manager, mem_module, - circuit_lib, sram_input_ports[1], sram_output_ports[0]); + add_module_nets_to_cmos_memory_scan_chain_module( + module_manager, mem_module, circuit_lib, sram_input_ports[1], + sram_output_ports[0]); } /* Add global ports to the pb_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 a list of it + * 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 + * a list of it */ add_module_global_ports_from_child_modules(module_manager, mem_module); } @@ -597,38 +684,46 @@ void build_memory_chain_module(ModuleManager& module_manager, * | Multiplexer Configuration port | * ********************************************************************/ -static -void build_frame_memory_module(ModuleManager& module_manager, - DecoderLibrary& frame_decoder_lib, - const CircuitLibrary& circuit_lib, - const std::string& module_name, - const CircuitModelId& sram_model, - const size_t& num_mems) { - +static void build_frame_memory_module(ModuleManager& module_manager, + DecoderLibrary& frame_decoder_lib, + const CircuitLibrary& circuit_lib, + const std::string& module_name, + const CircuitModelId& sram_model, + const size_t& num_mems) { /* Get the global ports required by the SRAM */ std::vector global_port_types; global_port_types.push_back(CIRCUIT_MODEL_PORT_CLOCK); global_port_types.push_back(CIRCUIT_MODEL_PORT_INPUT); - std::vector sram_global_ports = circuit_lib.model_global_ports_by_type(sram_model, global_port_types, true, false); + std::vector sram_global_ports = + circuit_lib.model_global_ports_by_type(sram_model, global_port_types, true, + false); /* Get the input ports from the SRAM */ - std::vector sram_input_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector sram_input_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true); /* A SRAM cell with BL/WL should not have any input */ - VTR_ASSERT( 0 == sram_input_ports.size() ); + VTR_ASSERT(0 == sram_input_ports.size()); /* Get the output ports from the SRAM */ - std::vector sram_output_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector sram_output_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, + true); - /* Get the BL/WL ports from the SRAM + /* Get the BL/WL ports from the SRAM * Here, we consider that the WL port will be EN signal of a SRAM - * and the BL port will be the data_in signal of a SRAM + * and the BL port will be the data_in signal of a SRAM */ - std::vector sram_bl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BL, true); - std::vector sram_blb_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BLB, true); - std::vector sram_wl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WL, true); - std::vector sram_wlb_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLB, true); + std::vector sram_bl_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BL, true); + std::vector sram_blb_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BLB, true); + std::vector sram_wl_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WL, true); + std::vector sram_wlb_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLB, true); /* We do NOT expect any BLB port here!!! - * TODO: to suppor this, we need an inverter circuit model to be specified by users !!! + * TODO: to suppor this, we need an inverter circuit model to be specified by + * users !!! */ VTR_ASSERT(1 == sram_bl_ports.size()); VTR_ASSERT(1 == circuit_lib.port_size(sram_bl_ports[0])); @@ -637,55 +732,61 @@ void build_frame_memory_module(ModuleManager& module_manager, VTR_ASSERT(0 == sram_blb_ports.size()); /* Create a module and add to the module manager */ - ModuleId mem_module = module_manager.add_module(module_name); + ModuleId mem_module = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); /* Label module usage */ module_manager.set_module_usage(mem_module, ModuleManager::MODULE_CONFIG); /* Find the specification of the decoder: - * Size of address port and data input + * Size of address port and data input */ size_t addr_size = find_mux_local_decoder_addr_size(num_mems); /* Data input should match the WL (data_in) of a SRAM */ - size_t data_size = num_mems * circuit_lib.port_size(sram_bl_ports[0]); - bool use_data_inv = (0 < sram_blb_ports.size()); - + size_t data_size = num_mems * circuit_lib.port_size(sram_bl_ports[0]); + bool use_data_inv = (0 < sram_blb_ports.size()); + /* Search the decoder library * If we find one, we use the module. * Otherwise, we create one and add it to the decoder library */ - DecoderId decoder_id = frame_decoder_lib.find_decoder(addr_size, data_size, true, false, use_data_inv, false); + DecoderId decoder_id = frame_decoder_lib.find_decoder( + addr_size, data_size, true, false, use_data_inv, false); if (DecoderId::INVALID() == decoder_id) { - decoder_id = frame_decoder_lib.add_decoder(addr_size, data_size, true, false, use_data_inv, false); + decoder_id = frame_decoder_lib.add_decoder(addr_size, data_size, true, + false, use_data_inv, false); } VTR_ASSERT(DecoderId::INVALID() != decoder_id); /* Create a module if not existed yet */ - std::string decoder_module_name = generate_memory_decoder_subckt_name(addr_size, data_size); + std::string decoder_module_name = + generate_memory_decoder_subckt_name(addr_size, data_size); ModuleId decoder_module = module_manager.find_module(decoder_module_name); if (ModuleId::INVALID() == decoder_module) { - decoder_module = build_frame_memory_decoder_module(module_manager, - frame_decoder_lib, - decoder_id); + decoder_module = build_frame_memory_decoder_module( + module_manager, frame_decoder_lib, decoder_id); } VTR_ASSERT(ModuleId::INVALID() != decoder_module); - + /* Add module ports */ /* Input: Enable port */ BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); - ModulePortId mem_en_port = module_manager.add_port(mem_module, en_port, ModuleManager::MODULE_INPUT_PORT); + ModulePortId mem_en_port = module_manager.add_port( + mem_module, en_port, ModuleManager::MODULE_INPUT_PORT); /* Input: Address port */ BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), addr_size); - ModulePortId mem_addr_port = module_manager.add_port(mem_module, addr_port, ModuleManager::MODULE_INPUT_PORT); + ModulePortId mem_addr_port = module_manager.add_port( + mem_module, addr_port, ModuleManager::MODULE_INPUT_PORT); /* Input: Data port */ BasicPort data_port(std::string(DECODER_DATA_IN_PORT_NAME), 1); - ModulePortId mem_data_port = module_manager.add_port(mem_module, data_port, ModuleManager::MODULE_INPUT_PORT); + ModulePortId mem_data_port = module_manager.add_port( + mem_module, data_port, ModuleManager::MODULE_INPUT_PORT); /* Should have only 1 or 2 output port */ - VTR_ASSERT( (1 == sram_output_ports.size()) || ( 2 == sram_output_ports.size()) ); + VTR_ASSERT((1 == sram_output_ports.size()) || + (2 == sram_output_ports.size())); /* Add each output port: port width should match the number of memories */ for (size_t iport = 0; iport < sram_output_ports.size(); ++iport) { @@ -693,11 +794,12 @@ void build_frame_memory_module(ModuleManager& module_manager, if (0 == iport) { port_name = generate_configurable_memory_data_out_name(); } else { - VTR_ASSERT( 1 == iport); + VTR_ASSERT(1 == iport); port_name = generate_configurable_memory_inverted_data_out_name(); } BasicPort output_port(port_name, num_mems); - module_manager.add_port(mem_module, output_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(mem_module, output_port, + ModuleManager::MODULE_OUTPUT_PORT); } /* Instanciate the decoder module here */ @@ -705,50 +807,63 @@ void build_frame_memory_module(ModuleManager& module_manager, module_manager.add_child_module(mem_module, decoder_module); /* Find the sram module in the module manager */ - ModuleId sram_mem_module = module_manager.find_module(circuit_lib.model_name(sram_model)); + ModuleId sram_mem_module = + module_manager.find_module(circuit_lib.model_name(sram_model)); /* Build module nets */ /* Wire enable port to decoder enable port */ - ModulePortId decoder_en_port = module_manager.find_module_port(decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); - add_module_bus_nets(module_manager, mem_module, - mem_module, 0, mem_en_port, + ModulePortId decoder_en_port = module_manager.find_module_port( + decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); + add_module_bus_nets(module_manager, mem_module, mem_module, 0, mem_en_port, decoder_module, 0, decoder_en_port); /* Wire address port to decoder address port */ - ModulePortId decoder_addr_port = module_manager.find_module_port(decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); - add_module_bus_nets(module_manager, mem_module, - mem_module, 0, mem_addr_port, + ModulePortId decoder_addr_port = module_manager.find_module_port( + decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); + add_module_bus_nets(module_manager, mem_module, mem_module, 0, mem_addr_port, decoder_module, 0, decoder_addr_port); /* Instanciate each submodule */ for (size_t i = 0; i < num_mems; ++i) { /* Memory seed module instanciation */ - size_t sram_instance = module_manager.num_instance(mem_module, sram_mem_module); + size_t sram_instance = + module_manager.num_instance(mem_module, sram_mem_module); module_manager.add_child_module(mem_module, sram_mem_module); - module_manager.add_configurable_child(mem_module, sram_mem_module, sram_instance); + module_manager.add_configurable_child(mem_module, sram_mem_module, + sram_instance); /* Wire data_in port to SRAM BL port */ - ModulePortId sram_bl_port = module_manager.find_module_port(sram_mem_module, circuit_lib.port_prefix(sram_bl_ports[0])); - add_module_bus_nets(module_manager, mem_module, - mem_module, 0, mem_data_port, - sram_mem_module, sram_instance, sram_bl_port); + ModulePortId sram_bl_port = module_manager.find_module_port( + sram_mem_module, circuit_lib.port_prefix(sram_bl_ports[0])); + add_module_bus_nets(module_manager, mem_module, mem_module, 0, + mem_data_port, sram_mem_module, sram_instance, + sram_bl_port); /* Wire decoder data_out port to sram WL ports */ - ModulePortId sram_wl_port = module_manager.find_module_port(sram_mem_module, circuit_lib.port_prefix(sram_wl_ports[0])); - ModulePortId decoder_data_port = module_manager.find_module_port(decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + ModulePortId sram_wl_port = module_manager.find_module_port( + sram_mem_module, circuit_lib.port_prefix(sram_wl_ports[0])); + ModulePortId decoder_data_port = module_manager.find_module_port( + decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); ModuleNetId wl_net = module_manager.create_module_net(mem_module); /* Source node of the input net is the input of memory module */ - module_manager.add_module_net_source(mem_module, wl_net, decoder_module, 0, decoder_data_port, sram_instance); - module_manager.add_module_net_sink(mem_module, wl_net, sram_mem_module, sram_instance, sram_wl_port, 0); + module_manager.add_module_net_source(mem_module, wl_net, decoder_module, 0, + decoder_data_port, sram_instance); + module_manager.add_module_net_sink(mem_module, wl_net, sram_mem_module, + sram_instance, sram_wl_port, 0); /* Optional: Wire decoder data_out inverted port to sram WLB ports */ if (true == use_data_inv) { - ModulePortId sram_wlb_port = module_manager.find_module_port(sram_mem_module, circuit_lib.port_lib_name(sram_wlb_ports[0])); - ModulePortId decoder_data_inv_port = module_manager.find_module_port(decoder_module, std::string(DECODER_DATA_OUT_INV_PORT_NAME)); + ModulePortId sram_wlb_port = module_manager.find_module_port( + sram_mem_module, circuit_lib.port_lib_name(sram_wlb_ports[0])); + ModulePortId decoder_data_inv_port = module_manager.find_module_port( + decoder_module, std::string(DECODER_DATA_OUT_INV_PORT_NAME)); ModuleNetId wlb_net = module_manager.create_module_net(mem_module); /* Source node of the input net is the input of memory module */ - module_manager.add_module_net_source(mem_module, wlb_net, decoder_module, 0, decoder_data_inv_port, sram_instance); - module_manager.add_module_net_sink(mem_module, wlb_net, sram_mem_module, sram_instance, sram_wlb_port, 0); + module_manager.add_module_net_source(mem_module, wlb_net, decoder_module, + 0, decoder_data_inv_port, + sram_instance); + module_manager.add_module_net_sink(mem_module, wlb_net, sram_mem_module, + sram_instance, sram_wlb_port, 0); } /* Wire inputs of parent module to outputs of child modules */ @@ -757,19 +872,20 @@ void build_frame_memory_module(ModuleManager& module_manager, if (0 == iport) { port_name = generate_configurable_memory_data_out_name(); } else { - VTR_ASSERT( 1 == iport); + VTR_ASSERT(1 == iport); port_name = generate_configurable_memory_inverted_data_out_name(); } - add_module_output_nets_to_chain_mem_modules(module_manager, mem_module, - port_name, circuit_lib, sram_output_ports[iport], - sram_mem_module, i, sram_instance); + add_module_output_nets_to_chain_mem_modules( + module_manager, mem_module, port_name, circuit_lib, + sram_output_ports[iport], sram_mem_module, i, sram_instance); } } /* Add global ports to the pb_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 a list of it + * 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 + * a list of it */ add_module_global_ports_from_child_modules(module_manager, mem_module); @@ -779,113 +895,115 @@ void build_frame_memory_module(ModuleManager& module_manager, /********************************************************************* * Generate Verilog modules for the memories that are used - * by a circuit model + * by a circuit model * The organization of memory circuit will depend on the style of * configuration protocols - * Currently, we support + * Currently, we support * 1. Flat SRAM organization * 2. Configuration chain * 3. Memory bank (memory decoders) ********************************************************************/ -static -void build_memory_module(ModuleManager& module_manager, - DecoderLibrary& arch_decoder_lib, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type, - const std::string& module_name, - const CircuitModelId& sram_model, - const size_t& num_mems) { +static void build_memory_module(ModuleManager& module_manager, + DecoderLibrary& arch_decoder_lib, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const std::string& module_name, + const CircuitModelId& sram_model, + const size_t& num_mems) { switch (sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: - build_memory_flatten_module(module_manager, circuit_lib, + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: + build_memory_flatten_module(module_manager, circuit_lib, module_name, + sram_model, num_mems); + break; + case CONFIG_MEM_SCAN_CHAIN: + build_memory_chain_module(module_manager, circuit_lib, module_name, + sram_model, num_mems); + break; + case CONFIG_MEM_FRAME_BASED: + build_frame_memory_module(module_manager, arch_decoder_lib, circuit_lib, module_name, sram_model, num_mems); - break; - case CONFIG_MEM_SCAN_CHAIN: - build_memory_chain_module(module_manager, circuit_lib, - module_name, sram_model, num_mems); - break; - case CONFIG_MEM_FRAME_BASED: - build_frame_memory_module(module_manager, arch_decoder_lib, circuit_lib, - module_name, sram_model, num_mems); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid configurable memory organization!\n"); - exit(1); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid configurable memory organization!\n"); + exit(1); } } - /********************************************************************* * Generate Verilog modules for the memories that are used - * by multiplexers + * by multiplexers * * +----------------+ * mem_in --->| Memory Module |---> mem_out * +----------------+ - * | | ... | | + * | | ... | | * v v v v SRAM ports of multiplexer * +---------------------+ * in--->| Multiplexer Module |---> out * +---------------------+ ********************************************************************/ -static -void build_mux_memory_module(ModuleManager& module_manager, - DecoderLibrary& arch_decoder_lib, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& mux_model, - const MuxGraph& mux_graph) { - /* Find the actual number of configuration bits, based on the mux graph - * Due to the use of local decoders inside mux, this may be +static void build_mux_memory_module( + ModuleManager& module_manager, DecoderLibrary& arch_decoder_lib, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, const CircuitModelId& mux_model, + const MuxGraph& mux_graph) { + /* Find the actual number of configuration bits, based on the mux graph + * Due to the use of local decoders inside mux, this may be + */ + size_t num_config_bits = + find_mux_num_config_bits(circuit_lib, mux_model, mux_graph, sram_orgz_type); + /* Multiplexers built with different technology is in different organization */ - size_t num_config_bits = find_mux_num_config_bits(circuit_lib, mux_model, mux_graph, sram_orgz_type); - /* Multiplexers built with different technology is in different organization */ switch (circuit_lib.design_tech_type(mux_model)) { - case CIRCUIT_MODEL_DESIGN_CMOS: { - /* Generate module name */ - std::string module_name = generate_mux_subckt_name(circuit_lib, mux_model, - find_mux_num_datapath_inputs(circuit_lib, mux_model, mux_graph.num_inputs()), - std::string(MEMORY_MODULE_POSTFIX)); + case CIRCUIT_MODEL_DESIGN_CMOS: { + /* Generate module name */ + std::string module_name = generate_mux_subckt_name( + circuit_lib, mux_model, + find_mux_num_datapath_inputs(circuit_lib, mux_model, + mux_graph.num_inputs()), + std::string(MEMORY_MODULE_POSTFIX)); - /* Get the sram ports from the mux */ - std::vector sram_models = find_circuit_sram_models(circuit_lib, mux_model); - VTR_ASSERT( 1 == sram_models.size() ); + /* Get the sram ports from the mux */ + std::vector sram_models = + find_circuit_sram_models(circuit_lib, mux_model); + VTR_ASSERT(1 == sram_models.size()); - build_memory_module(module_manager, arch_decoder_lib, - circuit_lib, sram_orgz_type, module_name, sram_models[0], num_config_bits); - break; - } - case CIRCUIT_MODEL_DESIGN_RRAM: - /* We do not need a memory submodule for RRAM MUX, - * RRAM are embedded in the datapath - * TODO: generate local encoders for RRAM-based multiplexers here!!! - */ - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid design technology of multiplexer '%s'\n", - circuit_lib.model_name(mux_model).c_str()); - exit(1); + build_memory_module(module_manager, arch_decoder_lib, circuit_lib, + sram_orgz_type, module_name, sram_models[0], + num_config_bits); + break; + } + case CIRCUIT_MODEL_DESIGN_RRAM: + /* We do not need a memory submodule for RRAM MUX, + * RRAM are embedded in the datapath + * TODO: generate local encoders for RRAM-based multiplexers here!!! + */ + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid design technology of multiplexer '%s'\n", + circuit_lib.model_name(mux_model).c_str()); + exit(1); } } /********************************************************************* - * Build modules for + * Build modules for * the memories that are affiliated to multiplexers and other programmable * circuit models, such as IOPADs, LUTs, etc. * - * We keep the memory modules separated from the multiplexers and other + * We keep the memory modules separated from the multiplexers and other * programmable circuit models, for the sake of supporting * various configuration schemes. * By following such organiztion, the Verilog modules of the circuit models * implements the functionality (circuit logic) only, while the memory Verilog * modules implements the memory circuits as well as configuration protocols. * For example, the local decoders of multiplexers are implemented in the - * memory modules. - * Take another example, the memory circuit can implement the scan-chain or + * memory modules. + * Take another example, the memory circuit can implement the scan-chain or * memory-bank organization for the memories. ********************************************************************/ void build_memory_modules(ModuleManager& module_manager, @@ -894,26 +1012,26 @@ void build_memory_modules(ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type) { vtr::ScopedStartFinishTimer timer("Build memory modules"); - + /* Create the memory circuits for the multiplexer */ for (auto mux : mux_lib.muxes()) { const MuxGraph& mux_graph = mux_lib.mux_graph(mux); - CircuitModelId mux_model = mux_lib.mux_circuit_model(mux); - /* Bypass the non-MUX circuit models (i.e., LUTs). - * They should be handled in a different way + CircuitModelId mux_model = mux_lib.mux_circuit_model(mux); + /* Bypass the non-MUX circuit models (i.e., LUTs). + * They should be handled in a different way * Memory circuits of LUT includes both regular and mode-select ports */ if (CIRCUIT_MODEL_MUX != circuit_lib.model_type(mux_model)) { continue; } /* Create a Verilog module for the memories used by the multiplexer */ - build_mux_memory_module(module_manager, arch_decoder_lib, - circuit_lib, sram_orgz_type, mux_model, mux_graph); + build_mux_memory_module(module_manager, arch_decoder_lib, circuit_lib, + sram_orgz_type, mux_model, mux_graph); } /* Create the memory circuits for non-MUX circuit models. * In this case, the memory modules are designed to interface - * the mode-select ports + * the mode-select ports */ for (const auto& model : circuit_lib.models()) { /* Bypass MUXes, they have already been considered */ @@ -921,27 +1039,30 @@ void build_memory_modules(ModuleManager& module_manager, continue; } /* Bypass those modules without any SRAM ports */ - std::vector sram_ports = circuit_lib.model_ports_by_type(model, CIRCUIT_MODEL_PORT_SRAM, true); + std::vector sram_ports = + circuit_lib.model_ports_by_type(model, CIRCUIT_MODEL_PORT_SRAM, true); if (0 == sram_ports.size()) { continue; } /* Find the name of memory module */ /* Get the total number of SRAMs */ - size_t num_mems = 0; + size_t num_mems = 0; for (const auto& port : sram_ports) { num_mems += circuit_lib.port_size(port); } /* Get the circuit model for the memory circuit used by the multiplexer */ - std::vector sram_models = find_circuit_sram_models(circuit_lib, model); + std::vector sram_models = + find_circuit_sram_models(circuit_lib, model); /* Should have only 1 SRAM model */ - VTR_ASSERT( 1 == sram_models.size() ); - + VTR_ASSERT(1 == sram_models.size()); + /* Create the module name for the memory block */ - std::string module_name = generate_memory_module_name(circuit_lib, model, sram_models[0], std::string(MEMORY_MODULE_POSTFIX)); + std::string module_name = generate_memory_module_name( + circuit_lib, model, sram_models[0], std::string(MEMORY_MODULE_POSTFIX)); /* Create a Verilog module for the memories used by the circuit model */ - build_memory_module(module_manager, arch_decoder_lib, - circuit_lib, sram_orgz_type, module_name, sram_models[0], num_mems); + build_memory_module(module_manager, arch_decoder_lib, circuit_lib, + sram_orgz_type, module_name, sram_models[0], num_mems); } } diff --git a/openfpga/src/fabric/build_memory_modules.h b/openfpga/src/fabric/build_memory_modules.h index 921b9fbd2..5eeaf25e8 100644 --- a/openfpga/src/fabric/build_memory_modules.h +++ b/openfpga/src/fabric/build_memory_modules.h @@ -4,10 +4,10 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "decoder_library.h" #include "circuit_library.h" -#include "mux_library.h" +#include "decoder_library.h" #include "module_manager.h" +#include "mux_library.h" /******************************************************************** * Function declaration @@ -16,14 +16,11 @@ /* begin namespace openfpga */ namespace openfpga { -std::vector add_module_output_nets_to_chain_mem_modules(ModuleManager& module_manager, - const ModuleId& mem_module, - const std::string& mem_module_output_name, - const CircuitLibrary& circuit_lib, - const CircuitPortId& circuit_port, - const ModuleId& child_module, - const size_t& child_index, - const size_t& child_instance); +std::vector add_module_output_nets_to_chain_mem_modules( + ModuleManager& module_manager, const ModuleId& mem_module, + const std::string& mem_module_output_name, const CircuitLibrary& circuit_lib, + const CircuitPortId& circuit_port, const ModuleId& child_module, + const size_t& child_index, const size_t& child_instance); void build_memory_modules(ModuleManager& module_manager, DecoderLibrary& arch_decoder_lib, diff --git a/openfpga/src/fabric/build_module_graph_utils.cpp b/openfpga/src/fabric/build_module_graph_utils.cpp index 617a156a6..aeba3d802 100644 --- a/openfpga/src/fabric/build_module_graph_utils.cpp +++ b/openfpga/src/fabric/build_module_graph_utils.cpp @@ -5,59 +5,61 @@ #include /* Headers from vtrutil library */ +#include "build_module_graph_utils.h" +#include "openfpga_naming.h" #include "vtr_assert.h" -#include "openfpga_naming.h" -#include "build_module_graph_utils.h" - /* begin namespace openfpga */ namespace openfpga { /******************************************************************** * Find input port of a buffer/inverter module ********************************************************************/ -ModulePortId find_inverter_buffer_module_port(const ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& model_id, - const e_circuit_model_port_type& port_type) { +ModulePortId find_inverter_buffer_module_port( + const ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& model_id, + const e_circuit_model_port_type& port_type) { /* We must have a valid module id */ VTR_ASSERT(true == module_manager.valid_module_id(module_id)); - /* Check the type of model */ + /* Check the type of model */ VTR_ASSERT(CIRCUIT_MODEL_INVBUF == circuit_lib.model_type(model_id)); /* Add module nets to wire to the buffer module */ - /* To match the context, Buffer should have only 2 non-global ports: 1 input port and 1 output port */ - std::vector model_ports = circuit_lib.model_ports_by_type(model_id, port_type, true); + /* To match the context, Buffer should have only 2 non-global ports: 1 input + * port and 1 output port */ + std::vector model_ports = + circuit_lib.model_ports_by_type(model_id, port_type, true); VTR_ASSERT(1 == model_ports.size()); /* Find the input and output module ports */ - ModulePortId module_port_id = module_manager.find_module_port(module_id, circuit_lib.port_prefix(model_ports[0])); - VTR_ASSERT(true == module_manager.valid_module_port_id(module_id, module_port_id)); + ModulePortId module_port_id = module_manager.find_module_port( + module_id, circuit_lib.port_prefix(model_ports[0])); + VTR_ASSERT(true == + module_manager.valid_module_port_id(module_id, module_port_id)); - return module_port_id; + return module_port_id; } /******************************************************************** * Add inverter/buffer module to a parent module * and complete the wiring to the input port of inverter/buffer - * This function will return the wire created for the output port of inverter/buffer + * This function will return the wire created for the output port of + *inverter/buffer * * parent_module * +----------------------------------------------------------------- - * | + * | * | input_net output_net * | | | * | v +---------------+ v - * | src_module_port --------->| child_module |--------> + * | src_module_port --------->| child_module |--------> * | +---------------+ * ********************************************************************/ -ModuleNetId add_inverter_buffer_child_module_and_nets(ModuleManager& module_manager, - const ModuleId& parent_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& model_id, - const ModuleNetId& input_net) { +ModuleNetId add_inverter_buffer_child_module_and_nets( + ModuleManager& module_manager, const ModuleId& parent_module, + const CircuitLibrary& circuit_lib, const CircuitModelId& model_id, + const ModuleNetId& input_net) { /* We must have a valid module id */ VTR_ASSERT(true == module_manager.valid_module_id(parent_module)); @@ -65,23 +67,35 @@ ModuleNetId add_inverter_buffer_child_module_and_nets(ModuleManager& module_mana ModuleId child_module = module_manager.find_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(child_module)); - ModulePortId module_input_port_id = find_inverter_buffer_module_port(module_manager, child_module, circuit_lib, model_id, CIRCUIT_MODEL_PORT_INPUT); - ModulePortId module_output_port_id = find_inverter_buffer_module_port(module_manager, child_module, circuit_lib, model_id, CIRCUIT_MODEL_PORT_OUTPUT); + ModulePortId module_input_port_id = + find_inverter_buffer_module_port(module_manager, child_module, circuit_lib, + model_id, CIRCUIT_MODEL_PORT_INPUT); + ModulePortId module_output_port_id = + find_inverter_buffer_module_port(module_manager, child_module, circuit_lib, + model_id, CIRCUIT_MODEL_PORT_OUTPUT); /* Port size should be 1 ! */ - VTR_ASSERT(1 == module_manager.module_port(child_module, module_input_port_id).get_width()); - VTR_ASSERT(1 == module_manager.module_port(child_module, module_output_port_id).get_width()); + VTR_ASSERT( + 1 == + module_manager.module_port(child_module, module_input_port_id).get_width()); + VTR_ASSERT(1 == + module_manager.module_port(child_module, module_output_port_id) + .get_width()); /* Instanciate a child module */ - size_t child_instance = module_manager.num_instance(parent_module, child_module); + size_t child_instance = + module_manager.num_instance(parent_module, child_module); module_manager.add_child_module(parent_module, child_module); /* Use the net to connect to the input net of buffer */ - module_manager.add_module_net_sink(parent_module, input_net, child_module, child_instance, module_input_port_id, 0); + module_manager.add_module_net_sink(parent_module, input_net, child_module, + child_instance, module_input_port_id, 0); - /* Create a net to bridge the input inverter and LUT MUX */ + /* Create a net to bridge the input inverter and LUT MUX */ ModuleNetId output_net = module_manager.create_module_net(parent_module); - module_manager.add_module_net_source(parent_module, output_net, child_module, child_instance, module_output_port_id, 0); + module_manager.add_module_net_source(parent_module, output_net, child_module, + child_instance, module_output_port_id, + 0); return output_net; } diff --git a/openfpga/src/fabric/build_module_graph_utils.h b/openfpga/src/fabric/build_module_graph_utils.h index dee44140a..794773ba2 100644 --- a/openfpga/src/fabric/build_module_graph_utils.h +++ b/openfpga/src/fabric/build_module_graph_utils.h @@ -6,13 +6,12 @@ *******************************************************************/ #include #include -#include "vtr_geometry.h" -#include "circuit_library.h" -#include "openfpga_side_manager.h" - -#include "vpr_types.h" -#include "module_manager.h" +#include "circuit_library.h" +#include "module_manager.h" +#include "openfpga_side_manager.h" +#include "vpr_types.h" +#include "vtr_geometry.h" /******************************************************************** * Function declaration @@ -21,17 +20,15 @@ /* begin namespace openfpga */ namespace openfpga { -ModulePortId find_inverter_buffer_module_port(const ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& model_id, - const e_circuit_model_port_type& port_type); +ModulePortId find_inverter_buffer_module_port( + const ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& model_id, + const e_circuit_model_port_type& port_type); -ModuleNetId add_inverter_buffer_child_module_and_nets(ModuleManager& module_manager, - const ModuleId& parent_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& model_id, - const ModuleNetId& input_net); +ModuleNetId add_inverter_buffer_child_module_and_nets( + ModuleManager& module_manager, const ModuleId& parent_module, + const CircuitLibrary& circuit_lib, const CircuitModelId& model_id, + const ModuleNetId& input_net); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_mux_modules.cpp b/openfpga/src/fabric/build_mux_modules.cpp index 2dbee6698..3233db768 100644 --- a/openfpga/src/fabric/build_mux_modules.cpp +++ b/openfpga/src/fabric/build_mux_modules.cpp @@ -2,36 +2,34 @@ * This file includes functions to generate * Verilog submodules for multiplexers. * including both fundamental submodules - * such as a branch in a multiplexer + * such as a branch in a multiplexer * and the full multiplexer **********************************************/ -#include #include +#include /* Headers from vtrutil library */ -#include "vtr_log.h" -#include "vtr_assert.h" -#include "vtr_time.h" - -#include "mux_graph.h" -#include "module_manager.h" -#include "mux_utils.h" +#include "build_module_graph_utils.h" +#include "build_mux_modules.h" #include "circuit_library_utils.h" #include "decoder_library_utils.h" +#include "module_manager.h" #include "module_manager_utils.h" -#include "build_module_graph_utils.h" -#include "openfpga_reserved_words.h" +#include "mux_graph.h" +#include "mux_utils.h" #include "openfpga_naming.h" - -#include "build_mux_modules.h" +#include "openfpga_reserved_words.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" /* begin namespace openfpga */ namespace openfpga { /********************************************************************* * Generate structural Verilog codes (consist of transmission-gates or - * pass-transistor) modeling an branch circuit - * for a multiplexer with the given size + * pass-transistor) modeling an branch circuit + * for a multiplexer with the given size * * +----------+ * input[0] --->| tgate[0] |-+ @@ -47,66 +45,82 @@ namespace openfpga { * input[i] --->| tgate[i] |-+ * +----------+ *********************************************************************/ -static -void build_cmos_mux_branch_body(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const CircuitModelId& tgate_model, - const ModuleId& mux_module, - const ModulePortId& module_input_port, - const ModulePortId& module_output_port, - const ModulePortId& module_mem_port, - const ModulePortId& module_mem_inv_port, - const MuxGraph& mux_graph) { +static void build_cmos_mux_branch_body( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const CircuitModelId& tgate_model, const ModuleId& mux_module, + const ModulePortId& module_input_port, const ModulePortId& module_output_port, + const ModulePortId& module_mem_port, const ModulePortId& module_mem_inv_port, + const MuxGraph& mux_graph) { /* Get the module id of tgate in Module manager */ - ModuleId tgate_module_id = module_manager.find_module(circuit_lib.model_name(tgate_model)); + ModuleId tgate_module_id = + module_manager.find_module(circuit_lib.model_name(tgate_model)); VTR_ASSERT(ModuleId::INVALID() != tgate_module_id); /* Get model ports of tgate */ - std::vector tgate_input_ports = circuit_lib.model_ports_by_type(tgate_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector tgate_output_ports = circuit_lib.model_ports_by_type(tgate_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector tgate_input_ports = + circuit_lib.model_ports_by_type(tgate_model, CIRCUIT_MODEL_PORT_INPUT, + true); + std::vector tgate_output_ports = + circuit_lib.model_ports_by_type(tgate_model, CIRCUIT_MODEL_PORT_OUTPUT, + true); VTR_ASSERT(3 == tgate_input_ports.size()); VTR_ASSERT(1 == tgate_output_ports.size()); /* Find the module ports of tgate module */ /* Input port is the data path input of the tgate, whose size must be 1 ! */ - ModulePortId tgate_module_input = module_manager.find_module_port(tgate_module_id, circuit_lib.port_prefix(tgate_input_ports[0])); - VTR_ASSERT(true == module_manager.valid_module_port_id(tgate_module_id, tgate_module_input)); - BasicPort tgate_module_input_port = module_manager.module_port(tgate_module_id, tgate_module_input); + ModulePortId tgate_module_input = module_manager.find_module_port( + tgate_module_id, circuit_lib.port_prefix(tgate_input_ports[0])); + VTR_ASSERT(true == module_manager.valid_module_port_id(tgate_module_id, + tgate_module_input)); + BasicPort tgate_module_input_port = + module_manager.module_port(tgate_module_id, tgate_module_input); VTR_ASSERT(1 == tgate_module_input_port.get_width()); /* Mem port is the memory of the tgate, whose size must be 1 ! */ - ModulePortId tgate_module_mem = module_manager.find_module_port(tgate_module_id, circuit_lib.port_prefix(tgate_input_ports[1])); - VTR_ASSERT(true == module_manager.valid_module_port_id(tgate_module_id, tgate_module_mem)); - BasicPort tgate_module_mem_port = module_manager.module_port(tgate_module_id, tgate_module_mem); + ModulePortId tgate_module_mem = module_manager.find_module_port( + tgate_module_id, circuit_lib.port_prefix(tgate_input_ports[1])); + VTR_ASSERT(true == module_manager.valid_module_port_id(tgate_module_id, + tgate_module_mem)); + BasicPort tgate_module_mem_port = + module_manager.module_port(tgate_module_id, tgate_module_mem); VTR_ASSERT(1 == tgate_module_mem_port.get_width()); /* Mem inv port is the inverted memory of the tgate, whose size must be 1 ! */ - ModulePortId tgate_module_mem_inv = module_manager.find_module_port(tgate_module_id, circuit_lib.port_prefix(tgate_input_ports[2])); - VTR_ASSERT(true == module_manager.valid_module_port_id(tgate_module_id, tgate_module_mem_inv)); - BasicPort tgate_module_mem_inv_port = module_manager.module_port(tgate_module_id, tgate_module_mem_inv); + ModulePortId tgate_module_mem_inv = module_manager.find_module_port( + tgate_module_id, circuit_lib.port_prefix(tgate_input_ports[2])); + VTR_ASSERT(true == module_manager.valid_module_port_id(tgate_module_id, + tgate_module_mem_inv)); + BasicPort tgate_module_mem_inv_port = + module_manager.module_port(tgate_module_id, tgate_module_mem_inv); VTR_ASSERT(1 == tgate_module_mem_inv_port.get_width()); /* Output port is the data path output of the tgate, whose size must be 1 ! */ - ModulePortId tgate_module_output = module_manager.find_module_port(tgate_module_id, circuit_lib.port_prefix(tgate_output_ports[0])); - VTR_ASSERT(true == module_manager.valid_module_port_id(tgate_module_id, tgate_module_output)); - BasicPort tgate_module_output_port = module_manager.module_port(tgate_module_id, tgate_module_output); + ModulePortId tgate_module_output = module_manager.find_module_port( + tgate_module_id, circuit_lib.port_prefix(tgate_output_ports[0])); + VTR_ASSERT(true == module_manager.valid_module_port_id(tgate_module_id, + tgate_module_output)); + BasicPort tgate_module_output_port = + module_manager.module_port(tgate_module_id, tgate_module_output); VTR_ASSERT(1 == tgate_module_output_port.get_width()); /* Ensure that input port size does match mux inputs */ - BasicPort input_port = module_manager.module_port(mux_module, module_input_port); + BasicPort input_port = + module_manager.module_port(mux_module, module_input_port); VTR_ASSERT(input_port.get_width() == mux_graph.num_inputs()); - + /* Add module nets for each mux inputs */ std::vector mux_input_nets; for (const size_t& pin : input_port.pins()) { ModuleNetId input_net = module_manager.create_module_net(mux_module); mux_input_nets.push_back(input_net); /* Configure the source for each net */ - module_manager.add_module_net_source(mux_module, input_net, mux_module, 0, module_input_port, pin); + module_manager.add_module_net_source(mux_module, input_net, mux_module, 0, + module_input_port, pin); } /* Ensure that output port size does match mux outputs */ - BasicPort output_port = module_manager.module_port(mux_module, module_output_port); + BasicPort output_port = + module_manager.module_port(mux_module, module_output_port); VTR_ASSERT(output_port.get_width() == mux_graph.num_outputs()); /* Add module nets for each mux outputs */ @@ -115,11 +129,12 @@ void build_cmos_mux_branch_body(ModuleManager& module_manager, ModuleNetId output_net = module_manager.create_module_net(mux_module); mux_output_nets.push_back(output_net); /* Configure the sink for each net */ - module_manager.add_module_net_sink(mux_module, output_net, mux_module, 0, module_output_port, pin); + module_manager.add_module_net_sink(mux_module, output_net, mux_module, 0, + module_output_port, pin); } /* Ensure that mem port size does match mux outputs */ - BasicPort mem_port = module_manager.module_port(mux_module, module_mem_port); + BasicPort mem_port = module_manager.module_port(mux_module, module_mem_port); VTR_ASSERT(mem_port.get_width() == mux_graph.num_memory_bits()); /* Add module nets for each mem inputs */ @@ -128,11 +143,13 @@ void build_cmos_mux_branch_body(ModuleManager& module_manager, ModuleNetId mem_net = module_manager.create_module_net(mux_module); mux_mem_nets.push_back(mem_net); /* Configure the source for each net */ - module_manager.add_module_net_source(mux_module, mem_net, mux_module, 0, module_mem_port, pin); + module_manager.add_module_net_source(mux_module, mem_net, mux_module, 0, + module_mem_port, pin); } /* Ensure that mem_inv port size does match mux outputs */ - BasicPort mem_inv_port = module_manager.module_port(mux_module, module_mem_inv_port); + BasicPort mem_inv_port = + module_manager.module_port(mux_module, module_mem_inv_port); VTR_ASSERT(mem_inv_port.get_width() == mux_graph.num_memory_bits()); /* Add module nets for each mem inverted inputs */ @@ -141,7 +158,8 @@ void build_cmos_mux_branch_body(ModuleManager& module_manager, ModuleNetId mem_net = module_manager.create_module_net(mux_module); mux_mem_inv_nets.push_back(mem_net); /* Configure the source for each net */ - module_manager.add_module_net_source(mux_module, mem_net, mux_module, 0, module_mem_inv_port, pin); + module_manager.add_module_net_source(mux_module, mem_net, mux_module, 0, + module_mem_inv_port, pin); } /* Build a module following the connections in mux_graph */ @@ -150,14 +168,20 @@ void build_cmos_mux_branch_body(ModuleManager& module_manager, /* Iterate over the outputs */ for (const auto& mux_output : mux_graph.outputs()) { /* Add the a tgate to bridge the mux input and output */ - size_t tgate_instance = module_manager.num_instance(mux_module, tgate_module_id); + size_t tgate_instance = + module_manager.num_instance(mux_module, tgate_module_id); module_manager.add_child_module(mux_module, tgate_module_id); /* Add module nets to connect the mux input and tgate input */ - module_manager.add_module_net_sink(mux_module, mux_input_nets[size_t(mux_graph.input_id(mux_input))], tgate_module_id, tgate_instance, tgate_module_input, tgate_module_input_port.get_lsb()); + module_manager.add_module_net_sink( + mux_module, mux_input_nets[size_t(mux_graph.input_id(mux_input))], + tgate_module_id, tgate_instance, tgate_module_input, + tgate_module_input_port.get_lsb()); - /* if there is a connection between the input and output, a tgate will be outputted */ - std::vector edges = mux_graph.find_edges(mux_input, mux_output); + /* if there is a connection between the input and output, a tgate will be + * outputted */ + std::vector edges = + mux_graph.find_edges(mux_input, mux_output); /* There should be only one edge or no edge*/ VTR_ASSERT((1 == edges.size()) || (0 == edges.size())); /* No need to output tgates if there are no edges between two nodes */ @@ -166,51 +190,66 @@ void build_cmos_mux_branch_body(ModuleManager& module_manager, } /* Add module nets to connect the mux output and tgate output */ - module_manager.add_module_net_source(mux_module, mux_output_nets[size_t(mux_graph.output_id(mux_output))], tgate_module_id, tgate_instance, tgate_module_output, tgate_module_output_port.get_lsb()); + module_manager.add_module_net_source( + mux_module, mux_output_nets[size_t(mux_graph.output_id(mux_output))], + tgate_module_id, tgate_instance, tgate_module_output, + tgate_module_output_port.get_lsb()); MuxMemId mux_mem = mux_graph.find_edge_mem(edges[0]); /* Add module nets to connect the mem input and tgate mem input */ if (false == mux_graph.is_edge_use_inv_mem(edges[0])) { /* wire mem to mem of module, and wire mem_inv to mem_inv of module */ - module_manager.add_module_net_sink(mux_module, mux_mem_nets[size_t(mux_mem)], tgate_module_id, tgate_instance, tgate_module_mem, tgate_module_mem_port.get_lsb()); - module_manager.add_module_net_sink(mux_module, mux_mem_inv_nets[size_t(mux_mem)], tgate_module_id, tgate_instance, tgate_module_mem_inv, tgate_module_mem_inv_port.get_lsb()); + module_manager.add_module_net_sink( + mux_module, mux_mem_nets[size_t(mux_mem)], tgate_module_id, + tgate_instance, tgate_module_mem, tgate_module_mem_port.get_lsb()); + module_manager.add_module_net_sink( + mux_module, mux_mem_inv_nets[size_t(mux_mem)], tgate_module_id, + tgate_instance, tgate_module_mem_inv, + tgate_module_mem_inv_port.get_lsb()); } else { /* wire mem_inv to mem of module, wire mem to mem_inv of module */ - module_manager.add_module_net_sink(mux_module, mux_mem_inv_nets[size_t(mux_mem)], tgate_module_id, tgate_instance, tgate_module_mem, tgate_module_mem_port.get_lsb()); - module_manager.add_module_net_sink(mux_module, mux_mem_nets[size_t(mux_mem)], tgate_module_id, tgate_instance, tgate_module_mem_inv, tgate_module_mem_inv_port.get_lsb()); - } + module_manager.add_module_net_sink( + mux_module, mux_mem_inv_nets[size_t(mux_mem)], tgate_module_id, + tgate_instance, tgate_module_mem, tgate_module_mem_port.get_lsb()); + module_manager.add_module_net_sink( + mux_module, mux_mem_nets[size_t(mux_mem)], tgate_module_id, + tgate_instance, tgate_module_mem_inv, + tgate_module_mem_inv_port.get_lsb()); + } } } } /********************************************************************* - * Generate Verilog codes modeling an branch circuit - * for a CMOS multiplexer with the given size + * Generate Verilog codes modeling an branch circuit + * for a CMOS multiplexer with the given size * Support structural and behavioral Verilog codes *********************************************************************/ -static -void build_cmos_mux_branch_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const std::string& module_name, - const MuxGraph& mux_graph) { +static void build_cmos_mux_branch_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const CircuitModelId& mux_model, + const std::string& module_name, + const MuxGraph& mux_graph) { /* Get the tgate model */ CircuitModelId tgate_model = circuit_lib.pass_gate_logic_model(mux_model); - /* Skip output if the tgate model is a MUX2, it is handled by essential-gate generator */ + /* Skip output if the tgate model is a MUX2, it is handled by essential-gate + * generator */ if (CIRCUIT_MODEL_GATE == circuit_lib.model_type(tgate_model)) { VTR_ASSERT(CIRCUIT_MODEL_GATE_MUX2 == circuit_lib.gate_type(tgate_model)); return; } - std::vector tgate_global_ports = circuit_lib.model_global_ports_by_type(tgate_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector tgate_global_ports = + circuit_lib.model_global_ports_by_type( + tgate_model, CIRCUIT_MODEL_PORT_INPUT, true, true); /* Generate the Verilog netlist according to the mux_graph */ - /* Find out the number of inputs */ + /* Find out the number of inputs */ size_t num_inputs = mux_graph.num_inputs(); - /* Find out the number of outputs */ + /* Find out the number of outputs */ size_t num_outputs = mux_graph.num_outputs(); - /* Find out the number of memory bits */ + /* Find out the number of memory bits */ size_t num_mems = mux_graph.num_memory_bits(); /* Check codes to ensure the port of Verilog netlists will match */ @@ -219,60 +258,72 @@ void build_cmos_mux_branch_module(ModuleManager& module_manager, /* MUX graph must have only 1 level*/ VTR_ASSERT(1 == mux_graph.num_levels()); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId mux_module = module_manager.add_module(module_name); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId mux_module = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); /* Add module ports */ /* Add each input port */ BasicPort input_port("in", num_inputs); - ModulePortId module_input_port = module_manager.add_port(mux_module, input_port, ModuleManager::MODULE_INPUT_PORT); + ModulePortId module_input_port = module_manager.add_port( + mux_module, input_port, ModuleManager::MODULE_INPUT_PORT); /* Add each output port */ BasicPort output_port("out", num_outputs); - ModulePortId module_output_port = module_manager.add_port(mux_module, output_port, ModuleManager::MODULE_OUTPUT_PORT); + ModulePortId module_output_port = module_manager.add_port( + mux_module, output_port, ModuleManager::MODULE_OUTPUT_PORT); /* Add each memory port */ BasicPort mem_port("mem", num_mems); - ModulePortId module_mem_port = module_manager.add_port(mux_module, mem_port, ModuleManager::MODULE_INPUT_PORT); + ModulePortId module_mem_port = module_manager.add_port( + mux_module, mem_port, ModuleManager::MODULE_INPUT_PORT); BasicPort mem_inv_port("mem_inv", num_mems); - ModulePortId module_mem_inv_port = module_manager.add_port(mux_module, mem_inv_port, ModuleManager::MODULE_INPUT_PORT); + ModulePortId module_mem_inv_port = module_manager.add_port( + mux_module, mem_inv_port, ModuleManager::MODULE_INPUT_PORT); - /* By default we give a structural description, - * Writers can freely write the module in their styles - * For instance, Verilog writer can ignore the internal structure and write in behavioral codes + /* By default we give a structural description, + * Writers can freely write the module in their styles + * For instance, Verilog writer can ignore the internal structure and write in + * behavioral codes */ - build_cmos_mux_branch_body(module_manager, circuit_lib, tgate_model, mux_module, module_input_port, module_output_port, module_mem_port, module_mem_inv_port, mux_graph); + build_cmos_mux_branch_body(module_manager, circuit_lib, tgate_model, + mux_module, module_input_port, module_output_port, + module_mem_port, module_mem_inv_port, mux_graph); /* Add global ports to the mux 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 a list of it + * 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 + * a list of it */ add_module_global_ports_from_child_modules(module_manager, mux_module); } /********************************************************************* - * Generate Verilog codes modeling an branch circuit - * for a RRAM-based multiplexer with the given size + * Generate Verilog codes modeling an branch circuit + * for a RRAM-based multiplexer with the given size * Support structural and behavioral Verilog codes *********************************************************************/ -static -void build_rram_mux_branch_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const std::string& module_name, - const MuxGraph& mux_graph) { +static void build_rram_mux_branch_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const CircuitModelId& mux_model, + const std::string& module_name, + const MuxGraph& mux_graph) { /* Get the input ports from the mux */ - std::vector mux_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector mux_input_ports = + circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); /* Get the output ports from the mux */ - std::vector mux_output_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector mux_output_ports = + circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_OUTPUT, true); /* Get the BL and WL ports from the mux */ - std::vector mux_blb_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_BLB, true); - std::vector mux_wl_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_WL, true); + std::vector mux_blb_ports = + circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_BLB, true); + std::vector mux_wl_ports = + circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_WL, true); /* Generate the Verilog netlist according to the mux_graph */ - /* Find out the number of inputs */ + /* Find out the number of inputs */ size_t num_inputs = mux_graph.num_inputs(); - /* Find out the number of outputs */ + /* Find out the number of outputs */ size_t num_outputs = mux_graph.num_outputs(); - /* Find out the number of memory bits */ + /* Find out the number of memory bits */ size_t num_mems = mux_graph.num_memory_bits(); /* Check codes to ensure the port of Verilog netlists will match */ @@ -286,100 +337,118 @@ void build_rram_mux_branch_module(ModuleManager& module_manager, VTR_ASSERT(1 == mux_blb_ports.size()); VTR_ASSERT(1 == mux_wl_ports.size()); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId mux_module = module_manager.add_module(module_name); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId mux_module = module_manager.add_module(module_name); VTR_ASSERT(ModuleId::INVALID() != mux_module); /* Add module ports */ /* Add each global programming enable/disable ports */ - std::vector prog_enable_ports = circuit_lib.model_global_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector prog_enable_ports = + circuit_lib.model_global_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, + true, true); for (const auto& port : prog_enable_ports) { /* Configure each global port */ - BasicPort global_port(circuit_lib.port_prefix(port), circuit_lib.port_size(port)); - module_manager.add_port(mux_module, global_port, ModuleManager::MODULE_GLOBAL_PORT); + BasicPort global_port(circuit_lib.port_prefix(port), + circuit_lib.port_size(port)); + module_manager.add_port(mux_module, global_port, + ModuleManager::MODULE_GLOBAL_PORT); } /* Add each input port */ BasicPort input_port(circuit_lib.port_prefix(mux_input_ports[0]), num_inputs); - module_manager.add_port(mux_module, input_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(mux_module, input_port, + ModuleManager::MODULE_INPUT_PORT); /* Add each output port */ - BasicPort output_port(circuit_lib.port_prefix(mux_output_ports[0]), num_outputs); - module_manager.add_port(mux_module, output_port, ModuleManager::MODULE_OUTPUT_PORT); + BasicPort output_port(circuit_lib.port_prefix(mux_output_ports[0]), + num_outputs); + module_manager.add_port(mux_module, output_port, + ModuleManager::MODULE_OUTPUT_PORT); - /* Add RRAM programming ports, - * RRAM MUXes require one more pair of BLB and WL + /* Add RRAM programming ports, + * RRAM MUXes require one more pair of BLB and WL * to configure the memories. See schematic for details */ BasicPort blb_port(circuit_lib.port_prefix(mux_blb_ports[0]), num_mems + 1); - module_manager.add_port(mux_module, blb_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(mux_module, blb_port, + ModuleManager::MODULE_INPUT_PORT); BasicPort wl_port(circuit_lib.port_prefix(mux_wl_ports[0]), num_mems + 1); - module_manager.add_port(mux_module, wl_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(mux_module, wl_port, + ModuleManager::MODULE_INPUT_PORT); /* Note: we do not generate the internal structure of the ReRAM-based MUX - * circuit as a module graph! + * circuit as a module graph! * This is mainly due to that the internal structure could be different * in Verilog or SPICE netlists - * Leave the writers to customize this + * Leave the writers to customize this */ } /*********************************************** - * Generate Verilog codes modeling an branch circuit - * for a multiplexer with the given size + * Generate Verilog codes modeling an branch circuit + * for a multiplexer with the given size **********************************************/ -static -void build_mux_branch_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const MuxGraph& mux_graph) { - std::string module_name = generate_mux_branch_subckt_name(circuit_lib, mux_model, mux_graph.num_inputs(), mux_graph.num_memory_bits(), MUX_BASIS_MODULE_POSTFIX); +static void build_mux_branch_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const CircuitModelId& mux_model, + const MuxGraph& mux_graph) { + std::string module_name = generate_mux_branch_subckt_name( + circuit_lib, mux_model, mux_graph.num_inputs(), mux_graph.num_memory_bits(), + MUX_BASIS_MODULE_POSTFIX); /* Skip the module building if it is already there */ if (module_manager.valid_module_id(module_manager.find_module(module_name))) { return; } - /* Multiplexers built with different technology is in different organization */ + /* Multiplexers built with different technology is in different organization + */ switch (circuit_lib.design_tech_type(mux_model)) { - case CIRCUIT_MODEL_DESIGN_CMOS: - build_cmos_mux_branch_module(module_manager, circuit_lib, mux_model, module_name, mux_graph); - break; - case CIRCUIT_MODEL_DESIGN_RRAM: - build_rram_mux_branch_module(module_manager, circuit_lib, mux_model, module_name, mux_graph); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid design technology of multiplexer '%s'\n", - circuit_lib.model_name(mux_model).c_str()); - exit(1); + case CIRCUIT_MODEL_DESIGN_CMOS: + build_cmos_mux_branch_module(module_manager, circuit_lib, mux_model, + module_name, mux_graph); + break; + case CIRCUIT_MODEL_DESIGN_RRAM: + build_rram_mux_branch_module(module_manager, circuit_lib, mux_model, + module_name, mux_graph); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid design technology of multiplexer '%s'\n", + circuit_lib.model_name(mux_model).c_str()); + exit(1); } } /******************************************************************** - * Generate the standard-cell-based internal logic (multiplexing structure) - * for a multiplexer or LUT in Verilog codes - * This function will : + * Generate the standard-cell-based internal logic (multiplexing structure) + * for a multiplexer or LUT in Verilog codes + * This function will : * 1. build a multiplexing structure by instanciating standard cells MUX2 * 2. add intermediate buffers between multiplexing stages if specified. *******************************************************************/ -static -void build_cmos_mux_module_mux2_multiplexing_structure(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const ModuleId& mux_module, - const CircuitModelId& mux_model, - const CircuitModelId& std_cell_model, - const vtr::vector& mux_module_input_nets, - const vtr::vector& mux_module_output_nets, - const vtr::vector& mux_module_mem_nets, - const MuxGraph& mux_graph) { +static void build_cmos_mux_module_mux2_multiplexing_structure( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const ModuleId& mux_module, const CircuitModelId& mux_model, + const CircuitModelId& std_cell_model, + const vtr::vector& mux_module_input_nets, + const vtr::vector& mux_module_output_nets, + const vtr::vector& mux_module_mem_nets, + const MuxGraph& mux_graph) { /* Get the regular (non-mode-select) sram ports from the mux */ - std::vector mux_regular_sram_ports = find_circuit_regular_sram_ports(circuit_lib, mux_model); + std::vector mux_regular_sram_ports = + find_circuit_regular_sram_ports(circuit_lib, mux_model); VTR_ASSERT(1 == mux_regular_sram_ports.size()); /* Find the input ports and output ports of the standard cell */ - std::vector std_cell_input_ports = circuit_lib.model_ports_by_type(std_cell_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector std_cell_output_ports = circuit_lib.model_ports_by_type(std_cell_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector std_cell_input_ports = + circuit_lib.model_ports_by_type(std_cell_model, CIRCUIT_MODEL_PORT_INPUT, + true); + std::vector std_cell_output_ports = + circuit_lib.model_ports_by_type(std_cell_model, CIRCUIT_MODEL_PORT_OUTPUT, + true); /* Quick check the requirements on port map */ VTR_ASSERT(3 == std_cell_input_ports.size()); VTR_ASSERT(1 == std_cell_output_ports.size()); @@ -387,31 +456,44 @@ void build_cmos_mux_module_mux2_multiplexing_structure(ModuleManager& module_man /* Find module information of the standard cell MUX2 */ std::string std_cell_module_name = circuit_lib.model_name(std_cell_model); /* Get the moduleId for the submodule */ - ModuleId std_cell_module_id = module_manager.find_module(std_cell_module_name); + ModuleId std_cell_module_id = + module_manager.find_module(std_cell_module_name); /* We must have one */ VTR_ASSERT(ModuleId::INVALID() != std_cell_module_id); /* Find the module ports of the standard cell MUX2 module */ std::vector std_cell_module_inputs; std::vector std_cell_module_input_ports; - /* Input 0 port is the first data path input of the tgate, whose size must be 1 ! */ + /* Input 0 port is the first data path input of the tgate, whose size must be + * 1 ! */ for (size_t port_id = 0; port_id < 2; ++port_id) { - std_cell_module_inputs.push_back(module_manager.find_module_port(std_cell_module_id, circuit_lib.port_prefix(std_cell_input_ports[port_id]))); - VTR_ASSERT(true == module_manager.valid_module_port_id(std_cell_module_id, std_cell_module_inputs[port_id])); - std_cell_module_input_ports.push_back(module_manager.module_port(std_cell_module_id, std_cell_module_inputs[port_id])); + std_cell_module_inputs.push_back(module_manager.find_module_port( + std_cell_module_id, + circuit_lib.port_prefix(std_cell_input_ports[port_id]))); + VTR_ASSERT(true == module_manager.valid_module_port_id( + std_cell_module_id, std_cell_module_inputs[port_id])); + std_cell_module_input_ports.push_back(module_manager.module_port( + std_cell_module_id, std_cell_module_inputs[port_id])); VTR_ASSERT(1 == std_cell_module_input_ports[port_id].get_width()); } /* Mem port is the memory of the standard cell MUX2, whose size must be 1 ! */ - ModulePortId std_cell_module_mem = module_manager.find_module_port(std_cell_module_id, circuit_lib.port_prefix(std_cell_input_ports[2])); - VTR_ASSERT(true == module_manager.valid_module_port_id(std_cell_module_id, std_cell_module_mem)); - BasicPort std_cell_module_mem_port = module_manager.module_port(std_cell_module_id, std_cell_module_mem); + ModulePortId std_cell_module_mem = module_manager.find_module_port( + std_cell_module_id, circuit_lib.port_prefix(std_cell_input_ports[2])); + VTR_ASSERT(true == module_manager.valid_module_port_id(std_cell_module_id, + std_cell_module_mem)); + BasicPort std_cell_module_mem_port = + module_manager.module_port(std_cell_module_id, std_cell_module_mem); VTR_ASSERT(1 == std_cell_module_mem_port.get_width()); - /* Output port is the data path output of the standard cell MUX2, whose size must be 1 ! */ - ModulePortId std_cell_module_output = module_manager.find_module_port(std_cell_module_id, circuit_lib.port_prefix(std_cell_output_ports[0])); - VTR_ASSERT(true == module_manager.valid_module_port_id(std_cell_module_id, std_cell_module_output)); - BasicPort std_cell_module_output_port = module_manager.module_port(std_cell_module_id, std_cell_module_output); + /* Output port is the data path output of the standard cell MUX2, whose size + * must be 1 ! */ + ModulePortId std_cell_module_output = module_manager.find_module_port( + std_cell_module_id, circuit_lib.port_prefix(std_cell_output_ports[0])); + VTR_ASSERT(true == module_manager.valid_module_port_id( + std_cell_module_id, std_cell_module_output)); + BasicPort std_cell_module_output_port = + module_manager.module_port(std_cell_module_id, std_cell_module_output); VTR_ASSERT(1 == std_cell_module_output_port.get_width()); /* Cache Net ids for each level of the multiplexer */ @@ -423,19 +505,22 @@ void build_cmos_mux_module_mux2_multiplexing_structure(ModuleManager& module_man } /* Build the location map of intermediate buffers */ - std::vector inter_buffer_location_map = build_mux_intermediate_buffer_location_map(circuit_lib, mux_model, mux_graph.num_node_levels()); - + std::vector inter_buffer_location_map = + build_mux_intermediate_buffer_location_map(circuit_lib, mux_model, + mux_graph.num_node_levels()); + /* Add all the branch modules and intermediate buffers */ for (const auto& node : mux_graph.non_input_nodes()) { - /* Get the size of branch circuit - * Instanciate an branch circuit by the size (fan-in) of the node + /* Get the size of branch circuit + * Instanciate an branch circuit by the size (fan-in) of the node */ size_t branch_size = mux_graph.node_in_edges(node).size(); /* To match the standard cell MUX2: We should have only 2 input_nodes */ VTR_ASSERT(2 == branch_size); /* Find the instance id */ - size_t std_cell_instance_id = module_manager.num_instance(mux_module, std_cell_module_id); + size_t std_cell_instance_id = + module_manager.num_instance(mux_module, std_cell_module_id); /* Add the module to mux_module */ module_manager.add_child_module(mux_module, std_cell_module_id); @@ -443,11 +528,14 @@ void build_cmos_mux_module_mux2_multiplexing_structure(ModuleManager& module_man size_t output_node_level = mux_graph.node_level(node); size_t output_node_index_at_level = mux_graph.node_index_at_level(node); /* Set a name for the instance */ - std::string std_cell_instance_name = generate_mux_branch_instance_name(output_node_level, output_node_index_at_level, false); - module_manager.set_child_instance_name(mux_module, std_cell_module_id, std_cell_instance_id, std_cell_instance_name); + std::string std_cell_instance_name = generate_mux_branch_instance_name( + output_node_level, output_node_index_at_level, false); + module_manager.set_child_instance_name(mux_module, std_cell_module_id, + std_cell_instance_id, + std_cell_instance_name); /* Add module nets to wire to next stage modules */ - ModuleNetId branch_net; + ModuleNetId branch_net; if (true == mux_graph.is_node_output(node)) { /* This is an output node, we should use existing output nets */ MuxOutputId output_id = mux_graph.output_id(node); @@ -456,14 +544,17 @@ void build_cmos_mux_module_mux2_multiplexing_structure(ModuleManager& module_man VTR_ASSERT(false == mux_graph.is_node_output(node)); branch_net = module_manager.create_module_net(mux_module); } - module_manager.add_module_net_source(mux_module, branch_net, std_cell_module_id, std_cell_instance_id, std_cell_module_output, std_cell_module_output_port.get_lsb()); + module_manager.add_module_net_source( + mux_module, branch_net, std_cell_module_id, std_cell_instance_id, + std_cell_module_output, std_cell_module_output_port.get_lsb()); /* Record the module net id in the cache */ - module_nets_by_level[output_node_level][output_node_index_at_level] = branch_net; + module_nets_by_level[output_node_level][output_node_index_at_level] = + branch_net; /* Wire the branch module memory ports to the nets of MUX memory ports */ /* Get the mems in the branch circuits */ - std::vector mems; + std::vector mems; for (const auto& edge : mux_graph.node_in_edges(node)) { /* Get the mem control the edge */ MuxMemId mem = mux_graph.find_edge_mem(edge); @@ -472,16 +563,19 @@ void build_cmos_mux_module_mux2_multiplexing_structure(ModuleManager& module_man mems.push_back(mem); } } - /* Connect mem to mem net one by one + /* Connect mem to mem net one by one * Note that standard cell MUX2 only needs mem but NOT mem_inv */ for (const MuxMemId& mem : mems) { - module_manager.add_module_net_sink(mux_module, mux_module_mem_nets[mem], std_cell_module_id, std_cell_instance_id, std_cell_module_mem, std_cell_module_mem_port.get_lsb()); + module_manager.add_module_net_sink( + mux_module, mux_module_mem_nets[mem], std_cell_module_id, + std_cell_instance_id, std_cell_module_mem, + std_cell_module_mem_port.get_lsb()); } /* Wire the branch module inputs to the nets in previous stage */ /* Get the nodes which drive the root_node */ - std::vector input_nodes; + std::vector input_nodes; for (const auto& edge : mux_graph.node_in_edges(node)) { /* Get the nodes drive the edge */ for (const auto& src_node : mux_graph.edge_src_nodes(edge)) { @@ -492,68 +586,79 @@ void build_cmos_mux_module_mux2_multiplexing_structure(ModuleManager& module_man VTR_ASSERT(input_nodes.size() == branch_size); /* To match the standard cell MUX2: We should have only 2 input_nodes */ VTR_ASSERT(2 == input_nodes.size()); - /* build the link between input_node[0] and std_cell_input_port[0] - * build the link between input_node[1] and std_cell_input_port[1] + /* build the link between input_node[0] and std_cell_input_port[0] + * build the link between input_node[1] and std_cell_input_port[1] */ for (size_t node_id = 0; node_id < input_nodes.size(); ++node_id) { /* Find the port info of each input node */ size_t input_node_level = mux_graph.node_level(input_nodes[node_id]); - size_t input_node_index_at_level = mux_graph.node_index_at_level(input_nodes[node_id]); + size_t input_node_index_at_level = + mux_graph.node_index_at_level(input_nodes[node_id]); /* For inputs of mux, the net id is reserved */ if (true == mux_graph.is_node_input(input_nodes[node_id])) { /* Get node input id */ MuxInputId input_id = mux_graph.input_id(input_nodes[node_id]); - module_manager.add_module_net_sink(mux_module, mux_module_input_nets[input_id], std_cell_module_id, std_cell_instance_id, std_cell_module_inputs[node_id], std_cell_module_input_ports[node_id].get_lsb()); + module_manager.add_module_net_sink( + mux_module, mux_module_input_nets[input_id], std_cell_module_id, + std_cell_instance_id, std_cell_module_inputs[node_id], + std_cell_module_input_ports[node_id].get_lsb()); } else { - VTR_ASSERT (false == mux_graph.is_node_input(input_nodes[node_id])); + VTR_ASSERT(false == mux_graph.is_node_input(input_nodes[node_id])); /* Find the input port of standard cell */ - module_manager.add_module_net_sink(mux_module, module_nets_by_level[input_node_level][input_node_index_at_level], std_cell_module_id, std_cell_instance_id, std_cell_module_inputs[node_id], std_cell_module_input_ports[node_id].get_lsb()); + module_manager.add_module_net_sink( + mux_module, + module_nets_by_level[input_node_level][input_node_index_at_level], + std_cell_module_id, std_cell_instance_id, + std_cell_module_inputs[node_id], + std_cell_module_input_ports[node_id].get_lsb()); } } /* Identify if an intermediate buffer is needed */ - if (false == inter_buffer_location_map[output_node_level]) { + if (false == inter_buffer_location_map[output_node_level]) { continue; } /* Add an intermediate buffer to mux_module if needed */ if (true == mux_graph.is_node_output(node)) { - /* Output node does not need buffer addition here, it is handled outside this function */ - continue; + /* Output node does not need buffer addition here, it is handled outside + * this function */ + continue; } /* Now we need to add intermediate buffers by instanciating the modules */ - CircuitModelId buffer_model = circuit_lib.lut_intermediate_buffer_model(mux_model); + CircuitModelId buffer_model = + circuit_lib.lut_intermediate_buffer_model(mux_model); /* We must have a valid model id */ VTR_ASSERT(CircuitModelId::INVALID() != buffer_model); /* Create a module net which sources from buffer output */ - ModuleNetId buffer_net = add_inverter_buffer_child_module_and_nets(module_manager, mux_module, circuit_lib, buffer_model, branch_net); + ModuleNetId buffer_net = add_inverter_buffer_child_module_and_nets( + module_manager, mux_module, circuit_lib, buffer_model, branch_net); /* Record the module net id in the cache */ - module_nets_by_level[output_node_level][output_node_index_at_level] = buffer_net; + module_nets_by_level[output_node_level][output_node_index_at_level] = + buffer_net; } } /******************************************************************** - * Generate the pass-transistor/transmission-gate -based internal logic - * (multiplexing structure) for a multiplexer or LUT in Verilog codes - * This function will : + * Generate the pass-transistor/transmission-gate -based internal logic + * (multiplexing structure) for a multiplexer or LUT in Verilog codes + * This function will : * 1. build a multiplexing structure by instanciating the branch circuits * generated before * 2. add intermediate buffers between multiplexing stages if specified. *******************************************************************/ -static -void build_cmos_mux_module_tgate_multiplexing_structure(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const ModuleId& mux_module, - const CircuitModelId& circuit_model, - const vtr::vector& mux_module_input_nets, - const vtr::vector& mux_module_output_nets, - const vtr::vector& mux_module_mem_nets, - const vtr::vector& mux_module_mem_inv_nets, - const MuxGraph& mux_graph) { - +static void build_cmos_mux_module_tgate_multiplexing_structure( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const ModuleId& mux_module, const CircuitModelId& circuit_model, + const vtr::vector& mux_module_input_nets, + const vtr::vector& mux_module_output_nets, + const vtr::vector& mux_module_mem_nets, + const vtr::vector& mux_module_mem_inv_nets, + const MuxGraph& mux_graph) { /* Get the regular (non-mode-select) sram ports from the mux */ - std::vector mux_regular_sram_ports = find_circuit_regular_sram_ports(circuit_lib, circuit_model); + std::vector mux_regular_sram_ports = + find_circuit_regular_sram_ports(circuit_lib, circuit_model); VTR_ASSERT(1 == mux_regular_sram_ports.size()); /* Cache Net ids for each level of the multiplexer */ @@ -565,17 +670,19 @@ void build_cmos_mux_module_tgate_multiplexing_structure(ModuleManager& module_ma } /* Build the location map of intermediate buffers */ - std::vector inter_buffer_location_map = build_mux_intermediate_buffer_location_map(circuit_lib, circuit_model, mux_graph.num_node_levels()); - + std::vector inter_buffer_location_map = + build_mux_intermediate_buffer_location_map(circuit_lib, circuit_model, + mux_graph.num_node_levels()); + /* Add all the branch modules and intermediate buffers */ for (const auto& node : mux_graph.non_input_nodes()) { - /* Get the size of branch circuit - * Instanciate an branch circuit by the size (fan-in) of the node + /* Get the size of branch circuit + * Instanciate an branch circuit by the size (fan-in) of the node */ size_t branch_size = mux_graph.node_in_edges(node).size(); /* Get the mems in the branch circuits */ - std::vector mems; + std::vector mems; for (const auto& edge : mux_graph.node_in_edges(node)) { /* Get the mem control the edge */ MuxMemId mem = mux_graph.find_edge_mem(edge); @@ -586,14 +693,17 @@ void build_cmos_mux_module_tgate_multiplexing_structure(ModuleManager& module_ma } /* Instanciate the branch module which is a tgate-based module */ - std::string branch_module_name= generate_mux_branch_subckt_name(circuit_lib, circuit_model, branch_size, mems.size(), MUX_BASIS_MODULE_POSTFIX); + std::string branch_module_name = + generate_mux_branch_subckt_name(circuit_lib, circuit_model, branch_size, + mems.size(), MUX_BASIS_MODULE_POSTFIX); /* Get the moduleId for the submodule */ ModuleId branch_module_id = module_manager.find_module(branch_module_name); /* We must have one */ VTR_ASSERT(ModuleId::INVALID() != branch_module_id); /* Find the instance id */ - size_t branch_instance_id = module_manager.num_instance(mux_module, branch_module_id); + size_t branch_instance_id = + module_manager.num_instance(mux_module, branch_module_id); /* Add the module to mux_module */ module_manager.add_child_module(mux_module, branch_module_id); @@ -601,15 +711,19 @@ void build_cmos_mux_module_tgate_multiplexing_structure(ModuleManager& module_ma size_t output_node_level = mux_graph.node_level(node); size_t output_node_index_at_level = mux_graph.node_index_at_level(node); /* Set a name for the instance */ - std::string branch_instance_name = generate_mux_branch_instance_name(output_node_level, output_node_index_at_level, false); - module_manager.set_child_instance_name(mux_module, branch_module_id, branch_instance_id, branch_instance_name); + std::string branch_instance_name = generate_mux_branch_instance_name( + output_node_level, output_node_index_at_level, false); + module_manager.set_child_instance_name( + mux_module, branch_module_id, branch_instance_id, branch_instance_name); /* Get the output port id of branch module */ - ModulePortId branch_module_output_port_id = module_manager.find_module_port(branch_module_id, std::string("out")); - BasicPort branch_module_output_port = module_manager.module_port(branch_module_id, branch_module_output_port_id); + ModulePortId branch_module_output_port_id = + module_manager.find_module_port(branch_module_id, std::string("out")); + BasicPort branch_module_output_port = module_manager.module_port( + branch_module_id, branch_module_output_port_id); /* Add module nets to wire to next stage modules */ - ModuleNetId branch_net; + ModuleNetId branch_net; if (true == mux_graph.is_node_output(node)) { /* This is an output node, we should use existing output nets */ MuxOutputId output_id = mux_graph.output_id(node); @@ -618,34 +732,49 @@ void build_cmos_mux_module_tgate_multiplexing_structure(ModuleManager& module_ma VTR_ASSERT(false == mux_graph.is_node_output(node)); branch_net = module_manager.create_module_net(mux_module); } - module_manager.add_module_net_source(mux_module, branch_net, branch_module_id, branch_instance_id, branch_module_output_port_id, branch_module_output_port.get_lsb()); + module_manager.add_module_net_source( + mux_module, branch_net, branch_module_id, branch_instance_id, + branch_module_output_port_id, branch_module_output_port.get_lsb()); /* Record the module net id in the cache */ - module_nets_by_level[output_node_level][output_node_index_at_level] = branch_net; + module_nets_by_level[output_node_level][output_node_index_at_level] = + branch_net; /* Wire the branch module memory ports to the nets of MUX memory ports */ /* Get mem/mem_inv ports of branch module */ - ModulePortId branch_module_mem_port_id = module_manager.find_module_port(branch_module_id, std::string("mem")); - BasicPort branch_module_mem_port = module_manager.module_port(branch_module_id, branch_module_mem_port_id); - ModulePortId branch_module_mem_inv_port_id = module_manager.find_module_port(branch_module_id, std::string("mem_inv")); - BasicPort branch_module_mem_inv_port = module_manager.module_port(branch_module_id, branch_module_mem_inv_port_id); + ModulePortId branch_module_mem_port_id = + module_manager.find_module_port(branch_module_id, std::string("mem")); + BasicPort branch_module_mem_port = + module_manager.module_port(branch_module_id, branch_module_mem_port_id); + ModulePortId branch_module_mem_inv_port_id = + module_manager.find_module_port(branch_module_id, std::string("mem_inv")); + BasicPort branch_module_mem_inv_port = module_manager.module_port( + branch_module_id, branch_module_mem_inv_port_id); - /* Note that we do NOT care inverted edge-to-mem connection. + /* Note that we do NOT care inverted edge-to-mem connection. * It is handled in branch module generation!!! */ /* Connect mem/mem_inv to mem/mem_inv net one by one */ for (size_t mem_id = 0; mem_id < mems.size(); ++mem_id) { - module_manager.add_module_net_sink(mux_module, mux_module_mem_nets[mems[mem_id]], branch_module_id, branch_instance_id, branch_module_mem_port_id, branch_module_mem_port.pins()[mem_id]); - module_manager.add_module_net_sink(mux_module, mux_module_mem_inv_nets[mems[mem_id]], branch_module_id, branch_instance_id, branch_module_mem_inv_port_id, branch_module_mem_inv_port.pins()[mem_id]); + module_manager.add_module_net_sink( + mux_module, mux_module_mem_nets[mems[mem_id]], branch_module_id, + branch_instance_id, branch_module_mem_port_id, + branch_module_mem_port.pins()[mem_id]); + module_manager.add_module_net_sink( + mux_module, mux_module_mem_inv_nets[mems[mem_id]], branch_module_id, + branch_instance_id, branch_module_mem_inv_port_id, + branch_module_mem_inv_port.pins()[mem_id]); } /* Wire the branch module inputs to the nets in previous stage */ /* Get the input port id of branch module */ - ModulePortId branch_module_input_port_id = module_manager.find_module_port(branch_module_id, std::string("in")); - BasicPort branch_module_input_port = module_manager.module_port(branch_module_id, branch_module_input_port_id); + ModulePortId branch_module_input_port_id = + module_manager.find_module_port(branch_module_id, std::string("in")); + BasicPort branch_module_input_port = + module_manager.module_port(branch_module_id, branch_module_input_port_id); /* Get the nodes which drive the root_node */ - std::vector input_nodes; + std::vector input_nodes; for (const auto& edge : mux_graph.node_in_edges(node)) { /* Get the nodes drive the edge */ for (const auto& src_node : mux_graph.edge_src_nodes(edge)) { @@ -654,58 +783,70 @@ void build_cmos_mux_module_tgate_multiplexing_structure(ModuleManager& module_ma } /* Number of inputs should match the branch_input_size!!! */ VTR_ASSERT(input_nodes.size() == branch_size); - /* build the link between input_node and branch circuit input_port[0] + /* build the link between input_node and branch circuit input_port[0] */ for (size_t node_id = 0; node_id < input_nodes.size(); ++node_id) { /* Find the port info of each input node */ size_t input_node_level = mux_graph.node_level(input_nodes[node_id]); - size_t input_node_index_at_level = mux_graph.node_index_at_level(input_nodes[node_id]); + size_t input_node_index_at_level = + mux_graph.node_index_at_level(input_nodes[node_id]); /* For inputs of mux, the net id is reserved */ if (true == mux_graph.is_node_input(input_nodes[node_id])) { /* Get node input id */ MuxInputId input_id = mux_graph.input_id(input_nodes[node_id]); - module_manager.add_module_net_sink(mux_module, mux_module_input_nets[input_id], branch_module_id, branch_instance_id, branch_module_input_port_id, branch_module_input_port.pins()[node_id]); + module_manager.add_module_net_sink( + mux_module, mux_module_input_nets[input_id], branch_module_id, + branch_instance_id, branch_module_input_port_id, + branch_module_input_port.pins()[node_id]); } else { - VTR_ASSERT (false == mux_graph.is_node_input(input_nodes[node_id])); - module_manager.add_module_net_sink(mux_module, module_nets_by_level[input_node_level][input_node_index_at_level], branch_module_id, branch_instance_id, branch_module_input_port_id, branch_module_input_port.pins()[node_id]); + VTR_ASSERT(false == mux_graph.is_node_input(input_nodes[node_id])); + module_manager.add_module_net_sink( + mux_module, + module_nets_by_level[input_node_level][input_node_index_at_level], + branch_module_id, branch_instance_id, branch_module_input_port_id, + branch_module_input_port.pins()[node_id]); } } /* Identify if an intermediate buffer is needed */ - if (false == inter_buffer_location_map[output_node_level]) { + if (false == inter_buffer_location_map[output_node_level]) { continue; } /* Add an intermediate buffer to mux_module if needed */ if (true == mux_graph.is_node_output(node)) { - /* Output node does not need buffer addition here, it is handled outside this function */ - continue; + /* Output node does not need buffer addition here, it is handled outside + * this function */ + continue; } /* Now we need to add intermediate buffers by instanciating the modules */ - CircuitModelId buffer_model = circuit_lib.lut_intermediate_buffer_model(circuit_model); + CircuitModelId buffer_model = + circuit_lib.lut_intermediate_buffer_model(circuit_model); /* We must have a valid model id */ VTR_ASSERT(CircuitModelId::INVALID() != buffer_model); - ModuleNetId buffer_net = add_inverter_buffer_child_module_and_nets(module_manager, mux_module, circuit_lib, buffer_model, branch_net); + ModuleNetId buffer_net = add_inverter_buffer_child_module_and_nets( + module_manager, mux_module, circuit_lib, buffer_model, branch_net); /* Record the module net id in the cache */ - module_nets_by_level[output_node_level][output_node_index_at_level] = buffer_net; + module_nets_by_level[output_node_level][output_node_index_at_level] = + buffer_net; } } /********************************************************************* - * This function will add nets and input buffers (if needed) - * to a mux module + * This function will add nets and input buffers (if needed) + * to a mux module * Module net represents the connections when there are no input buffers * mux_input_net[0] * | * v +------------ * mux_in[0] ----------->| * | - * | + * | * | * | Multiplexing * mux_input_net[i] | Structure - * | | + * | | * v | * mux_in[0] ----------->| * | @@ -717,71 +858,82 @@ void build_cmos_mux_module_tgate_multiplexing_structure(ModuleManager& module_ma * +-----------------+ v +------------ * mux_in[0] ----->| input_buffer[0] |-----> | * +-----------------+ | - * | + * | * ... | * | Multiplexing * mux_input_net[i] | Structure - * | | + * | | * +-----------------+ v | * mux_in[0] ----->| input_buffer[0] |-----> | * +-----------------+ | *********************************************************************/ -static -vtr::vector build_mux_module_input_buffers(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const ModuleId& mux_module, - const CircuitModelId& mux_model, - const MuxGraph& mux_graph) { - vtr::vector mux_input_nets(mux_graph.num_inputs(), ModuleNetId::INVALID()); +static vtr::vector build_mux_module_input_buffers( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const ModuleId& mux_module, const CircuitModelId& mux_model, + const MuxGraph& mux_graph) { + vtr::vector mux_input_nets(mux_graph.num_inputs(), + ModuleNetId::INVALID()); /* Get the input ports from the mux: - * - LUT may have ports that are driven by harden logic, + * - LUT may have ports that are driven by harden logic, * which should not be included when building the mux graph */ std::vector mux_input_ports; if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model)) { - mux_input_ports = find_lut_circuit_model_input_port(circuit_lib, mux_model, false, false); + mux_input_ports = + find_lut_circuit_model_input_port(circuit_lib, mux_model, false, false); } else { - VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)); - mux_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); + VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)); + mux_input_ports = circuit_lib.model_ports_by_type( + mux_model, CIRCUIT_MODEL_PORT_INPUT, true); } /* We should have only 1 input port! */ VTR_ASSERT(1 == mux_input_ports.size()); /* Get the input port from MUX module */ - ModulePortId module_input_port_id = module_manager.find_module_port(mux_module, circuit_lib.port_prefix(mux_input_ports[0])); + ModulePortId module_input_port_id = module_manager.find_module_port( + mux_module, circuit_lib.port_prefix(mux_input_ports[0])); VTR_ASSERT(ModulePortId::INVALID() != module_input_port_id); /* Get the port from module */ - BasicPort module_input_port = module_manager.module_port(mux_module, module_input_port_id); + BasicPort module_input_port = + module_manager.module_port(mux_module, module_input_port_id); /* Iterate over all the inputs in the MUX graph */ for (const auto& input_node : mux_graph.inputs()) { /* Fetch fundamental information from MUX graph w.r.t. the input node */ MuxInputId input_index = mux_graph.input_id(input_node); - VTR_ASSERT(MuxInputId::INVALID() != input_index); - + VTR_ASSERT(MuxInputId::INVALID() != input_index); + /* For last input: - * Add a constant value to the last input, if this MUX needs a constant input + * Add a constant value to the last input, if this MUX needs a constant + * input */ - if ( (MuxInputId(mux_graph.num_inputs() - 1) == mux_graph.input_id(input_node)) - && (true == circuit_lib.mux_add_const_input(mux_model)) ) { + if ((MuxInputId(mux_graph.num_inputs() - 1) == + mux_graph.input_id(input_node)) && + (true == circuit_lib.mux_add_const_input(mux_model))) { /* Get the constant input value */ size_t const_value = circuit_lib.mux_const_input_value(mux_model); - VTR_ASSERT( (0 == const_value) || (1 == const_value) ); + VTR_ASSERT((0 == const_value) || (1 == const_value)); /* Instanciate a VDD module (default module) * and build a net between VDD and the MUX input */ /* Get the moduleId for the buffer module */ - ModuleId const_val_module_id = module_manager.find_module(generate_const_value_module_name(const_value)); + ModuleId const_val_module_id = module_manager.find_module( + generate_const_value_module_name(const_value)); /* We must have one */ VTR_ASSERT(ModuleId::INVALID() != const_val_module_id); - size_t const_val_instance = module_manager.num_instance(mux_module, const_val_module_id); + size_t const_val_instance = + module_manager.num_instance(mux_module, const_val_module_id); module_manager.add_child_module(mux_module, const_val_module_id); - ModulePortId const_port_id = module_manager.find_module_port(const_val_module_id, generate_const_value_module_output_port_name(const_value)); + ModulePortId const_port_id = module_manager.find_module_port( + const_val_module_id, + generate_const_value_module_output_port_name(const_value)); ModuleNetId input_net = module_manager.create_module_net(mux_module); - module_manager.add_module_net_source(mux_module, input_net, const_val_module_id, const_val_instance, const_port_id, 0); + module_manager.add_module_net_source( + mux_module, input_net, const_val_module_id, const_val_instance, + const_port_id, 0); mux_input_nets[input_index] = input_net; continue; } @@ -789,11 +941,13 @@ vtr::vector build_mux_module_input_buffers(ModuleManage /* When we do not need any buffer, create a net for the input directly */ if (false == circuit_lib.is_input_buffered(mux_model)) { ModuleNetId input_net = module_manager.create_module_net(mux_module); - module_manager.add_module_net_source(mux_module, input_net, mux_module, 0, module_input_port_id, size_t(input_index)); + module_manager.add_module_net_source(mux_module, input_net, mux_module, 0, + module_input_port_id, + size_t(input_index)); mux_input_nets[input_index] = input_net; continue; } - + /* Now we need to add intermediate buffers by instanciating the modules */ CircuitModelId buffer_model = circuit_lib.input_buffer_model(mux_model); /* We must have a valid model id */ @@ -801,10 +955,13 @@ vtr::vector build_mux_module_input_buffers(ModuleManage /* Connect the module net from branch output to buffer input */ ModuleNetId buffer_net = module_manager.create_module_net(mux_module); - module_manager.add_module_net_source(mux_module, buffer_net, mux_module, 0, module_input_port_id, size_t(input_index)); + module_manager.add_module_net_source(mux_module, buffer_net, mux_module, 0, + module_input_port_id, + size_t(input_index)); /* Create a module net which sources from buffer output */ - ModuleNetId input_net = add_inverter_buffer_child_module_and_nets(module_manager, mux_module, circuit_lib, buffer_model, buffer_net); + ModuleNetId input_net = add_inverter_buffer_child_module_and_nets( + module_manager, mux_module, circuit_lib, buffer_model, buffer_net); mux_input_nets[input_index] = input_net; } @@ -812,8 +969,8 @@ vtr::vector build_mux_module_input_buffers(ModuleManage } /********************************************************************* - * This function will add nets and input buffers (if needed) - * to a mux module + * This function will add nets and input buffers (if needed) + * to a mux module * Module net represents the connections when there are no output buffers * * mux_output_net[0] @@ -834,84 +991,94 @@ vtr::vector build_mux_module_input_buffers(ModuleManage * mux_output_net[0] * ------------+ | * | | - * | v +------------------+ + * | v +------------------+ * |------->| output_buffer[0] |------> mux_output[0] - * | +------------------+ + * | +------------------+ * | * Multiplexer | ... * Strcuture | - * | +------------------+ + * | +------------------+ * |------->| output_buffer[i] |------> mux_output[i] - * | ^ +------------------+ + * | ^ +------------------+ * | | * | | * ------------+ mux_output_net[i] * *********************************************************************/ -static -vtr::vector build_mux_module_output_buffers(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const ModuleId& mux_module, - const CircuitModelId& mux_model, - const MuxGraph& mux_graph) { - +static vtr::vector build_mux_module_output_buffers( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const ModuleId& mux_module, const CircuitModelId& mux_model, + const MuxGraph& mux_graph) { /* Create module nets for output ports */ - vtr::vector mux_output_nets(mux_graph.num_outputs(), ModuleNetId::INVALID()); + vtr::vector mux_output_nets(mux_graph.num_outputs(), + ModuleNetId::INVALID()); /* Get the output ports from the mux: - * - LUT may have ports that are driven by harden logic, + * - LUT may have ports that are driven by harden logic, * which should not be included when building the mux graph - * - LUT may have global output ports that are wired directly to top-level module + * - LUT may have global output ports that are wired directly to top-level + * module */ std::vector mux_output_ports; if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model)) { - mux_output_ports = find_lut_circuit_model_output_port(circuit_lib, mux_model, false, true); + mux_output_ports = + find_lut_circuit_model_output_port(circuit_lib, mux_model, false, true); } else { - VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)); - mux_output_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_OUTPUT, false); + VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)); + mux_output_ports = circuit_lib.model_ports_by_type( + mux_model, CIRCUIT_MODEL_PORT_OUTPUT, false); } /* Iterate over all the outputs in the MUX module */ for (const auto& output_port : mux_output_ports) { /* Get the output port from MUX module */ - ModulePortId module_output_port_id = module_manager.find_module_port(mux_module, circuit_lib.port_prefix(output_port)); + ModulePortId module_output_port_id = module_manager.find_module_port( + mux_module, circuit_lib.port_prefix(output_port)); VTR_ASSERT(ModulePortId::INVALID() != module_output_port_id); /* Get the port from module */ - BasicPort module_output_port = module_manager.module_port(mux_module, module_output_port_id); + BasicPort module_output_port = + module_manager.module_port(mux_module, module_output_port_id); /* Iterate over each pin of the output port */ for (const size_t& pin : circuit_lib.pins(output_port)) { /* Fetch fundamental information from MUX graph w.r.t. the input node */ /* Deposite the last level of the graph, which is a default value */ - size_t output_node_level = mux_graph.num_node_levels() - 1; - /* If there is a fracturable level specified for the output, we find the exact level */ + size_t output_node_level = mux_graph.num_node_levels() - 1; + /* If there is a fracturable level specified for the output, we find the + * exact level */ if (size_t(-1) != circuit_lib.port_lut_frac_level(output_port)) { output_node_level = circuit_lib.port_lut_frac_level(output_port); } /* Deposite a zero, which is a default value */ - size_t output_node_index_at_level = 0; + size_t output_node_index_at_level = 0; /* If there are output masks, we find the node_index */ if (!circuit_lib.port_lut_output_mask(output_port).empty()) { - output_node_index_at_level = circuit_lib.port_lut_output_mask(output_port).at(pin); - } + output_node_index_at_level = + circuit_lib.port_lut_output_mask(output_port).at(pin); + } /* Double check the node exists in the Mux Graph */ - MuxNodeId node_id = mux_graph.node_id(output_node_level, output_node_index_at_level); + MuxNodeId node_id = + mux_graph.node_id(output_node_level, output_node_index_at_level); VTR_ASSERT(MuxNodeId::INVALID() != node_id); MuxOutputId output_index = mux_graph.output_id(node_id); - /* Create the port information of the module output at the given pin range, which is the output of buffer instance */ + /* Create the port information of the module output at the given pin + * range, which is the output of buffer instance */ BasicPort instance_output_port(module_output_port.get_name(), pin, pin); - /* If the output is not supposed to be buffered, create a net for the input directly */ + /* If the output is not supposed to be buffered, create a net for the + * input directly */ if (false == circuit_lib.is_output_buffered(mux_model)) { ModuleNetId output_net = module_manager.create_module_net(mux_module); - module_manager.add_module_net_sink(mux_module, output_net, mux_module, 0, module_output_port_id, pin); + module_manager.add_module_net_sink(mux_module, output_net, mux_module, + 0, module_output_port_id, pin); mux_output_nets[output_index] = output_net; continue; /* Finish here */ } - /* Reach here, we need a buffer, create a port-to-port map and output the buffer instance */ + /* Reach here, we need a buffer, create a port-to-port map and output the + * buffer instance */ /* Now we need to add intermediate buffers by instanciating the modules */ CircuitModelId buffer_model = circuit_lib.output_buffer_model(mux_model); /* We must have a valid model id */ @@ -919,8 +1086,10 @@ vtr::vector build_mux_module_output_buffers(ModuleMana /* Create a module net which sinks at buffer input */ ModuleNetId input_net = module_manager.create_module_net(mux_module); - ModuleNetId output_net = add_inverter_buffer_child_module_and_nets(module_manager, mux_module, circuit_lib, buffer_model, input_net); - module_manager.add_module_net_sink(mux_module, output_net, mux_module, 0, module_output_port_id, pin); + ModuleNetId output_net = add_inverter_buffer_child_module_and_nets( + module_manager, mux_module, circuit_lib, buffer_model, input_net); + module_manager.add_module_net_sink(mux_module, output_net, mux_module, 0, + module_output_port_id, pin); mux_output_nets[output_index] = input_net; } } @@ -929,18 +1098,18 @@ vtr::vector build_mux_module_output_buffers(ModuleMana } /********************************************************************* - * This function will + * This function will * 1. Build local encoders for a MUX module (if specified) * 2. Build nets between memory ports of a MUX module and branch circuits * This happens when local encoders are not needed * - * MUX module + * MUX module * +--------------------- * | mux_mem_nets/mux_mem_inv_nets * | | * | v +--------- * mem-+-------->| - * | | Branch Module + * | | Branch Module * | | * * 3. Build nets between local encoders and memory ports of a MUX module @@ -961,16 +1130,12 @@ vtr::vector build_mux_module_output_buffers(ModuleMana * | | | | * *********************************************************************/ -static -void build_mux_module_local_encoders_and_memory_nets(ModuleManager& module_manager, - const ModuleId& mux_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const std::vector& mux_sram_ports, - const MuxGraph& mux_graph, - vtr::vector& mux_mem_nets, - vtr::vector& mux_mem_inv_nets) { - +static void build_mux_module_local_encoders_and_memory_nets( + ModuleManager& module_manager, const ModuleId& mux_module, + const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, + const std::vector& mux_sram_ports, const MuxGraph& mux_graph, + vtr::vector& mux_mem_nets, + vtr::vector& mux_mem_inv_nets) { /* Create nets here, and we will configure the net source later */ for (size_t mem = 0; mem < mux_graph.num_memory_bits(); ++mem) { ModuleNetId mem_net = module_manager.create_module_net(mux_module); @@ -983,12 +1148,14 @@ void build_mux_module_local_encoders_and_memory_nets(ModuleManager& module_manag /* Add mem and mem_inv nets here */ size_t mem_net_cnt = 0; for (const auto& port : mux_sram_ports) { - ModulePortId mem_port_id = module_manager.find_module_port(mux_module, circuit_lib.port_prefix(port)); + ModulePortId mem_port_id = module_manager.find_module_port( + mux_module, circuit_lib.port_prefix(port)); BasicPort mem_port = module_manager.module_port(mux_module, mem_port_id); for (const size_t& pin : mem_port.pins()) { MuxMemId mem_id = MuxMemId(mem_net_cnt); /* Set the module net source */ - module_manager.add_module_net_source(mux_module, mux_mem_nets[mem_id], mux_module, 0, mem_port_id, pin); + module_manager.add_module_net_source(mux_module, mux_mem_nets[mem_id], + mux_module, 0, mem_port_id, pin); /* Update counter */ mem_net_cnt++; } @@ -998,12 +1165,17 @@ void build_mux_module_local_encoders_and_memory_nets(ModuleManager& module_manag /* Add mem and mem_inv nets here */ size_t mem_inv_net_cnt = 0; for (const auto& port : mux_sram_ports) { - ModulePortId mem_inv_port_id = module_manager.find_module_port(mux_module, std::string(circuit_lib.port_prefix(port) + INV_PORT_POSTFIX)); - BasicPort mem_inv_port = module_manager.module_port(mux_module, mem_inv_port_id); + ModulePortId mem_inv_port_id = module_manager.find_module_port( + mux_module, + std::string(circuit_lib.port_prefix(port) + INV_PORT_POSTFIX)); + BasicPort mem_inv_port = + module_manager.module_port(mux_module, mem_inv_port_id); for (const size_t& pin : mem_inv_port.pins()) { MuxMemId mem_id = MuxMemId(mem_inv_net_cnt); /* Set the module net source */ - module_manager.add_module_net_source(mux_module, mux_mem_inv_nets[mem_id], mux_module, 0, mem_inv_port_id, pin); + module_manager.add_module_net_source( + mux_module, mux_mem_inv_nets[mem_id], mux_module, 0, mem_inv_port_id, + pin); /* Update counter */ mem_inv_net_cnt++; } @@ -1014,12 +1186,18 @@ void build_mux_module_local_encoders_and_memory_nets(ModuleManager& module_manag /* Add local decoder instance here */ VTR_ASSERT(true == circuit_lib.mux_use_local_encoder(mux_model)); - BasicPort decoder_data_port(generate_mux_local_decoder_data_port_name(), mux_graph.num_memory_bits()); - BasicPort decoder_data_inv_port(generate_mux_local_decoder_data_inv_port_name(), mux_graph.num_memory_bits()); + BasicPort decoder_data_port(generate_mux_local_decoder_data_port_name(), + mux_graph.num_memory_bits()); + BasicPort decoder_data_inv_port( + generate_mux_local_decoder_data_inv_port_name(), + mux_graph.num_memory_bits()); - /* Local port to record the LSB and MSB of each level, here, we deposite (0, 0) */ - ModulePortId mux_module_sram_port_id = module_manager.find_module_port(mux_module, circuit_lib.port_prefix(mux_sram_ports[0])); - ModulePortId mux_module_sram_inv_port_id = module_manager.find_module_port(mux_module, circuit_lib.port_prefix(mux_sram_ports[0]) + INV_PORT_POSTFIX); + /* Local port to record the LSB and MSB of each level, here, we deposite (0, + * 0) */ + ModulePortId mux_module_sram_port_id = module_manager.find_module_port( + mux_module, circuit_lib.port_prefix(mux_sram_ports[0])); + ModulePortId mux_module_sram_inv_port_id = module_manager.find_module_port( + mux_module, circuit_lib.port_prefix(mux_sram_ports[0]) + INV_PORT_POSTFIX); BasicPort lvl_addr_port(circuit_lib.port_prefix(mux_sram_ports[0]), 0); BasicPort lvl_data_port(decoder_data_port.get_name(), 0); BasicPort lvl_data_inv_port(decoder_data_inv_port.get_name(), 0); @@ -1029,7 +1207,8 @@ void build_mux_module_local_encoders_and_memory_nets(ModuleManager& module_manag size_t mem_inv_net_cnt = 0; for (const auto& lvl : mux_graph.levels()) { - size_t addr_size = find_mux_local_decoder_addr_size(mux_graph.num_memory_bits_at_level(lvl)); + size_t addr_size = + find_mux_local_decoder_addr_size(mux_graph.num_memory_bits_at_level(lvl)); size_t data_size = mux_graph.num_memory_bits_at_level(lvl); /* Update the LSB and MSB of addr and data port for the current level */ lvl_addr_port.rotate(addr_size); @@ -1041,174 +1220,207 @@ void build_mux_module_local_encoders_and_memory_nets(ModuleManager& module_manag for (size_t pin_id = 0; pin_id < lvl_addr_port.pins().size(); ++pin_id) { MuxMemId mem_id = MuxMemId(mem_net_cnt); /* Set the module net source */ - module_manager.add_module_net_source(mux_module, mux_mem_nets[mem_id], mux_module, 0, mux_module_sram_port_id, lvl_addr_port.pins()[pin_id]); + module_manager.add_module_net_source( + mux_module, mux_mem_nets[mem_id], mux_module, 0, + mux_module_sram_port_id, lvl_addr_port.pins()[pin_id]); /* Update counter */ mem_net_cnt++; MuxMemId mem_inv_id = MuxMemId(mem_inv_net_cnt); /* Set the module net source */ - module_manager.add_module_net_source(mux_module, mux_mem_inv_nets[mem_inv_id], mux_module, 0, mux_module_sram_inv_port_id, lvl_addr_port.pins()[pin_id]); + module_manager.add_module_net_source( + mux_module, mux_mem_inv_nets[mem_inv_id], mux_module, 0, + mux_module_sram_inv_port_id, lvl_addr_port.pins()[pin_id]); /* Update counter */ mem_inv_net_cnt++; } continue; } - std::string decoder_module_name = generate_mux_local_decoder_subckt_name(addr_size, data_size); - ModuleId decoder_module = module_manager.find_module(decoder_module_name); + std::string decoder_module_name = + generate_mux_local_decoder_subckt_name(addr_size, data_size); + ModuleId decoder_module = module_manager.find_module(decoder_module_name); VTR_ASSERT(ModuleId::INVALID() != decoder_module); - size_t decoder_instance = module_manager.num_instance(mux_module, decoder_module); + size_t decoder_instance = + module_manager.num_instance(mux_module, decoder_module); module_manager.add_child_module(mux_module, decoder_module); - + /* Add module nets to connect sram ports of MUX to address port */ - ModulePortId decoder_module_addr_port_id = module_manager.find_module_port(decoder_module, generate_mux_local_decoder_addr_port_name()); - BasicPort decoder_module_addr_port = module_manager.module_port(decoder_module, decoder_module_addr_port_id); - VTR_ASSERT(decoder_module_addr_port.get_width() == lvl_addr_port.get_width()); + ModulePortId decoder_module_addr_port_id = module_manager.find_module_port( + decoder_module, generate_mux_local_decoder_addr_port_name()); + BasicPort decoder_module_addr_port = + module_manager.module_port(decoder_module, decoder_module_addr_port_id); + VTR_ASSERT(decoder_module_addr_port.get_width() == + lvl_addr_port.get_width()); /* Build pin-to-pin net connection */ for (size_t pin_id = 0; pin_id < lvl_addr_port.pins().size(); ++pin_id) { ModuleNetId net = module_manager.create_module_net(mux_module); - module_manager.add_module_net_source(mux_module, net, mux_module, 0, mux_module_sram_port_id, lvl_addr_port.pins()[pin_id]); - module_manager.add_module_net_sink(mux_module, net, decoder_module, decoder_instance, decoder_module_addr_port_id, decoder_module_addr_port.pins()[pin_id]); + module_manager.add_module_net_source(mux_module, net, mux_module, 0, + mux_module_sram_port_id, + lvl_addr_port.pins()[pin_id]); + module_manager.add_module_net_sink( + mux_module, net, decoder_module, decoder_instance, + decoder_module_addr_port_id, decoder_module_addr_port.pins()[pin_id]); } /* Add module nets to connect data port to MUX mem ports */ - ModulePortId decoder_module_data_port_id = module_manager.find_module_port(decoder_module, generate_mux_local_decoder_data_port_name()); - BasicPort decoder_module_data_port = module_manager.module_port(decoder_module, decoder_module_data_port_id); - + ModulePortId decoder_module_data_port_id = module_manager.find_module_port( + decoder_module, generate_mux_local_decoder_data_port_name()); + BasicPort decoder_module_data_port = + module_manager.module_port(decoder_module, decoder_module_data_port_id); + /* Build pin-to-pin net connection */ for (const size_t& pin : decoder_module_data_port.pins()) { ModuleNetId net = mux_mem_nets[MuxMemId(mem_net_cnt)]; - module_manager.add_module_net_source(mux_module, net, decoder_module, decoder_instance, decoder_module_data_port_id, pin); + module_manager.add_module_net_source(mux_module, net, decoder_module, + decoder_instance, + decoder_module_data_port_id, pin); /* Add the module nets to mux_mem_nets cache */ mem_net_cnt++; } - ModulePortId decoder_module_data_inv_port_id = module_manager.find_module_port(decoder_module, generate_mux_local_decoder_data_inv_port_name()); - BasicPort decoder_module_data_inv_port = module_manager.module_port(decoder_module, decoder_module_data_inv_port_id); + ModulePortId decoder_module_data_inv_port_id = + module_manager.find_module_port( + decoder_module, generate_mux_local_decoder_data_inv_port_name()); + BasicPort decoder_module_data_inv_port = module_manager.module_port( + decoder_module, decoder_module_data_inv_port_id); /* Build pin-to-pin net connection */ for (const size_t& pin : decoder_module_data_inv_port.pins()) { ModuleNetId net = mux_mem_inv_nets[MuxMemId(mem_inv_net_cnt)]; - module_manager.add_module_net_source(mux_module, net, decoder_module, decoder_instance, decoder_module_data_inv_port_id, pin); + module_manager.add_module_net_source( + mux_module, net, decoder_module, decoder_instance, + decoder_module_data_inv_port_id, pin); /* Add the module nets to mux_mem_inv_nets cache */ mem_inv_net_cnt++; } - } + } VTR_ASSERT(mem_net_cnt == mux_graph.num_memory_bits()); VTR_ASSERT(mem_inv_net_cnt == mux_graph.num_memory_bits()); } /********************************************************************* - * Generate module of a CMOS multiplexer with the given size + * Generate module of a CMOS multiplexer with the given size * The module will consist of three parts: - * 1. instances of the branch circuits of multiplexers which are generated before - * This builds up the multiplexing structure + * 1. instances of the branch circuits of multiplexers which are generated + *before This builds up the multiplexing structure * 2. Input buffers/inverters * 3. Output buffers/inverters *********************************************************************/ -static -void build_cmos_mux_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const std::string& module_name, - const MuxGraph& mux_graph) { +static void build_cmos_mux_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const CircuitModelId& mux_model, + const std::string& module_name, + const MuxGraph& mux_graph) { /* Get the global ports required by MUX (and any submodules) */ - std::vector mux_global_ports = circuit_lib.model_global_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector mux_global_ports = + circuit_lib.model_global_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, + true, true); /* Get the input ports from the mux: - * - LUT may have ports that are driven by harden logic, + * - LUT may have ports that are driven by harden logic, * which should not be included when building the mux graph */ std::vector mux_input_ports; if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model)) { - mux_input_ports = find_lut_circuit_model_input_port(circuit_lib, mux_model, false, false); + mux_input_ports = + find_lut_circuit_model_input_port(circuit_lib, mux_model, false, false); } else { - VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)); - mux_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); + VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)); + mux_input_ports = circuit_lib.model_ports_by_type( + mux_model, CIRCUIT_MODEL_PORT_INPUT, true); } /* Get the output ports from the mux: - * - LUT may have ports that are driven by harden logic, + * - LUT may have ports that are driven by harden logic, * which should not be included when building the mux graph - * - LUT may have global output ports that are wired directly to top-level module + * - LUT may have global output ports that are wired directly to top-level + * module */ std::vector mux_output_ports; if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model)) { - mux_output_ports = find_lut_circuit_model_output_port(circuit_lib, mux_model, false, true); + mux_output_ports = + find_lut_circuit_model_output_port(circuit_lib, mux_model, false, true); } else { - VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)); - mux_output_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_OUTPUT, false); + VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)); + mux_output_ports = circuit_lib.model_ports_by_type( + mux_model, CIRCUIT_MODEL_PORT_OUTPUT, false); } - /* Get the sram ports from the mux - * Multiplexing structure does not mode_sram_ports, they are handled in LUT modules - * Here we just bypass it. + /* Get the sram ports from the mux + * Multiplexing structure does not mode_sram_ports, they are handled in LUT + * modules Here we just bypass it. */ - std::vector mux_sram_ports = find_circuit_regular_sram_ports(circuit_lib, mux_model); + std::vector mux_sram_ports = + find_circuit_regular_sram_ports(circuit_lib, mux_model); /* Generate the Verilog netlist according to the mux_graph */ - /* Find out the number of data-path inputs */ - size_t num_inputs = find_mux_num_datapath_inputs(circuit_lib, mux_model, mux_graph.num_inputs()); - /* Find out the number of outputs */ + /* Find out the number of data-path inputs */ + size_t num_inputs = find_mux_num_datapath_inputs(circuit_lib, mux_model, + mux_graph.num_inputs()); + /* Find out the number of outputs */ size_t num_outputs = mux_graph.num_outputs(); - /* Find out the number of memory bits */ + /* Find out the number of memory bits */ size_t num_mems = mux_graph.num_memory_bits(); - /* The size of of memory ports depend on - * if a local encoder is used for the mux or not - * Multiplexer local encoders are applied to memory bits at each stage + /* The size of of memory ports depend on + * if a local encoder is used for the mux or not + * Multiplexer local encoders are applied to memory bits at each stage */ if (true == circuit_lib.mux_use_local_encoder(mux_model)) { num_mems = 0; for (const auto& lvl : mux_graph.levels()) { size_t data_size = mux_graph.num_memory_bits_at_level(lvl); num_mems += find_mux_local_decoder_addr_size(data_size); - } + } } /* Check codes to ensure the port of Verilog netlists will match */ /* MUX graph must have only 1 output */ VTR_ASSERT(1 == mux_input_ports.size()); /* A quick check on the model ports */ - if ((CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)) - || ((CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model)) - && (false == circuit_lib.is_lut_fracturable(mux_model))) ) { + if ((CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)) || + ((CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model)) && + (false == circuit_lib.is_lut_fracturable(mux_model)))) { VTR_ASSERT(1 == mux_output_ports.size()); - VTR_ASSERT(1 == circuit_lib.port_size(mux_output_ports[0])); + VTR_ASSERT(1 == circuit_lib.port_size(mux_output_ports[0])); } else { - VTR_ASSERT_SAFE( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model)) - && (true == circuit_lib.is_lut_fracturable(mux_model)) ); + VTR_ASSERT_SAFE((CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model)) && + (true == circuit_lib.is_lut_fracturable(mux_model))); for (const auto& port : mux_output_ports) { VTR_ASSERT(0 < circuit_lib.port_size(port)); } } - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId mux_module = module_manager.add_module(module_name); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId mux_module = module_manager.add_module(module_name); VTR_ASSERT(ModuleId::INVALID() != mux_module); /* Label module usage */ if (CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)) { module_manager.set_module_usage(mux_module, ModuleManager::MODULE_INTERC); } else { - VTR_ASSERT_SAFE(CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model)); + VTR_ASSERT_SAFE(CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model)); module_manager.set_module_usage(mux_module, ModuleManager::MODULE_LUT); } /* Add module ports */ /* Add each input port - * Treat MUX and LUT differently - * 1. MUXes: we do not have a specific input/output sizes, it is inferred by architecture - * 2. LUTes: we do have specific input/output sizes, + * Treat MUX and LUT differently + * 1. MUXes: we do not have a specific input/output sizes, it is inferred by + * architecture + * 2. LUTes: we do have specific input/output sizes, * but the inputs of MUXes are the SRAM ports of LUTs * and the SRAM ports of MUXes are the inputs of LUTs */ size_t input_port_cnt = 0; for (const auto& port : mux_input_ports) { BasicPort input_port(circuit_lib.port_prefix(port), num_inputs); - module_manager.add_port(mux_module, input_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(mux_module, input_port, + ModuleManager::MODULE_INPUT_PORT); /* Update counter */ input_port_cnt++; } @@ -1216,25 +1428,33 @@ void build_cmos_mux_module(ModuleManager& module_manager, VTR_ASSERT(1 == input_port_cnt); /* Add input buffers and update module nets for inputs */ - vtr::vector mux_input_nets = build_mux_module_input_buffers(module_manager, circuit_lib, mux_module, mux_model, mux_graph); + vtr::vector mux_input_nets = + build_mux_module_input_buffers(module_manager, circuit_lib, mux_module, + mux_model, mux_graph); for (const auto& port : mux_output_ports) { BasicPort output_port(circuit_lib.port_prefix(port), num_outputs); if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model)) { output_port.set_width(circuit_lib.port_size(port)); } - module_manager.add_port(mux_module, output_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(mux_module, output_port, + ModuleManager::MODULE_OUTPUT_PORT); } /* TODO: Add output buffers and update module nets for outputs */ - vtr::vector mux_output_nets = build_mux_module_output_buffers(module_manager, circuit_lib, mux_module, mux_model, mux_graph); + vtr::vector mux_output_nets = + build_mux_module_output_buffers(module_manager, circuit_lib, mux_module, + mux_model, mux_graph); size_t sram_port_cnt = 0; for (const auto& port : mux_sram_ports) { BasicPort mem_port(circuit_lib.port_prefix(port), num_mems); - module_manager.add_port(mux_module, mem_port, ModuleManager::MODULE_INPUT_PORT); - BasicPort mem_inv_port(std::string(circuit_lib.port_prefix(port) + INV_PORT_POSTFIX), num_mems); - module_manager.add_port(mux_module, mem_inv_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(mux_module, mem_port, + ModuleManager::MODULE_INPUT_PORT); + BasicPort mem_inv_port( + std::string(circuit_lib.port_prefix(port) + INV_PORT_POSTFIX), num_mems); + module_manager.add_port(mux_module, mem_inv_port, + ModuleManager::MODULE_INPUT_PORT); /* Update counter */ sram_port_cnt++; } @@ -1243,52 +1463,57 @@ void build_cmos_mux_module(ModuleManager& module_manager, /* Create module nets for mem and mem_inv ports */ vtr::vector mux_mem_nets; vtr::vector mux_mem_inv_nets; - - build_mux_module_local_encoders_and_memory_nets(module_manager, mux_module, - circuit_lib, mux_model, mux_sram_ports, - mux_graph, - mux_mem_nets, mux_mem_inv_nets); - + + build_mux_module_local_encoders_and_memory_nets( + module_manager, mux_module, circuit_lib, mux_model, mux_sram_ports, + mux_graph, mux_mem_nets, mux_mem_inv_nets); + /* Print the internal logic in Verilog codes */ - /* Print the Multiplexing structure in Verilog codes + /* Print the Multiplexing structure in Verilog codes * Separated generation strategy on using standard cell MUX2 or TGATE, - * 1. MUX2 has a fixed port map: input_port[0] and input_port[1] is the data_path input - * 2. Branch TGATE-based module has a fixed port name - * TODO: the naming could be more flexible? + * 1. MUX2 has a fixed port map: input_port[0] and input_port[1] is the + * data_path input + * 2. Branch TGATE-based module has a fixed port name + * TODO: the naming could be more flexible? */ /* Get the tgate model */ CircuitModelId tgate_model = circuit_lib.pass_gate_logic_model(mux_model); - /* Instanciate the branch module: + /* Instanciate the branch module: * Case 1: the branch module is a standard cell MUX2 - * Case 2: the branch module is a tgate-based module + * Case 2: the branch module is a tgate-based module */ std::string branch_module_name; if (CIRCUIT_MODEL_GATE == circuit_lib.model_type(tgate_model)) { VTR_ASSERT(CIRCUIT_MODEL_GATE_MUX2 == circuit_lib.gate_type(tgate_model)); - build_cmos_mux_module_mux2_multiplexing_structure(module_manager, circuit_lib, mux_module, mux_model, tgate_model, mux_input_nets, mux_output_nets, mux_mem_nets, mux_graph); + build_cmos_mux_module_mux2_multiplexing_structure( + module_manager, circuit_lib, mux_module, mux_model, tgate_model, + mux_input_nets, mux_output_nets, mux_mem_nets, mux_graph); } else { VTR_ASSERT(CIRCUIT_MODEL_PASSGATE == circuit_lib.model_type(tgate_model)); - build_cmos_mux_module_tgate_multiplexing_structure(module_manager, circuit_lib, mux_module, mux_model, mux_input_nets, mux_output_nets, mux_mem_nets, mux_mem_inv_nets, mux_graph); + build_cmos_mux_module_tgate_multiplexing_structure( + module_manager, circuit_lib, mux_module, mux_model, mux_input_nets, + mux_output_nets, mux_mem_nets, mux_mem_inv_nets, mux_graph); } /* Add global ports to the pb_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 a list of it + * 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 + * a list of it */ add_module_global_ports_from_child_modules(module_manager, mux_module); } /********************************************************************* - * Generate a module of a RRAM-based multiplexer with the given size + * Generate a module of a RRAM-based multiplexer with the given size * The module will consist of three parts: - * 1. instances of the branch circuits of multiplexers which are generated before - * This builds up the 4T1R-based multiplexing structure + * 1. instances of the branch circuits of multiplexers which are generated + *before This builds up the 4T1R-based multiplexing structure * * BLB WL * | | ... * v v - * +--------+ - * in[0]-->| | BLB WL + * +--------+ + * in[0]-->| | BLB WL * ...| Branch |-----+ | | * in -->| 0 | | v v * [N-1] +--------+ | +--------+ @@ -1305,36 +1530,43 @@ void build_cmos_mux_module(ModuleManager& module_manager, * 2. Input buffers/inverters * 3. Output buffers/inverters *********************************************************************/ -static -void build_rram_mux_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const std::string& module_name, - const MuxGraph& mux_graph) { +static void build_rram_mux_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const std::string& module_name, + const MuxGraph& mux_graph) { /* Error out for the conditions where we are not yet supported! */ if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)) { /* RRAM LUT is not supported now... */ - VTR_LOGF_ERROR(__FILE__, __LINE__, "RRAM-based LUT is not supported for circuit model '%s')!\n", - circuit_lib.model_name(circuit_model).c_str()); + VTR_LOGF_ERROR(__FILE__, __LINE__, + "RRAM-based LUT is not supported for circuit model '%s')!\n", + circuit_lib.model_name(circuit_model).c_str()); exit(1); } /* Get the global ports required by MUX (and any submodules) */ - std::vector mux_global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector mux_global_ports = + circuit_lib.model_global_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); /* Get the input ports from the mux */ - std::vector mux_input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector mux_input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); /* Get the output ports from the mux */ - std::vector mux_output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector mux_output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); /* Get the BL and WL ports from the mux */ - std::vector mux_blb_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_BLB, true); - std::vector mux_wl_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_WL, true); + std::vector mux_blb_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_BLB, true); + std::vector mux_wl_ports = + circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_WL, true); /* Generate the Verilog netlist according to the mux_graph */ - /* Find out the number of data-path inputs */ - size_t num_inputs = find_mux_num_datapath_inputs(circuit_lib, circuit_model, mux_graph.num_inputs()); - /* Find out the number of outputs */ + /* Find out the number of data-path inputs */ + size_t num_inputs = find_mux_num_datapath_inputs(circuit_lib, circuit_model, + mux_graph.num_inputs()); + /* Find out the number of outputs */ size_t num_outputs = mux_graph.num_outputs(); - /* Find out the number of memory bits */ + /* Find out the number of memory bits */ size_t num_mems = mux_graph.num_memory_bits(); /* Check codes to ensure the port of Verilog netlists will match */ @@ -1343,8 +1575,9 @@ void build_rram_mux_module(ModuleManager& module_manager, VTR_ASSERT(1 == mux_blb_ports.size()); VTR_ASSERT(1 == mux_wl_ports.size()); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = module_manager.add_module(module_name); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = module_manager.add_module(module_name); VTR_ASSERT(ModuleId::INVALID() != module_id); /* Label module usage */ @@ -1354,14 +1587,17 @@ void build_rram_mux_module(ModuleManager& module_manager, /* Add each global port */ for (const auto& port : mux_global_ports) { /* Configure each global port */ - BasicPort global_port(circuit_lib.port_prefix(port), circuit_lib.port_size(port)); - module_manager.add_port(module_id, global_port, ModuleManager::MODULE_GLOBAL_PORT); + BasicPort global_port(circuit_lib.port_prefix(port), + circuit_lib.port_size(port)); + module_manager.add_port(module_id, global_port, + ModuleManager::MODULE_GLOBAL_PORT); } /* Add each input port */ size_t input_port_cnt = 0; for (const auto& port : mux_input_ports) { BasicPort input_port(circuit_lib.port_prefix(port), num_inputs); - module_manager.add_port(module_id, input_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(module_id, input_port, + ModuleManager::MODULE_INPUT_PORT); /* Update counter */ input_port_cnt++; } @@ -1373,59 +1609,71 @@ void build_rram_mux_module(ModuleManager& module_manager, if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)) { output_port.set_width(circuit_lib.port_size(port)); } - module_manager.add_port(module_id, output_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(module_id, output_port, + ModuleManager::MODULE_OUTPUT_PORT); } /* BLB port */ for (const auto& port : mux_blb_ports) { - /* IMPORTANT: RRAM-based MUX has an additional BLB pin per level - * So, the actual port width of BLB should be added by the number of levels of the MUX graph + /* IMPORTANT: RRAM-based MUX has an additional BLB pin per level + * So, the actual port width of BLB should be added by the number of levels + * of the MUX graph */ - BasicPort blb_port(circuit_lib.port_prefix(port), num_mems + mux_graph.num_levels()); - module_manager.add_port(module_id, blb_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort blb_port(circuit_lib.port_prefix(port), + num_mems + mux_graph.num_levels()); + module_manager.add_port(module_id, blb_port, + ModuleManager::MODULE_INPUT_PORT); } /* WL port */ for (const auto& port : mux_wl_ports) { - /* IMPORTANT: RRAM-based MUX has an additional WL pin per level - * So, the actual port width of WL should be added by the number of levels of the MUX graph + /* IMPORTANT: RRAM-based MUX has an additional WL pin per level + * So, the actual port width of WL should be added by the number of levels + * of the MUX graph */ - BasicPort wl_port(circuit_lib.port_prefix(port), num_mems + mux_graph.num_levels()); - module_manager.add_port(module_id, wl_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort wl_port(circuit_lib.port_prefix(port), + num_mems + mux_graph.num_levels()); + module_manager.add_port(module_id, wl_port, + ModuleManager::MODULE_INPUT_PORT); } /* TODO: Add the input and output buffers in Verilog codes */ - + /* TODO: Print the internal logic in Verilog codes */ } /*********************************************** - * Generate Verilog codes modeling a multiplexer + * Generate Verilog codes modeling a multiplexer * with the given graph-level description **********************************************/ -static -void build_mux_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const MuxGraph& mux_graph) { - std::string module_name = generate_mux_subckt_name(circuit_lib, circuit_model, - find_mux_num_datapath_inputs(circuit_lib, circuit_model, mux_graph.num_inputs()), - std::string("")); - - /* Multiplexers built with different technology is in different organization */ +static void build_mux_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const MuxGraph& mux_graph) { + std::string module_name = generate_mux_subckt_name( + circuit_lib, circuit_model, + find_mux_num_datapath_inputs(circuit_lib, circuit_model, + mux_graph.num_inputs()), + std::string("")); + + /* Multiplexers built with different technology is in different organization + */ switch (circuit_lib.design_tech_type(circuit_model)) { - case CIRCUIT_MODEL_DESIGN_CMOS: - /* SRAM-based Multiplexer Verilog module generation */ - build_cmos_mux_module(module_manager, circuit_lib, circuit_model, module_name, mux_graph); - break; - case CIRCUIT_MODEL_DESIGN_RRAM: - /* TODO: RRAM-based Multiplexer Verilog module generation */ - build_rram_mux_module(module_manager, circuit_lib, circuit_model, module_name, mux_graph); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid design technology of multiplexer '%s'\n", - circuit_lib.model_name(circuit_model).c_str()); - exit(1); + case CIRCUIT_MODEL_DESIGN_CMOS: + /* SRAM-based Multiplexer Verilog module generation */ + build_cmos_mux_module(module_manager, circuit_lib, circuit_model, + module_name, mux_graph); + break; + case CIRCUIT_MODEL_DESIGN_RRAM: + /* TODO: RRAM-based Multiplexer Verilog module generation */ + build_rram_mux_module(module_manager, circuit_lib, circuit_model, + module_name, mux_graph); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid design technology of multiplexer '%s'\n", + circuit_lib.model_name(circuit_model).c_str()); + exit(1); } } @@ -1433,20 +1681,21 @@ void build_mux_module(ModuleManager& module_manager, * Generate Verilog modules for all the unique * multiplexers in the FPGA device **********************************************/ -void build_mux_modules(ModuleManager& module_manager, - const MuxLibrary& mux_lib, +void build_mux_modules(ModuleManager& module_manager, const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib) { vtr::ScopedStartFinishTimer timer("Building multiplexer modules"); - /* Generate basis sub-circuit for unique branches shared by the multiplexers */ + /* Generate basis sub-circuit for unique branches shared by the multiplexers + */ for (auto mux : mux_lib.muxes()) { const MuxGraph& mux_graph = mux_lib.mux_graph(mux); - CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); + CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); /* Create a mux graph for the branch circuit */ - std::vector branch_mux_graphs = mux_graph.build_mux_branch_graphs(); + std::vector branch_mux_graphs = + mux_graph.build_mux_branch_graphs(); /* Create branch circuits, which are N:1 one-level or 2:1 tree-like MUXes */ for (auto branch_mux_graph : branch_mux_graphs) { - build_mux_branch_module(module_manager, circuit_lib, mux_circuit_model, + build_mux_branch_module(module_manager, circuit_lib, mux_circuit_model, branch_mux_graph); } } @@ -1454,7 +1703,7 @@ void build_mux_modules(ModuleManager& module_manager, /* Generate unique Verilog modules for the multiplexers */ for (auto mux : mux_lib.muxes()) { const MuxGraph& mux_graph = mux_lib.mux_graph(mux); - CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); + CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); /* Create MUX circuits */ build_mux_module(module_manager, circuit_lib, mux_circuit_model, mux_graph); } diff --git a/openfpga/src/fabric/build_mux_modules.h b/openfpga/src/fabric/build_mux_modules.h index 8326eeb74..6544af3f4 100644 --- a/openfpga/src/fabric/build_mux_modules.h +++ b/openfpga/src/fabric/build_mux_modules.h @@ -5,8 +5,8 @@ * Include header files that are required by function declaration *******************************************************************/ #include "circuit_library.h" -#include "mux_library.h" #include "module_manager.h" +#include "mux_library.h" /******************************************************************** * Function declaration @@ -15,8 +15,7 @@ /* begin namespace openfpga */ namespace openfpga { -void build_mux_modules(ModuleManager& module_manager, - const MuxLibrary& mux_lib, +void build_mux_modules(ModuleManager& module_manager, const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_routing_module_utils.cpp b/openfpga/src/fabric/build_routing_module_utils.cpp index 9da256ba5..9ecef274d 100644 --- a/openfpga/src/fabric/build_routing_module_utils.cpp +++ b/openfpga/src/fabric/build_routing_module_utils.cpp @@ -1,20 +1,19 @@ /******************************************************************** - * This file includes most utilized functions that are used to build modules + * This file includes most utilized functions that are used to build modules * for global routing architecture of a FPGA fabric * Covering: * 1. Connection blocks * 2. Switch blocks *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" -#include "vtr_assert.h" -#include "vtr_geometry.h" +#include "build_routing_module_utils.h" -#include "openfpga_side_manager.h" #include "openfpga_naming.h" #include "openfpga_rr_graph_utils.h" - -#include "build_routing_module_utils.h" +#include "openfpga_side_manager.h" +#include "vtr_assert.h" +#include "vtr_geometry.h" +#include "vtr_log.h" /* begin namespace openfpga */ namespace openfpga { @@ -23,9 +22,10 @@ namespace openfpga { * Generate the port name of a grid pin for a routing module, * which could be a switch block or a connection block * Note that to ensure unique grid port name in the context of a routing module, - * we need a prefix which denotes the relative location of the port in the routing module + * we need a prefix which denotes the relative location of the port in the + *routing module * - * The prefix is created by considering the the grid coordinate + * The prefix is created by considering the the grid coordinate * and switch block coordinate * Detailed rules in conversion is as follows: * @@ -41,7 +41,7 @@ namespace openfpga { * bottom_left bottom_right * * +-------------------------------------------------------- - * | Grid Coordinate | Pin side of grid | module side + * | Grid Coordinate | Pin side of grid | module side * +-------------------------------------------------------- * | [x][y+1] | right | top_left * +-------------------------------------------------------- @@ -61,86 +61,98 @@ namespace openfpga { * +-------------------------------------------------------- * *********************************************************************/ -std::string generate_sb_module_grid_port_name(const e_side& sb_side, - const e_side& grid_side, - const DeviceGrid& vpr_device_grid, - const VprDeviceAnnotation& vpr_device_annotation, - const RRGraphView& rr_graph, - const RRNodeId& rr_node) { +std::string generate_sb_module_grid_port_name( + const e_side& sb_side, const e_side& grid_side, + const DeviceGrid& vpr_device_grid, + const VprDeviceAnnotation& vpr_device_annotation, const RRGraphView& rr_graph, + const RRNodeId& rr_node) { SideManager sb_side_manager(sb_side); SideManager grid_side_manager(grid_side); /* Relative location is opposite to the side in grid context */ grid_side_manager.set_opposite(); - std::string prefix = sb_side_manager.to_string() + std::string("_") + grid_side_manager.to_string(); + std::string prefix = sb_side_manager.to_string() + std::string("_") + + grid_side_manager.to_string(); /* Collect the attributes of the rr_node required to generate the port name */ int pin_id = rr_graph.node_pin_num(rr_node); e_side pin_side = get_rr_graph_single_node_side(rr_graph, rr_node); - t_physical_tile_type_ptr physical_tile = vpr_device_grid[rr_graph.node_xlow(rr_node)][rr_graph.node_ylow(rr_node)].type; - int pin_width_offset = physical_tile->pin_width_offset[pin_id]; - int pin_height_offset = physical_tile->pin_height_offset[pin_id]; - BasicPort pin_info = vpr_device_annotation.physical_tile_pin_port_info(physical_tile, pin_id); + t_physical_tile_type_ptr physical_tile = + vpr_device_grid[rr_graph.node_xlow(rr_node)][rr_graph.node_ylow(rr_node)] + .type; + int pin_width_offset = physical_tile->pin_width_offset[pin_id]; + int pin_height_offset = physical_tile->pin_height_offset[pin_id]; + BasicPort pin_info = + vpr_device_annotation.physical_tile_pin_port_info(physical_tile, pin_id); VTR_ASSERT(true == pin_info.is_valid()); - int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(physical_tile, pin_id); + int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index( + physical_tile, pin_id); VTR_ASSERT(OPEN != subtile_index && subtile_index < physical_tile->capacity); - return prefix + std::string("_") + generate_routing_module_grid_port_name(pin_width_offset, pin_height_offset, subtile_index, pin_side, pin_info); + return prefix + std::string("_") + + generate_routing_module_grid_port_name( + pin_width_offset, pin_height_offset, subtile_index, pin_side, + pin_info); } /********************************************************************* * Generate the port name of a grid pin for a routing module, * which could be a switch block or a connection block * Note that to ensure unique grid port name in the context of a routing module, - * we need a prefix which denotes the relative location of the port in the routing module + * we need a prefix which denotes the relative location of the port in the + *routing module *********************************************************************/ -std::string generate_cb_module_grid_port_name(const e_side& cb_side, - const DeviceGrid& vpr_device_grid, - const VprDeviceAnnotation& vpr_device_annotation, - const RRGraphView& rr_graph, - const RRNodeId& rr_node) { - +std::string generate_cb_module_grid_port_name( + const e_side& cb_side, const DeviceGrid& vpr_device_grid, + const VprDeviceAnnotation& vpr_device_annotation, const RRGraphView& rr_graph, + const RRNodeId& rr_node) { SideManager side_manager(cb_side); std::string prefix = side_manager.to_string(); /* Collect the attributes of the rr_node required to generate the port name */ int pin_id = rr_graph.node_pin_num(rr_node); e_side pin_side = get_rr_graph_single_node_side(rr_graph, rr_node); - t_physical_tile_type_ptr physical_tile = vpr_device_grid[rr_graph.node_xlow(rr_node)][rr_graph.node_ylow(rr_node)].type; - int pin_width_offset = physical_tile->pin_width_offset[pin_id]; - int pin_height_offset = physical_tile->pin_height_offset[pin_id]; - BasicPort pin_info = vpr_device_annotation.physical_tile_pin_port_info(physical_tile, pin_id); + t_physical_tile_type_ptr physical_tile = + vpr_device_grid[rr_graph.node_xlow(rr_node)][rr_graph.node_ylow(rr_node)] + .type; + int pin_width_offset = physical_tile->pin_width_offset[pin_id]; + int pin_height_offset = physical_tile->pin_height_offset[pin_id]; + BasicPort pin_info = + vpr_device_annotation.physical_tile_pin_port_info(physical_tile, pin_id); VTR_ASSERT(true == pin_info.is_valid()); - int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(physical_tile, pin_id); + int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index( + physical_tile, pin_id); VTR_ASSERT(OPEN != subtile_index && subtile_index < physical_tile->capacity); - return prefix + std::string("_") + generate_routing_module_grid_port_name(pin_width_offset, pin_height_offset, subtile_index, pin_side, pin_info); + return prefix + std::string("_") + + generate_routing_module_grid_port_name( + pin_width_offset, pin_height_offset, subtile_index, pin_side, + pin_info); } - /********************************************************************* - * Find the port id and pin id for a routing track in the switch + * Find the port id and pin id for a routing track in the switch * block module with a given rr_node ********************************************************************/ -ModulePinInfo find_switch_block_module_chan_port(const ModuleManager& module_manager, - const ModuleId& sb_module, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const e_side& chan_side, - const RRNodeId& cur_rr_node, - const PORTS& cur_rr_node_direction) { +ModulePinInfo find_switch_block_module_chan_port( + const ModuleManager& module_manager, const ModuleId& sb_module, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, const e_side& chan_side, + const RRNodeId& cur_rr_node, const PORTS& cur_rr_node_direction) { /* Get the index in sb_info of cur_rr_node */ - int index = rr_gsb.get_node_index(rr_graph, cur_rr_node, chan_side, cur_rr_node_direction); + int index = rr_gsb.get_node_index(rr_graph, cur_rr_node, chan_side, + cur_rr_node_direction); /* Make sure this node is included in this sb_info */ VTR_ASSERT((-1 != index) && (NUM_SIDES != chan_side)); - std::string chan_port_name = generate_sb_module_track_port_name(rr_graph.node_type(rr_gsb.get_chan_node(chan_side, index)), - chan_side, - rr_gsb.get_chan_node_direction(chan_side, index)); - + std::string chan_port_name = generate_sb_module_track_port_name( + rr_graph.node_type(rr_gsb.get_chan_node(chan_side, index)), chan_side, + rr_gsb.get_chan_node_direction(chan_side, index)); + /* Must find a valid port id in the Switch Block module */ - ModulePortId chan_port_id = module_manager.find_module_port(sb_module, chan_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(sb_module, chan_port_id)); - return ModulePinInfo(chan_port_id, index / 2); + ModulePortId chan_port_id = + module_manager.find_module_port(sb_module, chan_port_name); + VTR_ASSERT(true == + module_manager.valid_module_port_id(sb_module, chan_port_id)); + return ModulePinInfo(chan_port_id, index / 2); } /********************************************************************* @@ -162,63 +174,61 @@ ModulePinInfo find_switch_block_module_chan_port(const ModuleManager& module_man * 2. When the input is a routing track, the input_side should be * the side of the node locating on the switch block ********************************************************************/ -ModulePinInfo find_switch_block_module_input_port(const ModuleManager& module_manager, - const ModuleId& sb_module, - const DeviceGrid& grids, - const VprDeviceAnnotation& vpr_device_annotation, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const e_side& input_side, - const RRNodeId& input_rr_node) { +ModulePinInfo find_switch_block_module_input_port( + const ModuleManager& module_manager, const ModuleId& sb_module, + const DeviceGrid& grids, const VprDeviceAnnotation& vpr_device_annotation, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, const e_side& input_side, + const RRNodeId& input_rr_node) { /* Deposit an invalid value */ ModulePinInfo input_port(ModulePortId::INVALID(), 0); /* Generate the input port object */ switch (rr_graph.node_type(input_rr_node)) { - /* case SOURCE: */ - case OPIN: { - /* Find the coordinator (grid_x and grid_y) for the input port */ - vtr::Point input_port_coord(rr_graph.node_xlow(input_rr_node), - rr_graph.node_ylow(input_rr_node)); + /* case SOURCE: */ + case OPIN: { + /* Find the coordinator (grid_x and grid_y) for the input port */ + vtr::Point input_port_coord(rr_graph.node_xlow(input_rr_node), + rr_graph.node_ylow(input_rr_node)); - /* Find the side where the grid pin locates in the grid */ - enum e_side grid_pin_side = get_rr_graph_single_node_side(rr_graph, input_rr_node); - VTR_ASSERT(NUM_SIDES != grid_pin_side); + /* Find the side where the grid pin locates in the grid */ + enum e_side grid_pin_side = + get_rr_graph_single_node_side(rr_graph, input_rr_node); + VTR_ASSERT(NUM_SIDES != grid_pin_side); - std::string input_port_name = generate_sb_module_grid_port_name(input_side, - grid_pin_side, - grids, - vpr_device_annotation, - rr_graph, - input_rr_node); - /* Must find a valid port id in the Switch Block module */ - input_port.first = module_manager.find_module_port(sb_module, input_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(sb_module, input_port.first)); - break; - } - case CHANX: - case CHANY: { - input_port = find_switch_block_module_chan_port(module_manager, sb_module, rr_graph, - rr_gsb, input_side, input_rr_node, IN_PORT); - break; - } - default: /* SOURCE, IPIN, SINK are invalid*/ - VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid rr_node type! Should be [OPIN|CHANX|CHANY].\n"); - exit(1); + std::string input_port_name = generate_sb_module_grid_port_name( + input_side, grid_pin_side, grids, vpr_device_annotation, rr_graph, + input_rr_node); + /* Must find a valid port id in the Switch Block module */ + input_port.first = + module_manager.find_module_port(sb_module, input_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(sb_module, + input_port.first)); + break; + } + case CHANX: + case CHANY: { + input_port = find_switch_block_module_chan_port( + module_manager, sb_module, rr_graph, rr_gsb, input_side, input_rr_node, + IN_PORT); + break; + } + default: /* SOURCE, IPIN, SINK are invalid*/ + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid rr_node type! Should be [OPIN|CHANX|CHANY].\n"); + exit(1); } - return input_port; + return input_port; } /********************************************************************* - * Generate a list of input ports for routing multiplexer inside the switch block + * Generate a list of input ports for routing multiplexer inside the switch + *block ********************************************************************/ -std::vector find_switch_block_module_input_ports(const ModuleManager& module_manager, - const ModuleId& sb_module, - const DeviceGrid& grids, - const VprDeviceAnnotation& vpr_device_annotation, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const std::vector& input_rr_nodes) { +std::vector find_switch_block_module_input_ports( + const ModuleManager& module_manager, const ModuleId& sb_module, + const DeviceGrid& grids, const VprDeviceAnnotation& vpr_device_annotation, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, + const std::vector& input_rr_nodes) { std::vector input_ports; for (const RRNodeId& input_rr_node : input_rr_nodes) { @@ -226,11 +236,14 @@ std::vector find_switch_block_module_input_ports(const ModuleMana enum e_side input_pin_side = NUM_SIDES; /* The input could be at any side of the switch block, find it */ int index = -1; - rr_gsb.get_node_side_and_index(rr_graph, input_rr_node, IN_PORT, input_pin_side, index); + rr_gsb.get_node_side_and_index(rr_graph, input_rr_node, IN_PORT, + input_pin_side, index); VTR_ASSERT(NUM_SIDES != input_pin_side); VTR_ASSERT(-1 != index); - input_ports.push_back(find_switch_block_module_input_port(module_manager, sb_module, grids, vpr_device_annotation, rr_graph, rr_gsb, input_pin_side, input_rr_node)); + input_ports.push_back(find_switch_block_module_input_port( + module_manager, sb_module, grids, vpr_device_annotation, rr_graph, rr_gsb, + input_pin_side, input_rr_node)); } return input_ports; @@ -238,34 +251,35 @@ std::vector find_switch_block_module_input_ports(const ModuleMana /********************************************************************* * Generate an input port for routing multiplexer inside the connection block - * which is the middle output of a routing track + * which is the middle output of a routing track ********************************************************************/ -ModulePinInfo find_connection_block_module_chan_port(const ModuleManager& module_manager, - const ModuleId& cb_module, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const t_rr_type& cb_type, - const RRNodeId& chan_rr_node) { +ModulePinInfo find_connection_block_module_chan_port( + const ModuleManager& module_manager, const ModuleId& cb_module, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type, + const RRNodeId& chan_rr_node) { ModulePinInfo input_port_info; /* Generate the input port object */ switch (rr_graph.node_type(chan_rr_node)) { - case CHANX: - case CHANY: { - /* Create port description for the routing track middle output */ - int chan_node_track_id = rr_gsb.get_cb_chan_node_index(cb_type, chan_rr_node); - /* Create a port description for the middle output */ - std::string input_port_name = generate_cb_module_track_port_name(cb_type, - IN_PORT, - 0 == chan_node_track_id % 2); - /* Must find a valid port id in the Switch Block module */ - input_port_info.first = module_manager.find_module_port(cb_module, input_port_name); - input_port_info.second = chan_node_track_id / 2; - VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module, input_port_info.first)); - break; - } - default: /* OPIN, SOURCE, IPIN, SINK are invalid*/ - VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid rr_node type! Should be [OPIN|CHANX|CHANY].\n"); - exit(1); + case CHANX: + case CHANY: { + /* Create port description for the routing track middle output */ + int chan_node_track_id = + rr_gsb.get_cb_chan_node_index(cb_type, chan_rr_node); + /* Create a port description for the middle output */ + std::string input_port_name = generate_cb_module_track_port_name( + cb_type, IN_PORT, 0 == chan_node_track_id % 2); + /* Must find a valid port id in the Switch Block module */ + input_port_info.first = + module_manager.find_module_port(cb_module, input_port_name); + input_port_info.second = chan_node_track_id / 2; + VTR_ASSERT(true == module_manager.valid_module_port_id( + cb_module, input_port_info.first)); + break; + } + default: /* OPIN, SOURCE, IPIN, SINK are invalid*/ + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid rr_node type! Should be [OPIN|CHANX|CHANY].\n"); + exit(1); } return input_port_info; @@ -274,50 +288,49 @@ ModulePinInfo find_connection_block_module_chan_port(const ModuleManager& module /********************************************************************* * Generate a port for a routing track of a swtich block ********************************************************************/ -ModulePortId find_connection_block_module_ipin_port(const ModuleManager& module_manager, - const ModuleId& cb_module, - const DeviceGrid& grids, - const VprDeviceAnnotation& vpr_device_annotation, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const RRNodeId& src_rr_node) { - +ModulePortId find_connection_block_module_ipin_port( + const ModuleManager& module_manager, const ModuleId& cb_module, + const DeviceGrid& grids, const VprDeviceAnnotation& vpr_device_annotation, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, + const RRNodeId& src_rr_node) { /* Ensure the src_rr_node is an input pin of a CLB */ VTR_ASSERT(IPIN == rr_graph.node_type(src_rr_node)); /* Create port description for input pin of a CLB */ - vtr::Point port_coord(rr_graph.node_xlow(src_rr_node), rr_graph.node_ylow(src_rr_node)); - /* Search all the sides of a SB, see this drive_rr_node is an INPUT of this SB */ + vtr::Point port_coord(rr_graph.node_xlow(src_rr_node), + rr_graph.node_ylow(src_rr_node)); + /* Search all the sides of a SB, see this drive_rr_node is an INPUT of this SB + */ enum e_side cb_ipin_side = NUM_SIDES; int cb_ipin_index = -1; - rr_gsb.get_node_side_and_index(rr_graph, src_rr_node, OUT_PORT, cb_ipin_side, cb_ipin_index); + rr_gsb.get_node_side_and_index(rr_graph, src_rr_node, OUT_PORT, cb_ipin_side, + cb_ipin_index); /* We need to be sure that drive_rr_node is part of the CB */ - VTR_ASSERT((-1 != cb_ipin_index)&&(NUM_SIDES != cb_ipin_side)); - std::string port_name = generate_cb_module_grid_port_name(cb_ipin_side, - grids, - vpr_device_annotation, - rr_graph, - rr_gsb.get_ipin_node(cb_ipin_side, cb_ipin_index)); + VTR_ASSERT((-1 != cb_ipin_index) && (NUM_SIDES != cb_ipin_side)); + std::string port_name = generate_cb_module_grid_port_name( + cb_ipin_side, grids, vpr_device_annotation, rr_graph, + rr_gsb.get_ipin_node(cb_ipin_side, cb_ipin_index)); /* Must find a valid port id in the Switch Block module */ - ModulePortId ipin_port_id = module_manager.find_module_port(cb_module, port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module, ipin_port_id)); + ModulePortId ipin_port_id = + module_manager.find_module_port(cb_module, port_name); + VTR_ASSERT(true == + module_manager.valid_module_port_id(cb_module, ipin_port_id)); return ipin_port_id; } /********************************************************************* - * Generate a list of routing track middle output ports + * Generate a list of routing track middle output ports * for routing multiplexer inside the connection block ********************************************************************/ -std::vector find_connection_block_module_input_ports(const ModuleManager& module_manager, - const ModuleId& cb_module, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const t_rr_type& cb_type, - const std::vector& input_rr_nodes) { +std::vector find_connection_block_module_input_ports( + const ModuleManager& module_manager, const ModuleId& cb_module, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type, + const std::vector& input_rr_nodes) { std::vector input_ports; for (auto input_rr_node : input_rr_nodes) { - input_ports.push_back(find_connection_block_module_chan_port(module_manager, cb_module, rr_graph, rr_gsb, cb_type, input_rr_node)); + input_ports.push_back(find_connection_block_module_chan_port( + module_manager, cb_module, rr_graph, rr_gsb, cb_type, input_rr_node)); } return input_ports; diff --git a/openfpga/src/fabric/build_routing_module_utils.h b/openfpga/src/fabric/build_routing_module_utils.h index 69ea6937f..8c3907dfa 100644 --- a/openfpga/src/fabric/build_routing_module_utils.h +++ b/openfpga/src/fabric/build_routing_module_utils.h @@ -5,13 +5,14 @@ * Include header files that are required by function declaration *******************************************************************/ -#include #include -#include "rr_gsb.h" -#include "module_manager.h" -#include "vpr_types.h" +#include + #include "device_grid.h" +#include "module_manager.h" +#include "rr_gsb.h" #include "vpr_device_annotation.h" +#include "vpr_types.h" /******************************************************************** * Function declaration @@ -22,65 +23,49 @@ namespace openfpga { typedef std::pair ModulePinInfo; -std::string generate_sb_module_grid_port_name(const e_side& sb_side, - const e_side& grid_side, - const DeviceGrid& vpr_device_grid, - const VprDeviceAnnotation& vpr_device_annotation, - const RRGraphView& rr_graph, - const RRNodeId& rr_node); +std::string generate_sb_module_grid_port_name( + const e_side& sb_side, const e_side& grid_side, + const DeviceGrid& vpr_device_grid, + const VprDeviceAnnotation& vpr_device_annotation, const RRGraphView& rr_graph, + const RRNodeId& rr_node); -std::string generate_cb_module_grid_port_name(const e_side& cb_side, - const DeviceGrid& vpr_device_grid, - const VprDeviceAnnotation& vpr_device_annotation, - const RRGraphView& rr_graph, - const RRNodeId& rr_node); +std::string generate_cb_module_grid_port_name( + const e_side& cb_side, const DeviceGrid& vpr_device_grid, + const VprDeviceAnnotation& vpr_device_annotation, const RRGraphView& rr_graph, + const RRNodeId& rr_node); -ModulePinInfo find_switch_block_module_chan_port(const ModuleManager& module_manager, - const ModuleId& sb_module, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const e_side& chan_side, - const RRNodeId& cur_rr_node, - const PORTS& cur_rr_node_direction); +ModulePinInfo find_switch_block_module_chan_port( + const ModuleManager& module_manager, const ModuleId& sb_module, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, const e_side& chan_side, + const RRNodeId& cur_rr_node, const PORTS& cur_rr_node_direction); -ModulePinInfo find_switch_block_module_input_port(const ModuleManager& module_manager, - const ModuleId& sb_module, - const DeviceGrid& grids, - const VprDeviceAnnotation& vpr_device_annotation, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const e_side& input_side, - const RRNodeId& input_rr_node); +ModulePinInfo find_switch_block_module_input_port( + const ModuleManager& module_manager, const ModuleId& sb_module, + const DeviceGrid& grids, const VprDeviceAnnotation& vpr_device_annotation, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, const e_side& input_side, + const RRNodeId& input_rr_node); -std::vector find_switch_block_module_input_ports(const ModuleManager& module_manager, - const ModuleId& sb_module, - const DeviceGrid& grids, - const VprDeviceAnnotation& vpr_device_annotation, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const std::vector& input_rr_nodes); +std::vector find_switch_block_module_input_ports( + const ModuleManager& module_manager, const ModuleId& sb_module, + const DeviceGrid& grids, const VprDeviceAnnotation& vpr_device_annotation, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, + const std::vector& input_rr_nodes); -ModulePinInfo find_connection_block_module_chan_port(const ModuleManager& module_manager, - const ModuleId& cb_module, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const t_rr_type& cb_type, - const RRNodeId& chan_rr_node); +ModulePinInfo find_connection_block_module_chan_port( + const ModuleManager& module_manager, const ModuleId& cb_module, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type, + const RRNodeId& chan_rr_node); -ModulePortId find_connection_block_module_ipin_port(const ModuleManager& module_manager, - const ModuleId& cb_module, - const DeviceGrid& grids, - const VprDeviceAnnotation& vpr_device_annotation, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const RRNodeId& src_rr_node); +ModulePortId find_connection_block_module_ipin_port( + const ModuleManager& module_manager, const ModuleId& cb_module, + const DeviceGrid& grids, const VprDeviceAnnotation& vpr_device_annotation, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, + const RRNodeId& src_rr_node); -std::vector find_connection_block_module_input_ports(const ModuleManager& module_manager, - const ModuleId& cb_module, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const t_rr_type& cb_type, - const std::vector& input_rr_nodes); +std::vector find_connection_block_module_input_ports( + const ModuleManager& module_manager, const ModuleId& cb_module, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type, + const std::vector& input_rr_nodes); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_routing_modules.cpp b/openfpga/src/fabric/build_routing_modules.cpp index f16ca7273..5e69721cb 100644 --- a/openfpga/src/fabric/build_routing_modules.cpp +++ b/openfpga/src/fabric/build_routing_modules.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * This file includes functions that are used to build modules + * This file includes functions that are used to build modules * for global routing architecture of a FPGA fabric * Covering: * 1. Connection blocks @@ -14,18 +14,15 @@ #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_side_manager.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" - -#include "rr_gsb_utils.h" -#include "openfpga_rr_graph_utils.h" -#include "module_manager_utils.h" #include "build_module_graph_utils.h" #include "build_routing_module_utils.h" - #include "build_routing_modules.h" +#include "module_manager_utils.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "openfpga_rr_graph_utils.h" +#include "openfpga_side_manager.h" +#include "rr_gsb_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -34,121 +31,133 @@ namespace openfpga { * Generate a short interconneciton in switch box * There are two cases should be noticed. * 1. The actual fan-in of cur_rr_node is 0. In this case, - the cur_rr_node need to be short connected to itself + the cur_rr_node need to be short connected to itself which is on the opposite side of this switch block * 2. The actual fan-in of cur_rr_node is 0. In this case, * The cur_rr_node need to connected to the drive_rr_node ********************************************************************/ -static -void build_switch_block_module_short_interc(ModuleManager& module_manager, - const ModuleId& sb_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const e_side& chan_side, - const RRNodeId& cur_rr_node, - const RRNodeId& drive_rr_node, - const std::map& input_port_to_module_nets) { +static void build_switch_block_module_short_interc( + ModuleManager& module_manager, const ModuleId& sb_module, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, const e_side& chan_side, + const RRNodeId& cur_rr_node, const RRNodeId& drive_rr_node, + const std::map& input_port_to_module_nets) { /* Find the name of output port */ - ModulePinInfo output_port_info = find_switch_block_module_chan_port(module_manager, sb_module, - rr_graph, rr_gsb, - chan_side, cur_rr_node, OUT_PORT); + ModulePinInfo output_port_info = find_switch_block_module_chan_port( + module_manager, sb_module, rr_graph, rr_gsb, chan_side, cur_rr_node, + OUT_PORT); enum e_side input_pin_side = chan_side; int index = -1; /* Generate the input port object */ switch (rr_graph.node_type(drive_rr_node)) { - case OPIN: { - rr_gsb.get_node_side_and_index(rr_graph, drive_rr_node, IN_PORT, input_pin_side, index); - break; - } - case CHANX: - case CHANY: { - /* This should be an input in the data structure of RRGSB */ - if (cur_rr_node == drive_rr_node) { - /* To be strict, the input should locate on the opposite side. - * Use the else part if this may change in some architecture. - */ - SideManager side_manager(chan_side); - input_pin_side = side_manager.get_opposite(); - } else { - /* The input could be at any side of the switch block, find it */ - rr_gsb.get_node_side_and_index(rr_graph, drive_rr_node, IN_PORT, input_pin_side, index); + case OPIN: { + rr_gsb.get_node_side_and_index(rr_graph, drive_rr_node, IN_PORT, + input_pin_side, index); + break; } - break; - } - default: /* SOURCE, IPIN, SINK are invalid*/ - VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid rr_node type! Should be [OPIN|CHANX|CHANY].\n"); - exit(1); + case CHANX: + case CHANY: { + /* This should be an input in the data structure of RRGSB */ + if (cur_rr_node == drive_rr_node) { + /* To be strict, the input should locate on the opposite side. + * Use the else part if this may change in some architecture. + */ + SideManager side_manager(chan_side); + input_pin_side = side_manager.get_opposite(); + } else { + /* The input could be at any side of the switch block, find it */ + rr_gsb.get_node_side_and_index(rr_graph, drive_rr_node, IN_PORT, + input_pin_side, index); + } + break; + } + default: /* SOURCE, IPIN, SINK are invalid*/ + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid rr_node type! Should be [OPIN|CHANX|CHANY].\n"); + exit(1); } /* Find the name of input port */ - ModulePinInfo input_port_info = find_switch_block_module_input_port(module_manager, sb_module, grids, device_annotation, rr_graph, rr_gsb, input_pin_side, drive_rr_node); + ModulePinInfo input_port_info = find_switch_block_module_input_port( + module_manager, sb_module, grids, device_annotation, rr_graph, rr_gsb, + input_pin_side, drive_rr_node); /* The input port and output port must match in size */ - BasicPort input_port = module_manager.module_port(sb_module, input_port_info.first); - BasicPort output_port = module_manager.module_port(sb_module, output_port_info.first); - + BasicPort input_port = + module_manager.module_port(sb_module, input_port_info.first); + BasicPort output_port = + module_manager.module_port(sb_module, output_port_info.first); + /* Create a module net for this short-wire connection */ ModuleNetId net = input_port_to_module_nets.at(input_port_info); /* Skip Configuring the net source, it is done before */ /* Configure the net sink */ - module_manager.add_module_net_sink(sb_module, net, sb_module, 0, output_port_info.first, output_port_info.second); + module_manager.add_module_net_sink(sb_module, net, sb_module, 0, + output_port_info.first, + output_port_info.second); } /********************************************************************* * Build a instance of a routing multiplexer as well as * associated memory modules for a connection inside a switch block ********************************************************************/ -static -void build_switch_block_mux_module(ModuleManager& module_manager, - const ModuleId& sb_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const CircuitLibrary& circuit_lib, - const e_side& chan_side, - const size_t& chan_node_id, - const RRNodeId& cur_rr_node, - const std::vector& driver_rr_nodes, - const RRSwitchId& switch_index, - const std::map& input_port_to_module_nets) { +static void build_switch_block_mux_module( + ModuleManager& module_manager, const ModuleId& sb_module, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, + const CircuitLibrary& circuit_lib, const e_side& chan_side, + const size_t& chan_node_id, const RRNodeId& cur_rr_node, + const std::vector& driver_rr_nodes, const RRSwitchId& switch_index, + const std::map& input_port_to_module_nets) { /* Check current rr_node is CHANX or CHANY*/ - VTR_ASSERT((CHANX == rr_graph.node_type(cur_rr_node)) || (CHANY == rr_graph.node_type(cur_rr_node))); + VTR_ASSERT((CHANX == rr_graph.node_type(cur_rr_node)) || + (CHANY == rr_graph.node_type(cur_rr_node))); /* Get the circuit model id of the routing multiplexer */ - CircuitModelId mux_model = device_annotation.rr_switch_circuit_model(switch_index); + CircuitModelId mux_model = + device_annotation.rr_switch_circuit_model(switch_index); /* Find the input size of the implementation of a routing multiplexer */ size_t datapath_mux_size = driver_rr_nodes.size(); - /* Find the module name of the multiplexer and try to find it in the module manager */ - std::string mux_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string("")); + /* Find the module name of the multiplexer and try to find it in the module + * manager */ + std::string mux_module_name = generate_mux_subckt_name( + circuit_lib, mux_model, datapath_mux_size, std::string("")); ModuleId mux_module = module_manager.find_module(mux_module_name); - VTR_ASSERT (true == module_manager.valid_module_id(mux_module)); + VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); /* Get the MUX instance id from the module manager */ size_t mux_instance_id = module_manager.num_instance(sb_module, mux_module); /* Instanciate the MUX Module */ module_manager.add_child_module(sb_module, mux_module); - /* Give an instance name: this name should be consistent with the block name given in SDC manager, - * If you want to bind the SDC generation to modules + /* Give an instance name: this name should be consistent with the block name + * given in SDC manager, If you want to bind the SDC generation to modules */ - std::string mux_instance_name = generate_sb_memory_instance_name(SWITCH_BLOCK_MUX_INSTANCE_PREFIX, chan_side, chan_node_id, std::string("")); - module_manager.set_child_instance_name(sb_module, mux_module, mux_instance_id, mux_instance_name); + std::string mux_instance_name = generate_sb_memory_instance_name( + SWITCH_BLOCK_MUX_INSTANCE_PREFIX, chan_side, chan_node_id, std::string("")); + module_manager.set_child_instance_name(sb_module, mux_module, mux_instance_id, + mux_instance_name); - /* Generate input ports that are wired to the input bus of the routing multiplexer */ - std::vector sb_input_port_ids = find_switch_block_module_input_ports(module_manager, sb_module, grids, device_annotation, rr_graph, rr_gsb, driver_rr_nodes); + /* Generate input ports that are wired to the input bus of the routing + * multiplexer */ + std::vector sb_input_port_ids = + find_switch_block_module_input_ports(module_manager, sb_module, grids, + device_annotation, rr_graph, rr_gsb, + driver_rr_nodes); /* Link input bus port to Switch Block inputs */ - std::vector mux_model_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector mux_model_input_ports = + circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); VTR_ASSERT(1 == mux_model_input_ports.size()); /* Find the module port id of the input port */ - ModulePortId mux_input_port_id = module_manager.find_module_port(mux_module, circuit_lib.port_prefix(mux_model_input_ports[0])); - VTR_ASSERT(true == module_manager.valid_module_port_id(mux_module, mux_input_port_id)); - BasicPort mux_input_port = module_manager.module_port(mux_module, mux_input_port_id); + ModulePortId mux_input_port_id = module_manager.find_module_port( + mux_module, circuit_lib.port_prefix(mux_model_input_ports[0])); + VTR_ASSERT( + true == module_manager.valid_module_port_id(mux_module, mux_input_port_id)); + BasicPort mux_input_port = + module_manager.module_port(mux_module, mux_input_port_id); /* Check port size should match */ VTR_ASSERT(mux_input_port.get_width() == sb_input_port_ids.size()); @@ -156,51 +165,74 @@ void build_switch_block_mux_module(ModuleManager& module_manager, /* Use the exising net */ ModuleNetId net = input_port_to_module_nets.at(sb_input_port_ids[pin_id]); /* Configure the net source only if it is not yet in the source list */ - if (false == module_manager.net_source_exist(sb_module, net, sb_module, 0, sb_input_port_ids[pin_id].first, sb_input_port_ids[pin_id].second)) { - module_manager.add_module_net_source(sb_module, net, sb_module, 0, sb_input_port_ids[pin_id].first, sb_input_port_ids[pin_id].second); + if (false == + module_manager.net_source_exist(sb_module, net, sb_module, 0, + sb_input_port_ids[pin_id].first, + sb_input_port_ids[pin_id].second)) { + module_manager.add_module_net_source(sb_module, net, sb_module, 0, + sb_input_port_ids[pin_id].first, + sb_input_port_ids[pin_id].second); } /* Configure the net sink */ - module_manager.add_module_net_sink(sb_module, net, mux_module, mux_instance_id, mux_input_port_id, mux_input_port.pins()[pin_id]); + module_manager.add_module_net_sink(sb_module, net, mux_module, + mux_instance_id, mux_input_port_id, + mux_input_port.pins()[pin_id]); } /* Link output port to Switch Block outputs */ - std::vector mux_model_output_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector mux_model_output_ports = + circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_OUTPUT, true); VTR_ASSERT(1 == mux_model_output_ports.size()); /* Use the port name convention in the circuit library */ - ModulePortId mux_output_port_id = module_manager.find_module_port(mux_module, circuit_lib.port_prefix(mux_model_output_ports[0])); - VTR_ASSERT(true == module_manager.valid_module_port_id(mux_module, mux_output_port_id)); - BasicPort mux_output_port = module_manager.module_port(mux_module, mux_output_port_id); - ModulePinInfo sb_output_port_id = find_switch_block_module_chan_port(module_manager, sb_module, rr_graph, rr_gsb, chan_side, cur_rr_node, OUT_PORT); - BasicPort sb_output_port = module_manager.module_port(sb_module, sb_output_port_id.first); + ModulePortId mux_output_port_id = module_manager.find_module_port( + mux_module, circuit_lib.port_prefix(mux_model_output_ports[0])); + VTR_ASSERT(true == module_manager.valid_module_port_id(mux_module, + mux_output_port_id)); + BasicPort mux_output_port = + module_manager.module_port(mux_module, mux_output_port_id); + ModulePinInfo sb_output_port_id = find_switch_block_module_chan_port( + module_manager, sb_module, rr_graph, rr_gsb, chan_side, cur_rr_node, + OUT_PORT); + BasicPort sb_output_port = + module_manager.module_port(sb_module, sb_output_port_id.first); /* Check port size should match */ VTR_ASSERT(1 == mux_output_port.get_width()); for (size_t pin_id = 0; pin_id < mux_output_port.pins().size(); ++pin_id) { /* Configuring the net source */ - ModuleNetId net = create_module_source_pin_net(module_manager, sb_module, mux_module, mux_instance_id, mux_output_port_id, mux_output_port.pins()[pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, sb_module, mux_module, mux_instance_id, + mux_output_port_id, mux_output_port.pins()[pin_id]); /* Configure the net sink */ - module_manager.add_module_net_sink(sb_module, net, sb_module, 0, sb_output_port_id.first, sb_output_port_id.second); + module_manager.add_module_net_sink(sb_module, net, sb_module, 0, + sb_output_port_id.first, + sb_output_port_id.second); } /* Instanciate memory modules */ /* Find the name and module id of the memory module */ - std::string mem_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string(MEMORY_MODULE_POSTFIX)); + std::string mem_module_name = + generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, + std::string(MEMORY_MODULE_POSTFIX)); ModuleId mem_module = module_manager.find_module(mem_module_name); - VTR_ASSERT (true == module_manager.valid_module_id(mem_module)); + VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); size_t mem_instance_id = module_manager.num_instance(sb_module, mem_module); module_manager.add_child_module(sb_module, mem_module); - /* Give an instance name: this name should be consistent with the block name given in bitstream manager, - * If you want to bind the bitstream generation to modules + /* Give an instance name: this name should be consistent with the block name + * given in bitstream manager, If you want to bind the bitstream generation to + * modules */ - std::string mem_instance_name = generate_sb_memory_instance_name(SWITCH_BLOCK_MEM_INSTANCE_PREFIX, chan_side, chan_node_id, std::string("")); - module_manager.set_child_instance_name(sb_module, mem_module, mem_instance_id, mem_instance_name); + std::string mem_instance_name = generate_sb_memory_instance_name( + SWITCH_BLOCK_MEM_INSTANCE_PREFIX, chan_side, chan_node_id, std::string("")); + module_manager.set_child_instance_name(sb_module, mem_module, mem_instance_id, + mem_instance_name); - /* Add nets to connect regular and mode-select SRAM ports to the SRAM port of memory module */ - add_module_nets_between_logic_and_memory_sram_bus(module_manager, sb_module, - mux_module, mux_instance_id, - mem_module, mem_instance_id, - circuit_lib, mux_model); + /* Add nets to connect regular and mode-select SRAM ports to the SRAM port of + * memory module */ + add_module_nets_between_logic_and_memory_sram_bus( + module_manager, sb_module, mux_module, mux_instance_id, mem_module, + mem_instance_id, circuit_lib, mux_model); /* Update memory and instance list */ module_manager.add_configurable_child(sb_module, mem_module, mem_instance_id); } @@ -210,69 +242,57 @@ void build_switch_block_mux_module(ModuleManager& module_manager, * The interconnection could be either a wire or a routing multiplexer, * which depends on the fan-in of the rr_nodes in the switch block ********************************************************************/ -static -void build_switch_block_interc_modules(ModuleManager& module_manager, - const ModuleId& sb_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const CircuitLibrary& circuit_lib, - const e_side& chan_side, - const size_t& chan_node_id, - const std::map& input_port_to_module_nets) { +static void build_switch_block_interc_modules( + ModuleManager& module_manager, const ModuleId& sb_module, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, + const CircuitLibrary& circuit_lib, const e_side& chan_side, + const size_t& chan_node_id, + const std::map& input_port_to_module_nets) { std::vector driver_rr_nodes; /* Get the node */ const RRNodeId& cur_rr_node = rr_gsb.get_chan_node(chan_side, chan_node_id); - /* Determine if the interc lies inside a channel wire, that is interc between segments */ - if (false == rr_gsb.is_sb_node_passing_wire(rr_graph, chan_side, chan_node_id)) { - driver_rr_nodes = get_rr_gsb_chan_node_configurable_driver_nodes(rr_graph, rr_gsb, chan_side, chan_node_id); + /* Determine if the interc lies inside a channel wire, that is interc between + * segments */ + if (false == + rr_gsb.is_sb_node_passing_wire(rr_graph, chan_side, chan_node_id)) { + driver_rr_nodes = get_rr_gsb_chan_node_configurable_driver_nodes( + rr_graph, rr_gsb, chan_side, chan_node_id); /* Special: if there are zero-driver nodes. We skip here */ if (0 == driver_rr_nodes.size()) { - return; + return; } } if (0 == driver_rr_nodes.size()) { /* Print a special direct connection*/ - build_switch_block_module_short_interc(module_manager, sb_module, - device_annotation, - grids, - rr_graph, rr_gsb, - chan_side, cur_rr_node, - cur_rr_node, - input_port_to_module_nets); + build_switch_block_module_short_interc( + module_manager, sb_module, device_annotation, grids, rr_graph, rr_gsb, + chan_side, cur_rr_node, cur_rr_node, input_port_to_module_nets); } else if (1 == driver_rr_nodes.size()) { /* Print a direct connection*/ - build_switch_block_module_short_interc(module_manager, sb_module, - device_annotation, - grids, - rr_graph, rr_gsb, chan_side, cur_rr_node, - driver_rr_nodes[0], - input_port_to_module_nets); + build_switch_block_module_short_interc( + module_manager, sb_module, device_annotation, grids, rr_graph, rr_gsb, + chan_side, cur_rr_node, driver_rr_nodes[0], input_port_to_module_nets); } else if (1 < driver_rr_nodes.size()) { /* Print the multiplexer, fan_in >= 2 */ - std::vector driver_switches = get_rr_graph_driver_switches(rr_graph, cur_rr_node); + std::vector driver_switches = + get_rr_graph_driver_switches(rr_graph, cur_rr_node); VTR_ASSERT(1 == driver_switches.size()); - build_switch_block_mux_module(module_manager, - sb_module, device_annotation, - grids, rr_graph, rr_gsb, - circuit_lib, - chan_side, chan_node_id, cur_rr_node, - driver_rr_nodes, - driver_switches[0], - input_port_to_module_nets); - } /*Nothing should be done else*/ + build_switch_block_mux_module( + module_manager, sb_module, device_annotation, grids, rr_graph, rr_gsb, + circuit_lib, chan_side, chan_node_id, cur_rr_node, driver_rr_nodes, + driver_switches[0], input_port_to_module_nets); + } /*Nothing should be done else*/ } - /******************************************************************** * Build a module for a switch block whose detailed description is - * available in a RRGSB object + * available in a RRGSB object * A Switch Box module consists of following ports: - * 1. Channel Y [x][y] inputs + * 1. Channel Y [x][y] inputs * 2. Channel X [x+1][y] inputs * 3. Channel Y [x][y-1] outputs * 4. Channel X [x][y] outputs @@ -294,7 +314,7 @@ void build_switch_block_interc_modules(ModuleManager& module_manager, * | | | | * -------------- -------------- * ---------- - * ChanX | Switch | ChanX + * ChanX | Switch | ChanX * [x][y] | Box | [x+1][y] * | [x][y] | * ---------- @@ -307,54 +327,47 @@ void build_switch_block_interc_modules(ModuleManager& module_manager, * * Switch Block pin location map * - * Grid[x][y+1] ChanY[x][y+1] Grid[x+1][y+1] + * Grid[x][y+1] ChanY[x][y+1] Grid[x+1][y+1] * right_pins inputs/outputs left_pins * | ^ | * | | | * v v v * +-----------------------------------------------+ * | | - * Grid[x][y+1] | | Grid[x+1][y+1] - * bottom_pins---->| |<---- bottom_pins - * | | - * ChanX[x][y] | Switch Box [x][y] | ChanX[x+1][y] - * inputs/outputs<--->| |<---> inputs/outputs - * | | - * Grid[x][y+1] | | Grid[x+1][y+1] - * top_pins---->| |<---- top_pins - * | | + * Grid[x][y+1] | | + *Grid[x+1][y+1] bottom_pins---->| |<---- bottom_pins | | ChanX[x][y] | + *Switch Box [x][y] | ChanX[x+1][y] inputs/outputs<--->| + *|<---> inputs/outputs | | + * Grid[x][y+1] | | + *Grid[x+1][y+1] top_pins---->| |<---- top_pins | | * +-----------------------------------------------+ * ^ ^ ^ * | | | * | v | - * Grid[x][y] ChanY[x][y] Grid[x+1][y] + * Grid[x][y] ChanY[x][y] Grid[x+1][y] * right_pins inputs/outputs left_pins * * ********************************************************************/ -static -void build_switch_block_module(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - const RRGSB& rr_gsb, - const bool& verbose) { +static void build_switch_block_module( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, const RRGSB& rr_gsb, const bool& verbose) { /* Create a Module of Switch Block and add to module manager */ vtr::Point gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); - ModuleId sb_module = module_manager.add_module(generate_switch_block_module_name(gsb_coordinate)); + ModuleId sb_module = module_manager.add_module( + generate_switch_block_module_name(gsb_coordinate)); /* Label module usage */ module_manager.set_module_usage(sb_module, ModuleManager::MODULE_SB); - VTR_LOGV(verbose, - "Building module '%s'...", + VTR_LOGV(verbose, "Building module '%s'...", generate_switch_block_module_name(gsb_coordinate).c_str()); - /* Create a cache (fast look up) for module nets whose source are input ports */ + /* Create a cache (fast look up) for module nets whose source are input ports + */ std::map input_port_to_module_nets; /* Add routing channel ports at each side of the GSB */ @@ -365,19 +378,20 @@ void build_switch_block_module(ModuleManager& module_manager, size_t chan_input_port_size = 0; size_t chan_output_port_size = 0; - for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) { + for (size_t itrack = 0; + itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) { switch (rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) { - case OUT_PORT: - chan_output_port_size++; - break; - case IN_PORT: - chan_input_port_size++; - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid direction of chan[%d][%d]_track[%d]!\n", - rr_gsb.get_sb_x(), rr_gsb.get_sb_y(), itrack); - exit(1); + case OUT_PORT: + chan_output_port_size++; + break; + case IN_PORT: + chan_input_port_size++; + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid direction of chan[%d][%d]_track[%d]!\n", + rr_gsb.get_sb_x(), rr_gsb.get_sb_y(), itrack); + exit(1); } } @@ -385,93 +399,110 @@ void build_switch_block_module(ModuleManager& module_manager, if (0 < rr_gsb.get_chan_width(side_manager.get_side())) { t_rr_type chan_type = rr_gsb.get_chan_type(side_manager.get_side()); - std::string chan_input_port_name = generate_sb_module_track_port_name(chan_type, - side_manager.get_side(), - IN_PORT); + std::string chan_input_port_name = generate_sb_module_track_port_name( + chan_type, side_manager.get_side(), IN_PORT); BasicPort chan_input_port(chan_input_port_name, chan_input_port_size); - ModulePortId chan_input_port_id = module_manager.add_port(sb_module, chan_input_port, ModuleManager::MODULE_INPUT_PORT); + ModulePortId chan_input_port_id = module_manager.add_port( + sb_module, chan_input_port, ModuleManager::MODULE_INPUT_PORT); /* Cache the input net */ for (const size_t& pin : chan_input_port.pins()) { - ModuleNetId net = create_module_source_pin_net(module_manager, sb_module, sb_module, 0, chan_input_port_id, pin); + ModuleNetId net = create_module_source_pin_net( + module_manager, sb_module, sb_module, 0, chan_input_port_id, pin); input_port_to_module_nets[ModulePinInfo(chan_input_port_id, pin)] = net; } - std::string chan_output_port_name = generate_sb_module_track_port_name(chan_type, - side_manager.get_side(), - OUT_PORT); + std::string chan_output_port_name = generate_sb_module_track_port_name( + chan_type, side_manager.get_side(), OUT_PORT); BasicPort chan_output_port(chan_output_port_name, chan_output_port_size); - module_manager.add_port(sb_module, chan_output_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(sb_module, chan_output_port, + ModuleManager::MODULE_OUTPUT_PORT); } /* Dump OPINs of adjacent CLBs */ - for (size_t inode = 0; inode < rr_gsb.get_num_opin_nodes(side_manager.get_side()); ++inode) { - vtr::Point port_coord(rr_graph.node_xlow(rr_gsb.get_opin_node(side_manager.get_side(), inode)), - rr_graph.node_ylow(rr_gsb.get_opin_node(side_manager.get_side(), inode))); - std::string port_name = generate_sb_module_grid_port_name(side_manager.get_side(), - get_rr_graph_single_node_side(rr_graph, rr_gsb.get_opin_node(side_manager.get_side(), inode)), - grids, - device_annotation, - rr_graph, - rr_gsb.get_opin_node(side_manager.get_side(), inode)); - BasicPort module_port(port_name, 1); /* Every grid output has a port size of 1 */ + for (size_t inode = 0; + inode < rr_gsb.get_num_opin_nodes(side_manager.get_side()); ++inode) { + vtr::Point port_coord(rr_graph.node_xlow(rr_gsb.get_opin_node( + side_manager.get_side(), inode)), + rr_graph.node_ylow(rr_gsb.get_opin_node( + side_manager.get_side(), inode))); + std::string port_name = generate_sb_module_grid_port_name( + side_manager.get_side(), + get_rr_graph_single_node_side( + rr_graph, rr_gsb.get_opin_node(side_manager.get_side(), inode)), + grids, device_annotation, rr_graph, + rr_gsb.get_opin_node(side_manager.get_side(), inode)); + BasicPort module_port(port_name, + 1); /* Every grid output has a port size of 1 */ /* Grid outputs are inputs of switch blocks */ - ModulePortId input_port_id = module_manager.add_port(sb_module, module_port, ModuleManager::MODULE_INPUT_PORT); + ModulePortId input_port_id = module_manager.add_port( + sb_module, module_port, ModuleManager::MODULE_INPUT_PORT); /* Cache the input net */ - ModuleNetId net = create_module_source_pin_net(module_manager, sb_module, sb_module, 0, input_port_id, 0); + ModuleNetId net = create_module_source_pin_net( + module_manager, sb_module, sb_module, 0, input_port_id, 0); input_port_to_module_nets[ModulePinInfo(input_port_id, 0)] = net; - } + } } /* Add routing multiplexers as child modules */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); - for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) { + for (size_t itrack = 0; + itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) { /* We care OUTPUT tracks at this time only */ - if (OUT_PORT == rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) { - build_switch_block_interc_modules(module_manager, - sb_module, device_annotation, - grids, rr_graph, rr_gsb, - circuit_lib, - side_manager.get_side(), - itrack, - input_port_to_module_nets); - } + if (OUT_PORT == + rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) { + build_switch_block_interc_modules( + module_manager, sb_module, device_annotation, grids, rr_graph, rr_gsb, + circuit_lib, side_manager.get_side(), itrack, + input_port_to_module_nets); + } } } /* Add global ports to the pb_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 a list of it + * 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 + * a list of it */ add_module_global_ports_from_child_modules(module_manager, sb_module); /* Count shared SRAM ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it */ - size_t module_num_shared_config_bits = find_module_num_shared_config_bits_from_child_modules(module_manager, sb_module); + size_t module_num_shared_config_bits = + find_module_num_shared_config_bits_from_child_modules(module_manager, + sb_module); if (0 < module_num_shared_config_bits) { - add_reserved_sram_ports_to_module_manager(module_manager, sb_module, module_num_shared_config_bits); + add_reserved_sram_ports_to_module_manager(module_manager, sb_module, + module_num_shared_config_bits); } /* Count SRAM ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it */ - size_t module_num_config_bits = find_module_num_config_bits_from_child_modules(module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type); + size_t module_num_config_bits = + find_module_num_config_bits_from_child_modules( + module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type); if (0 < module_num_config_bits) { - add_pb_sram_ports_to_module_manager(module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type, module_num_config_bits); + add_pb_sram_ports_to_module_manager(module_manager, sb_module, circuit_lib, + sram_model, sram_orgz_type, + module_num_config_bits); } - /* Add all the nets to connect configuration ports from memory module to primitive modules - * This is a one-shot addition that covers all the memory modules in this primitive module! + /* Add all the nets to connect configuration ports from memory module to + * primitive modules This is a one-shot addition that covers all the memory + * modules in this primitive module! */ if (0 < module_manager.configurable_children(sb_module).size()) { - add_pb_module_nets_memory_config_bus(module_manager, decoder_lib, - sb_module, - sram_orgz_type, circuit_lib.design_tech_type(sram_model)); + add_pb_module_nets_memory_config_bus( + module_manager, decoder_lib, sb_module, sram_orgz_type, + circuit_lib.design_tech_type(sram_model)); } VTR_LOGV(verbose, "Done\n"); @@ -480,28 +511,24 @@ void build_switch_block_module(ModuleManager& module_manager, /********************************************************************* * Print a short interconneciton in connection ********************************************************************/ -static -void build_connection_block_module_short_interc(ModuleManager& module_manager, - const ModuleId& cb_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const t_rr_type& cb_type, - const e_side& cb_ipin_side, - const size_t& ipin_index, - const std::map& input_port_to_module_nets) { +static void build_connection_block_module_short_interc( + ModuleManager& module_manager, const ModuleId& cb_module, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type, + const e_side& cb_ipin_side, const size_t& ipin_index, + const std::map& input_port_to_module_nets) { /* Ensure we have only one 1 driver node */ const RRNodeId& src_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index); - std::vector driver_rr_edges = rr_gsb.get_ipin_node_in_edges(rr_graph, cb_ipin_side, ipin_index); + std::vector driver_rr_edges = + rr_gsb.get_ipin_node_in_edges(rr_graph, cb_ipin_side, ipin_index); std::vector driver_rr_nodes; for (const RREdgeId curr_edge : driver_rr_edges) { driver_rr_nodes.push_back(rr_graph.edge_src_node(curr_edge)); } /* We have OPINs since we may have direct connections: - * These connections should be handled by other functions in the compact_netlist.c - * So we just return here for OPINs + * These connections should be handled by other functions in the + * compact_netlist.c So we just return here for OPINs */ if (0 == driver_rr_nodes.size()) { return; @@ -509,101 +536,119 @@ void build_connection_block_module_short_interc(ModuleManager& module_manager, /* Find the driver node */ VTR_ASSERT_SAFE(1 == driver_rr_nodes.size()); - const RRNodeId& driver_rr_node = driver_rr_nodes[0]; + const RRNodeId& driver_rr_node = driver_rr_nodes[0]; /* Xifan Tang: VPR considers delayless switch to be configurable * As a result, the direct connection is considered to be configurable... * Here, I simply kick out OPINs in CB connection because they should be built * in the top mopdule. - * - * Note: this MUST BE reconsidered if we do have OPIN connected to IPINs + * + * Note: this MUST BE reconsidered if we do have OPIN connected to IPINs * through a programmable multiplexer!!! */ if (OPIN == rr_graph.node_type(driver_rr_node)) { return; } - VTR_ASSERT((CHANX == rr_graph.node_type(driver_rr_node)) || (CHANY == rr_graph.node_type(driver_rr_node))); + VTR_ASSERT((CHANX == rr_graph.node_type(driver_rr_node)) || + (CHANY == rr_graph.node_type(driver_rr_node))); /* Create port description for the routing track middle output */ - ModulePinInfo input_port_info = find_connection_block_module_chan_port(module_manager, cb_module, rr_graph, rr_gsb, cb_type, driver_rr_node); + ModulePinInfo input_port_info = find_connection_block_module_chan_port( + module_manager, cb_module, rr_graph, rr_gsb, cb_type, driver_rr_node); /* Create port description for input pin of a CLB */ - ModulePortId ipin_port_id = find_connection_block_module_ipin_port(module_manager, cb_module, grids, device_annotation, rr_graph, rr_gsb, src_rr_node); + ModulePortId ipin_port_id = find_connection_block_module_ipin_port( + module_manager, cb_module, grids, device_annotation, rr_graph, rr_gsb, + src_rr_node); /* The input port and output port must match in size */ - BasicPort input_port = module_manager.module_port(cb_module, input_port_info.first); + BasicPort input_port = + module_manager.module_port(cb_module, input_port_info.first); BasicPort ipin_port = module_manager.module_port(cb_module, ipin_port_id); VTR_ASSERT(1 == ipin_port.get_width()); - + /* Create a module net for this short-wire connection */ ModuleNetId net = input_port_to_module_nets.at(input_port_info); /* Skip Configuring the net source, it is done before */ /* Configure the net sink */ - module_manager.add_module_net_sink(cb_module, net, cb_module, 0, ipin_port_id, ipin_port.pins()[0]); + module_manager.add_module_net_sink(cb_module, net, cb_module, 0, ipin_port_id, + ipin_port.pins()[0]); } /********************************************************************* * Build a instance of a routing multiplexer as well as * associated memory modules for a connection inside a connection block ********************************************************************/ -static -void build_connection_block_mux_module(ModuleManager& module_manager, - const ModuleId& cb_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const t_rr_type& cb_type, - const CircuitLibrary& circuit_lib, - const e_side& cb_ipin_side, - const size_t& ipin_index, - const std::map& input_port_to_module_nets) { +static void build_connection_block_mux_module( + ModuleManager& module_manager, const ModuleId& cb_module, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type, + const CircuitLibrary& circuit_lib, const e_side& cb_ipin_side, + const size_t& ipin_index, + const std::map& input_port_to_module_nets) { const RRNodeId& cur_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index); /* Check current rr_node is an input pin of a CLB */ VTR_ASSERT(IPIN == rr_graph.node_type(cur_rr_node)); /* Build a vector of driver rr_nodes */ - std::vector driver_rr_edges = rr_gsb.get_ipin_node_in_edges(rr_graph, cb_ipin_side, ipin_index); + std::vector driver_rr_edges = + rr_gsb.get_ipin_node_in_edges(rr_graph, cb_ipin_side, ipin_index); std::vector driver_rr_nodes; for (const RREdgeId curr_edge : driver_rr_edges) { driver_rr_nodes.push_back(rr_graph.edge_src_node(curr_edge)); } - std::vector driver_switches = get_rr_graph_driver_switches(rr_graph, cur_rr_node); + std::vector driver_switches = + get_rr_graph_driver_switches(rr_graph, cur_rr_node); VTR_ASSERT(1 == driver_switches.size()); /* Get the circuit model id of the routing multiplexer */ - CircuitModelId mux_model = device_annotation.rr_switch_circuit_model(driver_switches[0]); + CircuitModelId mux_model = + device_annotation.rr_switch_circuit_model(driver_switches[0]); /* Find the input size of the implementation of a routing multiplexer */ size_t datapath_mux_size = driver_rr_nodes.size(); - /* Find the module name of the multiplexer and try to find it in the module manager */ - std::string mux_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string("")); + /* Find the module name of the multiplexer and try to find it in the module + * manager */ + std::string mux_module_name = generate_mux_subckt_name( + circuit_lib, mux_model, datapath_mux_size, std::string("")); ModuleId mux_module = module_manager.find_module(mux_module_name); - VTR_ASSERT (true == module_manager.valid_module_id(mux_module)); + VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); /* Get the MUX instance id from the module manager */ size_t mux_instance_id = module_manager.num_instance(cb_module, mux_module); module_manager.add_child_module(cb_module, mux_module); - /* Give an instance name: this name should be consistent with the block name given in SDC manager, - * If you want to bind the SDC generation to modules + /* Give an instance name: this name should be consistent with the block name + * given in SDC manager, If you want to bind the SDC generation to modules */ - std::string mux_instance_name = generate_cb_mux_instance_name(CONNECTION_BLOCK_MUX_INSTANCE_PREFIX, get_rr_graph_single_node_side(rr_graph, rr_gsb.get_ipin_node(cb_ipin_side, ipin_index)), ipin_index, std::string("")); - module_manager.set_child_instance_name(cb_module, mux_module, mux_instance_id, mux_instance_name); + std::string mux_instance_name = generate_cb_mux_instance_name( + CONNECTION_BLOCK_MUX_INSTANCE_PREFIX, + get_rr_graph_single_node_side( + rr_graph, rr_gsb.get_ipin_node(cb_ipin_side, ipin_index)), + ipin_index, std::string("")); + module_manager.set_child_instance_name(cb_module, mux_module, mux_instance_id, + mux_instance_name); - /* TODO: Generate input ports that are wired to the input bus of the routing multiplexer */ - std::vector cb_input_port_ids = find_connection_block_module_input_ports(module_manager, cb_module, rr_graph, rr_gsb, cb_type, driver_rr_nodes); + /* TODO: Generate input ports that are wired to the input bus of the routing + * multiplexer */ + std::vector cb_input_port_ids = + find_connection_block_module_input_ports( + module_manager, cb_module, rr_graph, rr_gsb, cb_type, driver_rr_nodes); /* Link input bus port to Switch Block inputs */ - std::vector mux_model_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector mux_model_input_ports = + circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); VTR_ASSERT(1 == mux_model_input_ports.size()); /* Find the module port id of the input port */ - ModulePortId mux_input_port_id = module_manager.find_module_port(mux_module, circuit_lib.port_prefix(mux_model_input_ports[0])); - VTR_ASSERT(true == module_manager.valid_module_port_id(mux_module, mux_input_port_id)); - BasicPort mux_input_port = module_manager.module_port(mux_module, mux_input_port_id); + ModulePortId mux_input_port_id = module_manager.find_module_port( + mux_module, circuit_lib.port_prefix(mux_model_input_ports[0])); + VTR_ASSERT( + true == module_manager.valid_module_port_id(mux_module, mux_input_port_id)); + BasicPort mux_input_port = + module_manager.module_port(mux_module, mux_input_port_id); /* Check port size should match */ VTR_ASSERT(mux_input_port.get_width() == cb_input_port_ids.size()); @@ -612,101 +657,118 @@ void build_connection_block_mux_module(ModuleManager& module_manager, ModuleNetId net = input_port_to_module_nets.at(cb_input_port_ids[pin_id]); /* No need to configure the net source since it is already done before */ /* Configure the net sink */ - module_manager.add_module_net_sink(cb_module, net, mux_module, mux_instance_id, mux_input_port_id, mux_input_port.pins()[pin_id]); + module_manager.add_module_net_sink(cb_module, net, mux_module, + mux_instance_id, mux_input_port_id, + mux_input_port.pins()[pin_id]); } /* Link output port to Switch Block outputs */ - std::vector mux_model_output_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector mux_model_output_ports = + circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_OUTPUT, true); VTR_ASSERT(1 == mux_model_output_ports.size()); /* Use the port name convention in the circuit library */ - ModulePortId mux_output_port_id = module_manager.find_module_port(mux_module, circuit_lib.port_prefix(mux_model_output_ports[0])); - VTR_ASSERT(true == module_manager.valid_module_port_id(mux_module, mux_output_port_id)); - BasicPort mux_output_port = module_manager.module_port(mux_module, mux_output_port_id); - ModulePortId cb_output_port_id = find_connection_block_module_ipin_port(module_manager, cb_module, grids, device_annotation, rr_graph, rr_gsb, cur_rr_node); - BasicPort cb_output_port = module_manager.module_port(cb_module, cb_output_port_id); + ModulePortId mux_output_port_id = module_manager.find_module_port( + mux_module, circuit_lib.port_prefix(mux_model_output_ports[0])); + VTR_ASSERT(true == module_manager.valid_module_port_id(mux_module, + mux_output_port_id)); + BasicPort mux_output_port = + module_manager.module_port(mux_module, mux_output_port_id); + ModulePortId cb_output_port_id = find_connection_block_module_ipin_port( + module_manager, cb_module, grids, device_annotation, rr_graph, rr_gsb, + cur_rr_node); + BasicPort cb_output_port = + module_manager.module_port(cb_module, cb_output_port_id); /* Check port size should match */ VTR_ASSERT(cb_output_port.get_width() == mux_output_port.get_width()); for (size_t pin_id = 0; pin_id < mux_output_port.pins().size(); ++pin_id) { /* Configuring the net source */ - ModuleNetId net = create_module_source_pin_net(module_manager, cb_module, mux_module, mux_instance_id, mux_output_port_id, mux_output_port.pins()[pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, cb_module, mux_module, mux_instance_id, + mux_output_port_id, mux_output_port.pins()[pin_id]); /* Configure the net sink */ - module_manager.add_module_net_sink(cb_module, net, cb_module, 0, cb_output_port_id, cb_output_port.pins()[pin_id]); + module_manager.add_module_net_sink(cb_module, net, cb_module, 0, + cb_output_port_id, + cb_output_port.pins()[pin_id]); } /* Instanciate memory modules */ /* Find the name and module id of the memory module */ - std::string mem_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string(MEMORY_MODULE_POSTFIX)); + std::string mem_module_name = + generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, + std::string(MEMORY_MODULE_POSTFIX)); ModuleId mem_module = module_manager.find_module(mem_module_name); - VTR_ASSERT (true == module_manager.valid_module_id(mem_module)); + VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); size_t mem_instance_id = module_manager.num_instance(cb_module, mem_module); module_manager.add_child_module(cb_module, mem_module); - /* Give an instance name: this name should be consistent with the block name given in bitstream manager, - * If you want to bind the bitstream generation to modules + /* Give an instance name: this name should be consistent with the block name + * given in bitstream manager, If you want to bind the bitstream generation to + * modules */ - std::string mem_instance_name = generate_cb_memory_instance_name(CONNECTION_BLOCK_MEM_INSTANCE_PREFIX, get_rr_graph_single_node_side(rr_graph, rr_gsb.get_ipin_node(cb_ipin_side, ipin_index)), ipin_index, std::string("")); - module_manager.set_child_instance_name(cb_module, mem_module, mem_instance_id, mem_instance_name); + std::string mem_instance_name = generate_cb_memory_instance_name( + CONNECTION_BLOCK_MEM_INSTANCE_PREFIX, + get_rr_graph_single_node_side( + rr_graph, rr_gsb.get_ipin_node(cb_ipin_side, ipin_index)), + ipin_index, std::string("")); + module_manager.set_child_instance_name(cb_module, mem_module, mem_instance_id, + mem_instance_name); - /* Add nets to connect regular and mode-select SRAM ports to the SRAM port of memory module */ - add_module_nets_between_logic_and_memory_sram_bus(module_manager, cb_module, - mux_module, mux_instance_id, - mem_module, mem_instance_id, - circuit_lib, mux_model); + /* Add nets to connect regular and mode-select SRAM ports to the SRAM port of + * memory module */ + add_module_nets_between_logic_and_memory_sram_bus( + module_manager, cb_module, mux_module, mux_instance_id, mem_module, + mem_instance_id, circuit_lib, mux_model); /* Update memory and instance list */ module_manager.add_configurable_child(cb_module, mem_module, mem_instance_id); } /******************************************************************** - * Print internal connections of a connection block + * Print internal connections of a connection block * For a IPIN node that is driven by only 1 fan-in, * a short wire will be created * For a IPIN node that is driven by more than two fan-ins, - * a routing multiplexer will be instanciated + * a routing multiplexer will be instanciated ********************************************************************/ -static -void build_connection_block_interc_modules(ModuleManager& module_manager, - const ModuleId& cb_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const t_rr_type& cb_type, - const CircuitLibrary& circuit_lib, - const e_side& cb_ipin_side, - const size_t& ipin_index, - const std::map& input_port_to_module_nets) { +static void build_connection_block_interc_modules( + ModuleManager& module_manager, const ModuleId& cb_module, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type, + const CircuitLibrary& circuit_lib, const e_side& cb_ipin_side, + const size_t& ipin_index, + const std::map& input_port_to_module_nets) { const RRNodeId& src_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index); - std::vector driver_rr_edges = rr_gsb.get_ipin_node_in_edges(rr_graph, cb_ipin_side, ipin_index); + std::vector driver_rr_edges = + rr_gsb.get_ipin_node_in_edges(rr_graph, cb_ipin_side, ipin_index); if (1 > driver_rr_edges.size()) { return; /* This port has no driver, skip it */ } else if (1 == driver_rr_edges.size()) { /* Print a direct connection */ - build_connection_block_module_short_interc(module_manager, cb_module, device_annotation, grids, rr_graph, rr_gsb, cb_type, cb_ipin_side, ipin_index, input_port_to_module_nets); + build_connection_block_module_short_interc( + module_manager, cb_module, device_annotation, grids, rr_graph, rr_gsb, + cb_type, cb_ipin_side, ipin_index, input_port_to_module_nets); } else if (1 < driver_rr_edges.size()) { /* Print the multiplexer, fan_in >= 2 */ - build_connection_block_mux_module(module_manager, - cb_module, device_annotation, - grids, rr_graph, rr_gsb, cb_type, - circuit_lib, - cb_ipin_side, ipin_index, - input_port_to_module_nets); - } /*Nothing should be done else*/ + build_connection_block_mux_module( + module_manager, cb_module, device_annotation, grids, rr_graph, rr_gsb, + cb_type, circuit_lib, cb_ipin_side, ipin_index, + input_port_to_module_nets); + } /*Nothing should be done else*/ } -/******************************************************************** +/******************************************************************** * Generate a module of a connection Box (Type: [CHANX|CHANY]) * Actually it is very similiar to switch box but * the difference is connection boxes connect Grid INPUT Pins to channels * NOTE: direct connection between CLBs should NOT be included inside this - * module! They should be added in the top-level module as their connection - * is not limited to adjacent CLBs!!! + * module! They should be added in the top-level module as their + *connection is not limited to adjacent CLBs!!! * * Location of a X- and Y-direction Connection Block in FPGA fabric - * +------------+ +-------------+ + * +------------+ +-------------+ * | |------>| | * | CLB |<------| Y-direction | * | | ... | Connection | @@ -716,15 +778,16 @@ void build_connection_block_interc_modules(ModuleManager& module_manager, * v | v v | v * +-------------------+ +-------------+ * --->| |--->| | - * <---| X-direction |<---| Switch | + * <---| X-direction |<---| Switch | * ...| Connection block |... | Block | * --->| |--->| | * +-------------------+ +-------------+ * * Internal structure: - * This is an example of a X-direction connection block - * Note that middle output ports are shorted wire from inputs of routing tracks, - * which are also the inputs of routing multiplexer of the connection block + * This is an example of a X-direction connection block + * Note that middle output ports are shorted wire from inputs of routing + *tracks, which are also the inputs of routing multiplexer of the connection + *block * * CLB Input Pins * (IPINs) @@ -732,11 +795,11 @@ void build_connection_block_interc_modules(ModuleManager& module_manager, * | | ... | * +--------------------------+ * | ^ ^ ^ | - * | | | ... | | - * | +--------------------+ | + * | | | ... | | + * | +--------------------+ | * | | routing | | * | | multiplexers | | - * | +--------------------+ | + * | +--------------------+ | * | middle outputs | * | of routing channel | * | ^ ^ ^ ^ ^ ^ ^ ^ | @@ -749,211 +812,215 @@ void build_connection_block_interc_modules(ModuleManager& module_manager, * +--------------------------+ * * W: routing channel width - * + * ********************************************************************/ -static -void build_connection_block_module(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - const RRGSB& rr_gsb, - const t_rr_type& cb_type, - const bool& verbose) { +static void build_connection_block_module( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, const RRGSB& rr_gsb, + const t_rr_type& cb_type, const bool& verbose) { /* Create the netlist */ - vtr::Point gsb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); + vtr::Point gsb_coordinate(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId cb_module = module_manager.add_module(generate_connection_block_module_name(cb_type, gsb_coordinate)); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId cb_module = module_manager.add_module( + generate_connection_block_module_name(cb_type, gsb_coordinate)); /* Label module usage */ module_manager.set_module_usage(cb_module, ModuleManager::MODULE_CB); - VTR_LOGV(verbose, - "Building module '%s'...", - generate_connection_block_module_name(cb_type, gsb_coordinate).c_str()); + VTR_LOGV( + verbose, "Building module '%s'...", + generate_connection_block_module_name(cb_type, gsb_coordinate).c_str()); - /* Add the input and output ports of routing tracks in the channel - * Routing tracks pass through the connection blocks + /* Add the input and output ports of routing tracks in the channel + * Routing tracks pass through the connection blocks */ VTR_ASSERT(0 == rr_gsb.get_cb_chan_width(cb_type) % 2); /* Upper input port: W/2 == 0 tracks */ - std::string chan_upper_input_port_name = generate_cb_module_track_port_name(cb_type, - IN_PORT, - true); + std::string chan_upper_input_port_name = + generate_cb_module_track_port_name(cb_type, IN_PORT, true); BasicPort chan_upper_input_port(chan_upper_input_port_name, - rr_gsb.get_cb_chan_width(cb_type) / 2); - ModulePortId chan_upper_input_port_id = module_manager.add_port(cb_module, - chan_upper_input_port, - ModuleManager::MODULE_INPUT_PORT); + rr_gsb.get_cb_chan_width(cb_type) / 2); + ModulePortId chan_upper_input_port_id = module_manager.add_port( + cb_module, chan_upper_input_port, ModuleManager::MODULE_INPUT_PORT); /* Lower input port: W/2 == 1 tracks */ - std::string chan_lower_input_port_name = generate_cb_module_track_port_name(cb_type, - IN_PORT, - false); + std::string chan_lower_input_port_name = + generate_cb_module_track_port_name(cb_type, IN_PORT, false); BasicPort chan_lower_input_port(chan_lower_input_port_name, - rr_gsb.get_cb_chan_width(cb_type) / 2); - ModulePortId chan_lower_input_port_id = module_manager.add_port(cb_module, - chan_lower_input_port, - ModuleManager::MODULE_INPUT_PORT); + rr_gsb.get_cb_chan_width(cb_type) / 2); + ModulePortId chan_lower_input_port_id = module_manager.add_port( + cb_module, chan_lower_input_port, ModuleManager::MODULE_INPUT_PORT); /* Upper output port: W/2 == 0 tracks */ - std::string chan_upper_output_port_name = generate_cb_module_track_port_name(cb_type, - OUT_PORT, - true); + std::string chan_upper_output_port_name = + generate_cb_module_track_port_name(cb_type, OUT_PORT, true); BasicPort chan_upper_output_port(chan_upper_output_port_name, rr_gsb.get_cb_chan_width(cb_type) / 2); - ModulePortId chan_upper_output_port_id = module_manager.add_port(cb_module, - chan_upper_output_port, - ModuleManager::MODULE_OUTPUT_PORT); + ModulePortId chan_upper_output_port_id = module_manager.add_port( + cb_module, chan_upper_output_port, ModuleManager::MODULE_OUTPUT_PORT); /* Lower output port: W/2 == 1 tracks */ - std::string chan_lower_output_port_name = generate_cb_module_track_port_name(cb_type, - OUT_PORT, - false); + std::string chan_lower_output_port_name = + generate_cb_module_track_port_name(cb_type, OUT_PORT, false); BasicPort chan_lower_output_port(chan_lower_output_port_name, rr_gsb.get_cb_chan_width(cb_type) / 2); - ModulePortId chan_lower_output_port_id = module_manager.add_port(cb_module, - chan_lower_output_port, - ModuleManager::MODULE_OUTPUT_PORT); + ModulePortId chan_lower_output_port_id = module_manager.add_port( + cb_module, chan_lower_output_port, ModuleManager::MODULE_OUTPUT_PORT); - /* Add the input pins of grids, which are output ports of the connection block */ + /* Add the input pins of grids, which are output ports of the connection block + */ std::vector cb_ipin_sides = rr_gsb.get_cb_ipin_sides(cb_type); for (size_t iside = 0; iside < cb_ipin_sides.size(); ++iside) { enum e_side cb_ipin_side = cb_ipin_sides[iside]; - for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); ++inode) { + for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); + ++inode) { const RRNodeId& ipin_node = rr_gsb.get_ipin_node(cb_ipin_side, inode); - vtr::Point port_coord(rr_graph.node_xlow(ipin_node), rr_graph.node_ylow(ipin_node)); - std::string port_name = generate_cb_module_grid_port_name(cb_ipin_side, - grids, - device_annotation, - rr_graph, - ipin_node); - BasicPort module_port(port_name, 1); /* Every grid output has a port size of 1 */ + vtr::Point port_coord(rr_graph.node_xlow(ipin_node), + rr_graph.node_ylow(ipin_node)); + std::string port_name = generate_cb_module_grid_port_name( + cb_ipin_side, grids, device_annotation, rr_graph, ipin_node); + BasicPort module_port(port_name, + 1); /* Every grid output has a port size of 1 */ /* Grid outputs are inputs of switch blocks */ - module_manager.add_port(cb_module, module_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(cb_module, module_port, + ModuleManager::MODULE_OUTPUT_PORT); } } - /* Create a cache (fast look up) for module nets whose source are input ports */ + /* Create a cache (fast look up) for module nets whose source are input ports + */ std::map input_port_to_module_nets; - /* Generate short-wire connection for each routing track : + /* Generate short-wire connection for each routing track : * Each input port is short-wired to its output port - * + * * upper_in[i] ----------> lower_out[i] * lower_in[i] <---------- upper_out[i] */ /* Create short-wires: input port ---> output port */ - VTR_ASSERT(chan_upper_input_port.get_width() == chan_lower_output_port.get_width()); - for (size_t pin_id = 0; pin_id < chan_upper_input_port.pins().size(); ++pin_id) { - ModuleNetId net = create_module_source_pin_net(module_manager, cb_module, cb_module, 0, chan_upper_input_port_id, chan_upper_input_port.pins()[pin_id]); - module_manager.add_module_net_sink(cb_module, net, cb_module, 0, chan_lower_output_port_id, chan_lower_output_port.pins()[pin_id]); + VTR_ASSERT(chan_upper_input_port.get_width() == + chan_lower_output_port.get_width()); + for (size_t pin_id = 0; pin_id < chan_upper_input_port.pins().size(); + ++pin_id) { + ModuleNetId net = create_module_source_pin_net( + module_manager, cb_module, cb_module, 0, chan_upper_input_port_id, + chan_upper_input_port.pins()[pin_id]); + module_manager.add_module_net_sink(cb_module, net, cb_module, 0, + chan_lower_output_port_id, + chan_lower_output_port.pins()[pin_id]); /* Cache the module net */ - input_port_to_module_nets[ModulePinInfo(chan_upper_input_port_id, chan_upper_input_port.pins()[pin_id])] = net; + input_port_to_module_nets[ModulePinInfo( + chan_upper_input_port_id, chan_upper_input_port.pins()[pin_id])] = net; } - VTR_ASSERT(chan_lower_input_port.get_width() == chan_upper_output_port.get_width()); - for (size_t pin_id = 0; pin_id < chan_lower_input_port.pins().size(); ++pin_id) { - ModuleNetId net = create_module_source_pin_net(module_manager, cb_module, cb_module, 0, chan_lower_input_port_id, chan_lower_input_port.pins()[pin_id]); - module_manager.add_module_net_sink(cb_module, net, cb_module, 0, chan_upper_output_port_id, chan_upper_output_port.pins()[pin_id]); + VTR_ASSERT(chan_lower_input_port.get_width() == + chan_upper_output_port.get_width()); + for (size_t pin_id = 0; pin_id < chan_lower_input_port.pins().size(); + ++pin_id) { + ModuleNetId net = create_module_source_pin_net( + module_manager, cb_module, cb_module, 0, chan_lower_input_port_id, + chan_lower_input_port.pins()[pin_id]); + module_manager.add_module_net_sink(cb_module, net, cb_module, 0, + chan_upper_output_port_id, + chan_upper_output_port.pins()[pin_id]); /* Cache the module net */ - input_port_to_module_nets[ModulePinInfo(chan_lower_input_port_id, chan_lower_input_port.pins()[pin_id])] = net; + input_port_to_module_nets[ModulePinInfo( + chan_lower_input_port_id, chan_lower_input_port.pins()[pin_id])] = net; } /* Add sub modules of routing multiplexers or direct interconnect*/ for (size_t iside = 0; iside < cb_ipin_sides.size(); ++iside) { enum e_side cb_ipin_side = cb_ipin_sides[iside]; - for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); ++inode) { - build_connection_block_interc_modules(module_manager, - cb_module, device_annotation, - grids, - rr_graph, - rr_gsb, cb_type, - circuit_lib, - cb_ipin_side, inode, - input_port_to_module_nets); + for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); + ++inode) { + build_connection_block_interc_modules( + module_manager, cb_module, device_annotation, grids, rr_graph, rr_gsb, + cb_type, circuit_lib, cb_ipin_side, inode, input_port_to_module_nets); } } /* Add global ports to the pb_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 a list of it + * 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 + * a list of it */ add_module_global_ports_from_child_modules(module_manager, cb_module); /* Count shared SRAM ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it */ - size_t module_num_shared_config_bits = find_module_num_shared_config_bits_from_child_modules(module_manager, cb_module); + size_t module_num_shared_config_bits = + find_module_num_shared_config_bits_from_child_modules(module_manager, + cb_module); if (0 < module_num_shared_config_bits) { - add_reserved_sram_ports_to_module_manager(module_manager, cb_module, module_num_shared_config_bits); + add_reserved_sram_ports_to_module_manager(module_manager, cb_module, + module_num_shared_config_bits); } /* Count SRAM ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it */ - size_t module_num_config_bits = find_module_num_config_bits_from_child_modules(module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type); + size_t module_num_config_bits = + find_module_num_config_bits_from_child_modules( + module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type); if (0 < module_num_config_bits) { - add_pb_sram_ports_to_module_manager(module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type, module_num_config_bits); + add_pb_sram_ports_to_module_manager(module_manager, cb_module, circuit_lib, + sram_model, sram_orgz_type, + module_num_config_bits); } - /* Add all the nets to connect configuration ports from memory module to primitive modules - * This is a one-shot addition that covers all the memory modules in this primitive module! + /* Add all the nets to connect configuration ports from memory module to + * primitive modules This is a one-shot addition that covers all the memory + * modules in this primitive module! */ if (0 < module_manager.configurable_children(cb_module).size()) { - add_pb_module_nets_memory_config_bus(module_manager, decoder_lib, - cb_module, - sram_orgz_type, circuit_lib.design_tech_type(sram_model)); + add_pb_module_nets_memory_config_bus( + module_manager, decoder_lib, cb_module, sram_orgz_type, + circuit_lib.design_tech_type(sram_model)); } VTR_LOGV(verbose, "Done\n"); } - /******************************************************************** * Iterate over all the connection blocks in a device - * and build a module for each of them + * and build a module for each of them *******************************************************************/ -static -void build_flatten_connection_block_modules(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const DeviceRRGSB& device_rr_gsb, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - const t_rr_type& cb_type, - const bool& verbose) { +static void build_flatten_connection_block_modules( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, + const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, const t_rr_type& cb_type, + const bool& verbose) { /* Build unique X-direction connection block modules */ vtr::Point cb_range = device_rr_gsb.get_gsb_range(); for (size_t ix = 0; ix < cb_range.x(); ++ix) { for (size_t iy = 0; iy < cb_range.y(); ++iy) { /* Check if the connection block exists in the device! - * Some of them do NOT exist due to heterogeneous blocks (height > 1) + * Some of them do NOT exist due to heterogeneous blocks (height > 1) * We will skip those modules */ const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); if (false == rr_gsb.is_cb_exist(cb_type)) { continue; } - build_connection_block_module(module_manager, - decoder_lib, - device_annotation, - device_ctx.grid, - device_ctx.rr_graph, - circuit_lib, - sram_orgz_type, sram_model, - rr_gsb, cb_type, - verbose); + build_connection_block_module( + module_manager, decoder_lib, device_annotation, device_ctx.grid, + device_ctx.rr_graph, circuit_lib, sram_orgz_type, sram_model, rr_gsb, + cb_type, verbose); } } } @@ -967,16 +1034,12 @@ void build_flatten_connection_block_modules(ModuleManager& module_manager, * 1. Connection blocks * 2. Switch blocks *******************************************************************/ -void build_flatten_routing_modules(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const DeviceRRGSB& device_rr_gsb, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - const bool& verbose) { - +void build_flatten_routing_modules( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, + const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, const bool& verbose) { vtr::ScopedStartFinishTimer timer("Build routing modules..."); vtr::Point sb_range = device_rr_gsb.get_gsb_range(); @@ -988,37 +1051,20 @@ void build_flatten_routing_modules(ModuleManager& module_manager, if (false == rr_gsb.is_sb_exist()) { continue; } - build_switch_block_module(module_manager, - decoder_lib, - device_annotation, - device_ctx.grid, - device_ctx.rr_graph, - circuit_lib, - sram_orgz_type, sram_model, - rr_gsb, + build_switch_block_module(module_manager, decoder_lib, device_annotation, + device_ctx.grid, device_ctx.rr_graph, + circuit_lib, sram_orgz_type, sram_model, rr_gsb, verbose); } } - build_flatten_connection_block_modules(module_manager, - decoder_lib, - device_ctx, - device_annotation, - device_rr_gsb, - circuit_lib, - sram_orgz_type, sram_model, - CHANX, - verbose); + build_flatten_connection_block_modules( + module_manager, decoder_lib, device_ctx, device_annotation, device_rr_gsb, + circuit_lib, sram_orgz_type, sram_model, CHANX, verbose); - build_flatten_connection_block_modules(module_manager, - decoder_lib, - device_ctx, - device_annotation, - device_rr_gsb, - circuit_lib, - sram_orgz_type, sram_model, - CHANY, - verbose); + build_flatten_connection_block_modules( + module_manager, decoder_lib, device_ctx, device_annotation, device_rr_gsb, + circuit_lib, sram_orgz_type, sram_model, CHANY, verbose); } /******************************************************************** @@ -1029,63 +1075,46 @@ void build_flatten_routing_modules(ModuleManager& module_manager, * 1. Connection blocks * 2. Switch blocks * - * Note: this function SHOULD be called only when + * Note: this function SHOULD be called only when * the option compact_routing_hierarchy is turned on!!! *******************************************************************/ -void build_unique_routing_modules(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const DeviceRRGSB& device_rr_gsb, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - const bool& verbose) { - +void build_unique_routing_modules( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, + const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, const bool& verbose) { vtr::ScopedStartFinishTimer timer("Build unique routing modules..."); /* Build unique switch block modules */ for (size_t isb = 0; isb < device_rr_gsb.get_num_sb_unique_module(); ++isb) { const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(isb); - build_switch_block_module(module_manager, - decoder_lib, - device_annotation, - device_ctx.grid, - device_ctx.rr_graph, - circuit_lib, - sram_orgz_type, sram_model, - unique_mirror, + build_switch_block_module(module_manager, decoder_lib, device_annotation, + device_ctx.grid, device_ctx.rr_graph, circuit_lib, + sram_orgz_type, sram_model, unique_mirror, verbose); } /* Build unique X-direction connection block modules */ - for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANX); ++icb) { + for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANX); + ++icb) { const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(CHANX, icb); - build_connection_block_module(module_manager, - decoder_lib, - device_annotation, - device_ctx.grid, - device_ctx.rr_graph, - circuit_lib, - sram_orgz_type, sram_model, - unique_mirror, CHANX, - verbose); + build_connection_block_module( + module_manager, decoder_lib, device_annotation, device_ctx.grid, + device_ctx.rr_graph, circuit_lib, sram_orgz_type, sram_model, + unique_mirror, CHANX, verbose); } /* Build unique X-direction connection block modules */ - for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANY); ++icb) { + for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANY); + ++icb) { const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(CHANY, icb); - build_connection_block_module(module_manager, - decoder_lib, - device_annotation, - device_ctx.grid, - device_ctx.rr_graph, - circuit_lib, - sram_orgz_type, sram_model, - unique_mirror, CHANY, - verbose); + build_connection_block_module( + module_manager, decoder_lib, device_annotation, device_ctx.grid, + device_ctx.rr_graph, circuit_lib, sram_orgz_type, sram_model, + unique_mirror, CHANY, verbose); } } diff --git a/openfpga/src/fabric/build_routing_modules.h b/openfpga/src/fabric/build_routing_modules.h index d82ce3a69..59274bc11 100644 --- a/openfpga/src/fabric/build_routing_modules.h +++ b/openfpga/src/fabric/build_routing_modules.h @@ -4,13 +4,13 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ +#include "circuit_library.h" +#include "decoder_library.h" +#include "device_rr_gsb.h" +#include "module_manager.h" +#include "mux_library.h" #include "vpr_context.h" #include "vpr_device_annotation.h" -#include "device_rr_gsb.h" -#include "mux_library.h" -#include "decoder_library.h" -#include "circuit_library.h" -#include "module_manager.h" /******************************************************************** * Function declaration @@ -19,25 +19,19 @@ /* begin namespace openfpga */ namespace openfpga { -void build_flatten_routing_modules(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const DeviceRRGSB& device_rr_gsb, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - const bool& verbose); +void build_flatten_routing_modules( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, + const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, const bool& verbose); -void build_unique_routing_modules(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const DeviceRRGSB& device_rr_gsb, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - const bool& verbose); +void build_unique_routing_modules( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, + const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index 579344ae3..d20e3d355 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -2,33 +2,31 @@ * This file includes functions that are used to print the top-level * module for the FPGA fabric in Verilog format *******************************************************************/ -#include #include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from vpr library */ #include "vpr_utils.h" /* Headers from openfpgashell library */ -#include "command_exit_codes.h" - -#include "rr_gsb_utils.h" -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" -#include "module_manager_utils.h" -#include "build_top_module_utils.h" +#include "build_module_graph_utils.h" +#include "build_top_module.h" #include "build_top_module_connection.h" +#include "build_top_module_directs.h" #include "build_top_module_memory.h" #include "build_top_module_memory_bank.h" -#include "build_top_module_directs.h" - -#include "build_module_graph_utils.h" +#include "build_top_module_utils.h" +#include "command_exit_codes.h" +#include "module_manager_utils.h" #include "openfpga_device_grid_utils.h" -#include "build_top_module.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "rr_gsb_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -36,41 +34,44 @@ namespace openfpga { /******************************************************************** * Add a instance of a grid module to the top module *******************************************************************/ -static -size_t add_top_module_grid_instance(ModuleManager& module_manager, - const ModuleId& top_module, - t_physical_tile_type_ptr grid_type, - const e_side& border_side, - const vtr::Point& grid_coord) { +static size_t add_top_module_grid_instance( + ModuleManager& module_manager, const ModuleId& top_module, + t_physical_tile_type_ptr grid_type, const e_side& border_side, + const vtr::Point& grid_coord) { /* Find the module name for this type of grid */ std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); - std::string grid_module_name = generate_grid_block_module_name(grid_module_name_prefix, std::string(grid_type->name), is_io_type(grid_type), border_side); + std::string grid_module_name = generate_grid_block_module_name( + grid_module_name_prefix, std::string(grid_type->name), + is_io_type(grid_type), border_side); ModuleId grid_module = module_manager.find_module(grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); /* Record the instance id */ size_t grid_instance = module_manager.num_instance(top_module, grid_module); - /* Add the module to top_module */ + /* Add the module to top_module */ module_manager.add_child_module(top_module, grid_module, false); /* Set an unique name to the instance * Note: it is your risk to gurantee the name is unique! */ - std::string instance_name = generate_grid_block_instance_name(grid_module_name_prefix, std::string(grid_type->name), is_io_type(grid_type), border_side, grid_coord); - module_manager.set_child_instance_name(top_module, grid_module, grid_instance, instance_name); + std::string instance_name = generate_grid_block_instance_name( + grid_module_name_prefix, std::string(grid_type->name), + is_io_type(grid_type), border_side, grid_coord); + module_manager.set_child_instance_name(top_module, grid_module, grid_instance, + instance_name); return grid_instance; } /******************************************************************** * Add all the grids as sub-modules across the fabric - * The grid modules are created for each unique type of grid (based + * The grid modules are created for each unique type of grid (based * on the type in data structure data_structure * Here, we will iterate over the full fabric (coordinates) - * and instanciate the grid modules + * and instanciate the grid modules * - * Return an 2-D array of instance ids of the grid modules that + * Return an 2-D array of instance ids of the grid modules that * have been added * - * This function assumes an island-style floorplanning for FPGA fabric + * This function assumes an island-style floorplanning for FPGA fabric * * * +-----------------------------------+ @@ -91,73 +92,84 @@ size_t add_top_module_grid_instance(ModuleManager& module_manager, * +-----------------------------------+ * *******************************************************************/ -static -vtr::Matrix add_top_module_grid_instances(ModuleManager& module_manager, - const ModuleId& top_module, - const DeviceGrid& grids) { - +static vtr::Matrix add_top_module_grid_instances( + ModuleManager& module_manager, const ModuleId& top_module, + const DeviceGrid& grids) { vtr::ScopedStartFinishTimer timer("Add grid instances to top module"); /* Reserve an array for the instance ids */ - vtr::Matrix grid_instance_ids({grids.width(), grids.height()}); + vtr::Matrix grid_instance_ids({grids.width(), grids.height()}); grid_instance_ids.fill(size_t(-1)); /* Instanciate I/O grids */ /* Create the coordinate range for each side of FPGA fabric */ - std::map>> io_coordinates = generate_perimeter_grid_coordinates( grids); + std::map>> io_coordinates = + generate_perimeter_grid_coordinates(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)) { + if (true == + is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) { continue; - } + } /* Skip width, 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)) { - /* Find the root of this grid, the instance id should be valid. + if ((0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset) || + (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) { + /* Find the root of this grid, the instance id should be valid. * We just copy it here */ - vtr::Point root_grid_coord(io_coordinate.x() - grids[io_coordinate.x()][io_coordinate.y()].width_offset, - io_coordinate.y() - grids[io_coordinate.x()][io_coordinate.y()].height_offset); - VTR_ASSERT(size_t(-1) != grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]); - grid_instance_ids[io_coordinate.x()][io_coordinate.y()] = grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]; + vtr::Point root_grid_coord( + io_coordinate.x() - + grids[io_coordinate.x()][io_coordinate.y()].width_offset, + io_coordinate.y() - + grids[io_coordinate.x()][io_coordinate.y()].height_offset); + VTR_ASSERT(size_t(-1) != + grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]); + grid_instance_ids[io_coordinate.x()][io_coordinate.y()] = + grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]; continue; } /* Add a grid module to top_module*/ - grid_instance_ids[io_coordinate.x()][io_coordinate.y()] = add_top_module_grid_instance(module_manager, top_module, grids[io_coordinate.x()][io_coordinate.y()].type, io_side, io_coordinate); + grid_instance_ids[io_coordinate.x()][io_coordinate.y()] = + add_top_module_grid_instance( + module_manager, top_module, + grids[io_coordinate.x()][io_coordinate.y()].type, io_side, + io_coordinate); } } /* Instanciate core grids * IMPORTANT: sequence matters here, it impacts the I/O indexing. - * We should follow the same sequence as the build_io_location_map()! - * If you change the sequence of walking through grids here, you should change it in the build_io_location map()! + * We should follow the same sequence as the build_io_location_map()! + * If you change the sequence of walking through grids here, you should change + * it in the build_io_location map()! */ for (size_t ix = 1; ix < grids.width() - 1; ++ix) { for (size_t iy = 1; iy < grids.height() - 1; ++iy) { /* Bypass EMPTY grid */ 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)) { - /* Find the root of this grid, the instance id should be valid. + if ((0 < grids[ix][iy].width_offset) || + (0 < grids[ix][iy].height_offset)) { + /* Find the root of this grid, the instance id should be valid. * We just copy it here */ vtr::Point root_grid_coord(ix - grids[ix][iy].width_offset, iy - grids[ix][iy].height_offset); - VTR_ASSERT(size_t(-1) != grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]); - grid_instance_ids[ix][iy] = grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]; + VTR_ASSERT(size_t(-1) != + grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]); + grid_instance_ids[ix][iy] = + grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]; continue; } /* Add a grid module to top_module*/ vtr::Point grid_coord(ix, iy); - grid_instance_ids[ix][iy] = add_top_module_grid_instance(module_manager, top_module, - grids[ix][iy].type, - NUM_SIDES, grid_coord); + grid_instance_ids[ix][iy] = add_top_module_grid_instance( + module_manager, top_module, grids[ix][iy].type, NUM_SIDES, grid_coord); } } @@ -166,52 +178,55 @@ vtr::Matrix add_top_module_grid_instances(ModuleManager& module_manager, /******************************************************************** * Add switch blocks across the FPGA fabric to the top-level module - * Return an 2-D array of instance ids of the switch blocks that + * Return an 2-D array of instance ids of the switch blocks that * have been added *******************************************************************/ -static -vtr::Matrix add_top_module_switch_block_instances(ModuleManager& module_manager, - const ModuleId& top_module, - const DeviceRRGSB& device_rr_gsb, - const bool& compact_routing_hierarchy) { - +static vtr::Matrix add_top_module_switch_block_instances( + ModuleManager& module_manager, const ModuleId& top_module, + const DeviceRRGSB& device_rr_gsb, const bool& compact_routing_hierarchy) { vtr::ScopedStartFinishTimer timer("Add switch block instances to top module"); vtr::Point sb_range = device_rr_gsb.get_gsb_range(); /* Reserve an array for the instance ids */ - vtr::Matrix sb_instance_ids({sb_range.x(), sb_range.y()}); + vtr::Matrix sb_instance_ids({sb_range.x(), sb_range.y()}); sb_instance_ids.fill(size_t(-1)); for (size_t ix = 0; ix < sb_range.x(); ++ix) { for (size_t iy = 0; iy < sb_range.y(); ++iy) { - /* If we use compact routing hierarchy, we should instanciate the unique module of SB */ + /* If we use compact routing hierarchy, we should instanciate the unique + * module of SB */ const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); - if ( false == rr_gsb.is_sb_exist() ) { + if (false == rr_gsb.is_sb_exist()) { continue; } vtr::Point sb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); if (true == compact_routing_hierarchy) { vtr::Point sb_coord(ix, iy); - const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(sb_coord); - sb_coordinate.set_x(unique_mirror.get_sb_x()); - sb_coordinate.set_y(unique_mirror.get_sb_y()); - } - std::string sb_module_name = generate_switch_block_module_name(sb_coordinate); + const RRGSB& unique_mirror = + device_rr_gsb.get_sb_unique_module(sb_coord); + sb_coordinate.set_x(unique_mirror.get_sb_x()); + sb_coordinate.set_y(unique_mirror.get_sb_y()); + } + std::string sb_module_name = + generate_switch_block_module_name(sb_coordinate); ModuleId sb_module = module_manager.find_module(sb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); /* Record the instance id */ - sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()] = module_manager.num_instance(top_module, sb_module); - /* Add the module to top_module */ + sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()] = + module_manager.num_instance(top_module, sb_module); + /* Add the module to top_module */ module_manager.add_child_module(top_module, sb_module, false); /* Set an unique name to the instance * Note: it is your risk to gurantee the name is unique! */ - module_manager.set_child_instance_name(top_module, sb_module, - sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()], - generate_switch_block_module_name(vtr::Point(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()))); + module_manager.set_child_instance_name( + top_module, sb_module, + sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()], + generate_switch_block_module_name( + vtr::Point(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()))); } } @@ -221,54 +236,60 @@ vtr::Matrix add_top_module_switch_block_instances(ModuleManager& module_ /******************************************************************** * Add switch blocks across the FPGA fabric to the top-level module *******************************************************************/ -static -vtr::Matrix add_top_module_connection_block_instances(ModuleManager& module_manager, - const ModuleId& top_module, - const DeviceRRGSB& device_rr_gsb, - const t_rr_type& cb_type, - const bool& compact_routing_hierarchy) { - - vtr::ScopedStartFinishTimer timer("Add connection block instances to top module"); +static vtr::Matrix add_top_module_connection_block_instances( + ModuleManager& module_manager, const ModuleId& top_module, + const DeviceRRGSB& device_rr_gsb, const t_rr_type& cb_type, + const bool& compact_routing_hierarchy) { + vtr::ScopedStartFinishTimer timer( + "Add connection block instances to top module"); vtr::Point cb_range = device_rr_gsb.get_gsb_range(); /* Reserve an array for the instance ids */ - vtr::Matrix cb_instance_ids({cb_range.x(), cb_range.y()}); + vtr::Matrix cb_instance_ids({cb_range.x(), cb_range.y()}); cb_instance_ids.fill(size_t(-1)); for (size_t ix = 0; ix < cb_range.x(); ++ix) { for (size_t iy = 0; iy < cb_range.y(); ++iy) { /* Check if the connection block exists in the device! - * Some of them do NOT exist due to heterogeneous blocks (height > 1) + * Some of them do NOT exist due to heterogeneous blocks (height > 1) * We will skip those modules */ const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); - vtr::Point cb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); - if ( false == rr_gsb.is_cb_exist(cb_type) ) { + vtr::Point cb_coordinate(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); + if (false == rr_gsb.is_cb_exist(cb_type)) { continue; } - /* If we use compact routing hierarchy, we should instanciate the unique module of SB */ + /* If we use compact routing hierarchy, we should instanciate the unique + * module of SB */ if (true == compact_routing_hierarchy) { vtr::Point cb_coord(ix, iy); /* Note: use GSB coordinate when inquire for unique modules!!! */ - const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(cb_type, cb_coord); - cb_coordinate.set_x(unique_mirror.get_cb_x(cb_type)); - cb_coordinate.set_y(unique_mirror.get_cb_y(cb_type)); - } - std::string cb_module_name = generate_connection_block_module_name(cb_type, cb_coordinate); + const RRGSB& unique_mirror = + device_rr_gsb.get_cb_unique_module(cb_type, cb_coord); + cb_coordinate.set_x(unique_mirror.get_cb_x(cb_type)); + cb_coordinate.set_y(unique_mirror.get_cb_y(cb_type)); + } + std::string cb_module_name = + generate_connection_block_module_name(cb_type, cb_coordinate); ModuleId cb_module = module_manager.find_module(cb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); /* Record the instance id */ - cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)] = module_manager.num_instance(top_module, cb_module); - /* Add the module to top_module */ + cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)] = + module_manager.num_instance(top_module, cb_module); + /* Add the module to top_module */ module_manager.add_child_module(top_module, cb_module, false); /* Set an unique name to the instance * Note: it is your risk to gurantee the name is unique! */ - std::string cb_instance_name = generate_connection_block_module_name(cb_type, vtr::Point(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type))); - module_manager.set_child_instance_name(top_module, cb_module, - cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)], - cb_instance_name); + std::string cb_instance_name = generate_connection_block_module_name( + cb_type, + vtr::Point(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type))); + module_manager.set_child_instance_name( + top_module, cb_module, + cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)], + cb_instance_name); } } @@ -279,8 +300,9 @@ vtr::Matrix add_top_module_connection_block_instances(ModuleManager& mod * Add the I/O children to the top-level module, which impacts the I/O indexing * This is the default function to build the I/O sequence/indexing * The I/O children is added in a maze shape - * The function supports I/Os in the center of grids, starting from the bottom-left corner and ending at the center - * + * The function supports I/Os in the center of grids, starting from the + *bottom-left corner and ending at the center + * * +----------------------+ * |+--------------------+| * ||+------------------+|| @@ -291,35 +313,39 @@ vtr::Matrix add_top_module_connection_block_instances(ModuleManager& mod * ||+-------------------+| * |+---------------------+ * ^ - * io[0] + * io[0] *******************************************************************/ -static -void add_top_module_io_children(ModuleManager& module_manager, - const ModuleId& top_module, - const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids) { +static void add_top_module_io_children( + ModuleManager& module_manager, const ModuleId& top_module, + const DeviceGrid& grids, const vtr::Matrix& grid_instance_ids) { /* Create the coordinate range for the perimeter I/Os of FPGA fabric */ - std::map>> io_coordinates = generate_perimeter_grid_coordinates( grids); + std::map>> io_coordinates = + generate_perimeter_grid_coordinates(grids); for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { for (const vtr::Point& io_coord : io_coordinates[io_side]) { /* Bypass EMPTY grid */ if (true == is_empty_type(grids[io_coord.x()][io_coord.y()].type)) { continue; - } + } /* Skip width, height > 1 tiles (mostly heterogeneous blocks) */ - if ( (0 < grids[io_coord.x()][io_coord.y()].width_offset) - || (0 < grids[io_coord.x()][io_coord.y()].height_offset)) { + if ((0 < grids[io_coord.x()][io_coord.y()].width_offset) || + (0 < grids[io_coord.x()][io_coord.y()].height_offset)) { continue; } /* Find the module name for this type of grid */ - t_physical_tile_type_ptr grid_type = grids[io_coord.x()][io_coord.y()].type; + t_physical_tile_type_ptr grid_type = + grids[io_coord.x()][io_coord.y()].type; std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); - std::string grid_module_name = generate_grid_block_module_name(grid_module_name_prefix, std::string(grid_type->name), is_io_type(grid_type), io_side); + std::string grid_module_name = generate_grid_block_module_name( + grid_module_name_prefix, std::string(grid_type->name), + is_io_type(grid_type), io_side); ModuleId grid_module = module_manager.find_module(grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); /* Add a I/O children to top_module*/ - module_manager.add_io_child(top_module, grid_module, grid_instance_ids[io_coord.x()][io_coord.y()], vtr::Point(io_coord.x(), io_coord.y())); + module_manager.add_io_child(top_module, grid_module, + grid_instance_ids[io_coord.x()][io_coord.y()], + vtr::Point(io_coord.x(), io_coord.y())); } } @@ -329,7 +355,7 @@ void add_top_module_io_children(ModuleManager& module_manager, size_t ymin = 1; size_t ymax = grids.height() - 2; std::vector> coords; - while (xmin < xmax && ymin < ymax) { + while (xmin < xmax && ymin < ymax) { for (size_t iy = ymin; iy < ymax + 1; iy++) { coords.push_back(vtr::Point(xmin, iy)); } @@ -370,58 +396,55 @@ void add_top_module_io_children(ModuleManager& module_manager, /* Bypass EMPTY grid */ if (true == is_empty_type(grids[coord.x()][coord.y()].type)) { continue; - } + } /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ - if ( (0 < grids[coord.x()][coord.y()].width_offset) - || (0 < grids[coord.x()][coord.y()].height_offset)) { + if ((0 < grids[coord.x()][coord.y()].width_offset) || + (0 < grids[coord.x()][coord.y()].height_offset)) { continue; } /* Find the module name for this type of grid */ t_physical_tile_type_ptr grid_type = grids[coord.x()][coord.y()].type; std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); - std::string grid_module_name = generate_grid_block_module_name(grid_module_name_prefix, std::string(grid_type->name), is_io_type(grid_type), NUM_SIDES); + std::string grid_module_name = generate_grid_block_module_name( + grid_module_name_prefix, std::string(grid_type->name), + is_io_type(grid_type), NUM_SIDES); ModuleId grid_module = module_manager.find_module(grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); /* Add a I/O children to top_module*/ - module_manager.add_io_child(top_module, grid_module, grid_instance_ids[coord.x()][coord.y()], vtr::Point(coord.x(), coord.y())); + module_manager.add_io_child(top_module, grid_module, + grid_instance_ids[coord.x()][coord.y()], + vtr::Point(coord.x(), coord.y())); } } /******************************************************************** * Print the top-level module for the FPGA fabric in Verilog format - * This function will + * This function will * 1. name the top-level module - * 2. include dependent netlists + * 2. include dependent netlists * - User defined netlists * - Auto-generated netlists * 3. Add the submodules to the top-level graph * 4. Add module nets to connect datapath ports * 5. Add module nets/submodules to connect configuration ports *******************************************************************/ -int build_top_module(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - MemoryBankShiftRegisterBanks& blwl_sr_banks, - const CircuitLibrary& circuit_lib, - 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, - const ArchDirect& arch_direct, - const ConfigProtocol& config_protocol, - const CircuitModelId& sram_model, - const bool& frame_view, - const bool& compact_routing_hierarchy, - const bool& duplicate_grid_pin, - const FabricKey& fabric_key, - const bool& generate_random_fabric_key) { - +int build_top_module( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + MemoryBankShiftRegisterBanks& blwl_sr_banks, + const CircuitLibrary& circuit_lib, + 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, + const ArchDirect& arch_direct, const ConfigProtocol& config_protocol, + const CircuitModelId& sram_model, const bool& frame_view, + const bool& compact_routing_hierarchy, const bool& duplicate_grid_pin, + const FabricKey& fabric_key, const bool& generate_random_fabric_key) { vtr::ScopedStartFinishTimer timer("Build FPGA fabric module"); int status = CMD_EXEC_SUCCESS; - /* Create a module as the top-level fabric, and add it to the module manager */ + /* Create a module as the top-level fabric, and add it to the module manager + */ std::string top_module_name = generate_fpga_top_module_name(); ModuleId top_module = module_manager.add_module(top_module_name); @@ -429,18 +452,25 @@ int build_top_module(ModuleManager& module_manager, module_manager.set_module_usage(top_module, ModuleManager::MODULE_TOP); std::map> cb_instance_ids; - + /* Add sub modules, which are grid, SB and CBX/CBY modules as instances */ /* Add all the grids across the fabric */ - vtr::Matrix grid_instance_ids = add_top_module_grid_instances(module_manager, top_module, grids); + vtr::Matrix grid_instance_ids = + add_top_module_grid_instances(module_manager, top_module, grids); /* Add all the SBs across the fabric */ - vtr::Matrix sb_instance_ids = add_top_module_switch_block_instances(module_manager, top_module, device_rr_gsb, compact_routing_hierarchy); + vtr::Matrix sb_instance_ids = add_top_module_switch_block_instances( + module_manager, top_module, device_rr_gsb, compact_routing_hierarchy); /* Add all the CBX and CBYs across the fabric */ - cb_instance_ids[CHANX] = add_top_module_connection_block_instances(module_manager, top_module, device_rr_gsb, CHANX, compact_routing_hierarchy); - cb_instance_ids[CHANY] = add_top_module_connection_block_instances(module_manager, top_module, device_rr_gsb, CHANY, compact_routing_hierarchy); + cb_instance_ids[CHANX] = add_top_module_connection_block_instances( + module_manager, top_module, device_rr_gsb, CHANX, + compact_routing_hierarchy); + cb_instance_ids[CHANY] = add_top_module_connection_block_instances( + module_manager, top_module, device_rr_gsb, CHANY, + compact_routing_hierarchy); /* Update I/O children list */ - add_top_module_io_children(module_manager, top_module, grids, grid_instance_ids); + add_top_module_io_children(module_manager, top_module, grids, + grid_instance_ids); /* Add nets when we need a complete fabric modeling, * which is required by downstream functions @@ -450,59 +480,61 @@ int build_top_module(ModuleManager& module_manager, reserve_module_manager_module_nets(module_manager, top_module); /* Add module nets to connect the sub modules */ - add_top_module_nets_connect_grids_and_gsbs(module_manager, top_module, - vpr_device_annotation, - grids, grid_instance_ids, - rr_graph, device_rr_gsb, sb_instance_ids, cb_instance_ids, - compact_routing_hierarchy, duplicate_grid_pin); + add_top_module_nets_connect_grids_and_gsbs( + module_manager, top_module, vpr_device_annotation, grids, + grid_instance_ids, rr_graph, device_rr_gsb, sb_instance_ids, + cb_instance_ids, compact_routing_hierarchy, duplicate_grid_pin); /* Add inter-CLB direct connections */ - add_top_module_nets_tile_direct_connections(module_manager, top_module, circuit_lib, - vpr_device_annotation, - grids, grid_instance_ids, - tile_direct, arch_direct); + add_top_module_nets_tile_direct_connections( + module_manager, top_module, circuit_lib, vpr_device_annotation, grids, + grid_instance_ids, tile_direct, arch_direct); } - /* Add global ports from grid ports that are defined as global in tile annotation */ - status = add_top_module_global_ports_from_grid_modules(module_manager, top_module, tile_annotation, vpr_device_annotation, grids, grid_instance_ids); + /* Add global ports from grid ports that are defined as global in tile + * annotation */ + status = add_top_module_global_ports_from_grid_modules( + module_manager, top_module, tile_annotation, vpr_device_annotation, grids, + grid_instance_ids); if (CMD_EXEC_FATAL_ERROR == status) { return status; } - /* Add GPIO ports from the sub-modules under this Verilog module - * For top-level module, we follow a special sequencing for I/O modules. So we rebuild the I/O children list here + /* Add GPIO ports from the sub-modules under this Verilog module + * For top-level module, we follow a special sequencing for I/O modules. So we + * rebuild the I/O children list here */ add_module_gpio_ports_from_child_modules(module_manager, top_module); /* Organize the list of memory modules and instances * If we have an empty fabric key, we organize the memory modules as routine - * Otherwise, we will load the fabric key directly + * Otherwise, we will load the fabric key directly */ if (true == fabric_key.empty()) { - organize_top_module_memory_modules(module_manager, top_module, - circuit_lib, config_protocol, sram_model, - grids, grid_instance_ids, - device_rr_gsb, sb_instance_ids, cb_instance_ids, - compact_routing_hierarchy); + organize_top_module_memory_modules( + module_manager, top_module, circuit_lib, config_protocol, sram_model, + grids, grid_instance_ids, device_rr_gsb, sb_instance_ids, cb_instance_ids, + compact_routing_hierarchy); } else { VTR_ASSERT_SAFE(false == fabric_key.empty()); - /* Throw a fatal error when the fabric key has a mismatch in region organization. - * between architecture file and fabric key + /* Throw a fatal error when the fabric key has a mismatch in region + * organization. between architecture file and fabric key */ if (size_t(config_protocol.num_regions()) != fabric_key.regions().size()) { - VTR_LOG_ERROR("Fabric key has a different number of configurable regions (='%ld') than architecture definition (=%d)!\n", - fabric_key.regions().size(), - config_protocol.num_regions()); + VTR_LOG_ERROR( + "Fabric key has a different number of configurable regions (='%ld') " + "than architecture definition (=%d)!\n", + fabric_key.regions().size(), config_protocol.num_regions()); return CMD_EXEC_FATAL_ERROR; } - status = load_top_module_memory_modules_from_fabric_key(module_manager, top_module, - circuit_lib, config_protocol, - fabric_key); + status = load_top_module_memory_modules_from_fabric_key( + module_manager, top_module, circuit_lib, config_protocol, fabric_key); if (CMD_EXEC_FATAL_ERROR == status) { return status; } - status = load_top_module_shift_register_banks_from_fabric_key(fabric_key, blwl_sr_banks); + status = load_top_module_shift_register_banks_from_fabric_key( + fabric_key, blwl_sr_banks); if (CMD_EXEC_FATAL_ERROR == status) { return status; } @@ -510,56 +542,63 @@ int build_top_module(ModuleManager& module_manager, /* Shuffle the configurable children in a random sequence */ if (true == generate_random_fabric_key) { - shuffle_top_module_configurable_children(module_manager, top_module, config_protocol); + shuffle_top_module_configurable_children(module_manager, top_module, + config_protocol); } /* Build shift register bank detailed connections */ - sync_memory_bank_shift_register_banks_with_config_protocol_settings(module_manager, - blwl_sr_banks, - config_protocol, - top_module, - circuit_lib); + sync_memory_bank_shift_register_banks_with_config_protocol_settings( + module_manager, blwl_sr_banks, config_protocol, top_module, circuit_lib); /* Add shared SRAM ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it */ - size_t module_num_shared_config_bits = find_module_num_shared_config_bits_from_child_modules(module_manager, top_module); + size_t module_num_shared_config_bits = + find_module_num_shared_config_bits_from_child_modules(module_manager, + top_module); if (0 < module_num_shared_config_bits) { - add_reserved_sram_ports_to_module_manager(module_manager, top_module, module_num_shared_config_bits); + add_reserved_sram_ports_to_module_manager(module_manager, top_module, + module_num_shared_config_bits); } /* Add SRAM ports from the sub-modules under this Verilog module - * This is a much easier job after adding sub modules (instances), - * we just need to find all the I/O ports from the child modules and build a list of it + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it */ - TopModuleNumConfigBits top_module_num_config_bits = find_top_module_regional_num_config_bit(module_manager, top_module, circuit_lib, sram_model, config_protocol.type()); + TopModuleNumConfigBits top_module_num_config_bits = + find_top_module_regional_num_config_bit(module_manager, top_module, + circuit_lib, sram_model, + config_protocol.type()); if (!top_module_num_config_bits.empty()) { - add_top_module_sram_ports(module_manager, top_module, - circuit_lib, sram_model, - config_protocol, - const_cast(blwl_sr_banks), - top_module_num_config_bits); + add_top_module_sram_ports( + module_manager, top_module, circuit_lib, sram_model, config_protocol, + const_cast(blwl_sr_banks), + top_module_num_config_bits); } /* Add module nets to connect memory cells inside - * This is a one-shot addition that covers all the memory modules in this pb module! + * This is a one-shot addition that covers all the memory modules in this pb + * module! */ if (false == frame_view) { if (0 < module_manager.configurable_children(top_module).size()) { - add_top_module_nets_memory_config_bus(module_manager, decoder_lib, blwl_sr_banks, - top_module, - circuit_lib, - config_protocol, circuit_lib.design_tech_type(sram_model), - top_module_num_config_bits); + add_top_module_nets_memory_config_bus( + module_manager, decoder_lib, blwl_sr_banks, top_module, circuit_lib, + config_protocol, circuit_lib.design_tech_type(sram_model), + top_module_num_config_bits); } } /* 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 a list of it - * @note This function is called after the add_top_module_nets_memory_config_bus() because it may add some sub modules + * 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 + * a list of it + * @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); diff --git a/openfpga/src/fabric/build_top_module.h b/openfpga/src/fabric/build_top_module.h index a78846ee2..613f88990 100644 --- a/openfpga/src/fabric/build_top_module.h +++ b/openfpga/src/fabric/build_top_module.h @@ -6,20 +6,21 @@ *******************************************************************/ #include -#include "vtr_geometry.h" -#include "device_grid.h" -#include "vpr_device_annotation.h" -#include "tile_annotation.h" -#include "rr_graph_view.h" -#include "device_rr_gsb.h" -#include "circuit_library.h" -#include "decoder_library.h" -#include "tile_direct.h" + #include "arch_direct.h" +#include "circuit_library.h" #include "config_protocol.h" -#include "module_manager.h" +#include "decoder_library.h" +#include "device_grid.h" +#include "device_rr_gsb.h" #include "fabric_key.h" #include "memory_bank_shift_register_banks.h" +#include "module_manager.h" +#include "rr_graph_view.h" +#include "tile_annotation.h" +#include "tile_direct.h" +#include "vpr_device_annotation.h" +#include "vtr_geometry.h" /******************************************************************** * Function declaration @@ -28,24 +29,17 @@ /* begin namespace openfpga */ namespace openfpga { -int build_top_module(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - MemoryBankShiftRegisterBanks& blwl_sr_banks, - const CircuitLibrary& circuit_lib, - 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, - const ArchDirect& arch_direct, - const ConfigProtocol& config_protocol, - const CircuitModelId& sram_model, - const bool& frame_view, - const bool& compact_routing_hierarchy, - const bool& duplicate_grid_pin, - const FabricKey& fabric_key, - const bool& generate_random_fabric_key); +int build_top_module( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + MemoryBankShiftRegisterBanks& blwl_sr_banks, + const CircuitLibrary& circuit_lib, + 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, + const ArchDirect& arch_direct, const ConfigProtocol& config_protocol, + const CircuitModelId& sram_model, const bool& frame_view, + const bool& compact_routing_hierarchy, const bool& duplicate_grid_pin, + const FabricKey& fabric_key, const bool& generate_random_fabric_key); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index 2f8133f57..01c3a5a01 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * This file include most utilized functions for building connections + * This file include most utilized functions for building connections * inside the module graph for FPGA fabric *******************************************************************/ /* Headers from vtrutil library */ @@ -13,32 +13,30 @@ #include "openfpga_side_manager.h" /* Headers from vpr library */ -#include "vpr_utils.h" - -#include "openfpga_reserved_words.h" +#include "build_routing_module_utils.h" +#include "build_top_module_connection.h" +#include "build_top_module_utils.h" +#include "module_manager_utils.h" +#include "openfpga_device_grid_utils.h" #include "openfpga_naming.h" +#include "openfpga_physical_tile_utils.h" +#include "openfpga_reserved_words.h" +#include "openfpga_rr_graph_utils.h" #include "pb_type_utils.h" #include "rr_gsb_utils.h" -#include "openfpga_physical_tile_utils.h" -#include "openfpga_device_grid_utils.h" -#include "openfpga_rr_graph_utils.h" -#include "module_manager_utils.h" - -#include "build_routing_module_utils.h" -#include "build_top_module_utils.h" -#include "build_top_module_connection.h" +#include "vpr_utils.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * Add module nets to connect a GSB to adjacent grid ports/pins + * Add module nets to connect a GSB to adjacent grid ports/pins * as well as connection blocks * This function will create nets for the following types of connections * between grid output pins of Switch block and adjacent grids * In this case, the net source is the grid pin, while the net sink * is the switch block pin - * + * * +------------+ +------------+ * | | | | * | Grid | | Grid | @@ -63,101 +61,135 @@ namespace openfpga { * *******************************************************************/ -static -void add_top_module_nets_connect_grids_and_sb(ModuleManager& module_manager, - const ModuleId& top_module, - const VprDeviceAnnotation& vpr_device_annotation, - const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, - const RRGSB& rr_gsb, - const vtr::Matrix& sb_instance_ids, - const bool& compact_routing_hierarchy) { - +static void add_top_module_nets_connect_grids_and_sb( + ModuleManager& module_manager, const ModuleId& top_module, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const vtr::Matrix& grid_instance_ids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, const RRGSB& rr_gsb, + const vtr::Matrix& sb_instance_ids, + const bool& compact_routing_hierarchy) { /* Skip those Switch blocks that do not exist */ if (false == rr_gsb.is_sb_exist()) { return; } - /* We could have two different coordinators, one is the instance, the other is the module */ - vtr::Point instance_sb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); + /* We could have two different coordinators, one is the instance, the other is + * the module */ + vtr::Point instance_sb_coordinate(rr_gsb.get_sb_x(), + rr_gsb.get_sb_y()); vtr::Point module_gsb_coordinate(rr_gsb.get_x(), rr_gsb.get_y()); - /* If we use compact routing hierarchy, we should find the unique module of CB, which is added to the top module */ + /* If we use compact routing hierarchy, we should find the unique module of + * CB, which is added to the top module */ if (true == compact_routing_hierarchy) { vtr::Point gsb_coord(rr_gsb.get_x(), rr_gsb.get_y()); const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(gsb_coord); - module_gsb_coordinate.set_x(unique_mirror.get_x()); - module_gsb_coordinate.set_y(unique_mirror.get_y()); - } + module_gsb_coordinate.set_x(unique_mirror.get_x()); + module_gsb_coordinate.set_y(unique_mirror.get_y()); + } /* This is the source cb that is added to the top module */ const RRGSB& module_sb = device_rr_gsb.get_gsb(module_gsb_coordinate); - vtr::Point module_sb_coordinate(module_sb.get_sb_x(), module_sb.get_sb_y()); + vtr::Point module_sb_coordinate(module_sb.get_sb_x(), + module_sb.get_sb_y()); /* Collect sink-related information */ - std::string sink_sb_module_name = generate_switch_block_module_name(module_sb_coordinate); + std::string sink_sb_module_name = + generate_switch_block_module_name(module_sb_coordinate); ModuleId sink_sb_module = module_manager.find_module(sink_sb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(sink_sb_module)); - size_t sink_sb_instance = sb_instance_ids[instance_sb_coordinate.x()][instance_sb_coordinate.y()]; + size_t sink_sb_instance = + sb_instance_ids[instance_sb_coordinate.x()][instance_sb_coordinate.y()]; /* Connect grid output pins (OPIN) to switch block grid pins */ for (size_t side = 0; side < module_sb.get_num_sides(); ++side) { SideManager side_manager(side); - for (size_t inode = 0; inode < module_sb.get_num_opin_nodes(side_manager.get_side()); ++inode) { + for (size_t inode = 0; + inode < module_sb.get_num_opin_nodes(side_manager.get_side()); + ++inode) { /* Collect source-related information */ - /* Generate the grid module name by considering if it locates on the border */ - vtr::Point grid_coordinate(rr_graph.node_xlow(rr_gsb.get_opin_node(side_manager.get_side(), inode)), - rr_graph.node_ylow(rr_gsb.get_opin_node(side_manager.get_side(), inode))); - std::string src_grid_module_name = generate_grid_block_module_name_in_top_module(std::string(GRID_MODULE_NAME_PREFIX), grids, grid_coordinate); - ModuleId src_grid_module = module_manager.find_module(src_grid_module_name); + /* Generate the grid module name by considering if it locates on the + * border */ + vtr::Point grid_coordinate( + rr_graph.node_xlow( + rr_gsb.get_opin_node(side_manager.get_side(), inode)), + rr_graph.node_ylow( + rr_gsb.get_opin_node(side_manager.get_side(), inode))); + std::string src_grid_module_name = + generate_grid_block_module_name_in_top_module( + std::string(GRID_MODULE_NAME_PREFIX), grids, grid_coordinate); + ModuleId src_grid_module = + module_manager.find_module(src_grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(src_grid_module)); - size_t src_grid_instance = grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()]; - size_t src_grid_pin_index = rr_graph.node_pin_num(rr_gsb.get_opin_node(side_manager.get_side(), inode)); + size_t src_grid_instance = + grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()]; + size_t src_grid_pin_index = rr_graph.node_pin_num( + rr_gsb.get_opin_node(side_manager.get_side(), inode)); - t_physical_tile_type_ptr grid_type_descriptor = grids[grid_coordinate.x()][grid_coordinate.y()].type; - size_t src_grid_pin_width = grid_type_descriptor->pin_width_offset[src_grid_pin_index]; - size_t src_grid_pin_height = grid_type_descriptor->pin_height_offset[src_grid_pin_index]; - BasicPort src_grid_pin_info = vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor, src_grid_pin_index); + t_physical_tile_type_ptr grid_type_descriptor = + grids[grid_coordinate.x()][grid_coordinate.y()].type; + size_t src_grid_pin_width = + grid_type_descriptor->pin_width_offset[src_grid_pin_index]; + size_t src_grid_pin_height = + grid_type_descriptor->pin_height_offset[src_grid_pin_index]; + BasicPort src_grid_pin_info = + vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor, + src_grid_pin_index); VTR_ASSERT(true == src_grid_pin_info.is_valid()); - int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(grid_type_descriptor, src_grid_pin_index); - VTR_ASSERT(OPEN != subtile_index && subtile_index < grid_type_descriptor->capacity); - std::string src_grid_port_name = generate_grid_port_name(src_grid_pin_width, src_grid_pin_height, subtile_index, - get_rr_graph_single_node_side(rr_graph, rr_gsb.get_opin_node(side_manager.get_side(), inode)), - src_grid_pin_info); - ModulePortId src_grid_port_id = module_manager.find_module_port(src_grid_module, src_grid_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(src_grid_module, src_grid_port_id)); - BasicPort src_grid_port = module_manager.module_port(src_grid_module, src_grid_port_id); + int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index( + grid_type_descriptor, src_grid_pin_index); + VTR_ASSERT(OPEN != subtile_index && + subtile_index < grid_type_descriptor->capacity); + std::string src_grid_port_name = generate_grid_port_name( + src_grid_pin_width, src_grid_pin_height, subtile_index, + get_rr_graph_single_node_side( + rr_graph, rr_gsb.get_opin_node(side_manager.get_side(), inode)), + src_grid_pin_info); + ModulePortId src_grid_port_id = + module_manager.find_module_port(src_grid_module, src_grid_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(src_grid_module, + src_grid_port_id)); + BasicPort src_grid_port = + module_manager.module_port(src_grid_module, src_grid_port_id); /* Collect sink-related information */ - vtr::Point sink_sb_port_coord(rr_graph.node_xlow(module_sb.get_opin_node(side_manager.get_side(), inode)), - rr_graph.node_ylow(module_sb.get_opin_node(side_manager.get_side(), inode))); - std::string sink_sb_port_name = generate_sb_module_grid_port_name(side_manager.get_side(), - get_rr_graph_single_node_side(rr_graph, module_sb.get_opin_node(side_manager.get_side(), inode)), - grids, - vpr_device_annotation, - rr_graph, - module_sb.get_opin_node(side_manager.get_side(), inode)); - ModulePortId sink_sb_port_id = module_manager.find_module_port(sink_sb_module, sink_sb_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(sink_sb_module, sink_sb_port_id)); - BasicPort sink_sb_port = module_manager.module_port(sink_sb_module, sink_sb_port_id); + vtr::Point sink_sb_port_coord( + rr_graph.node_xlow( + module_sb.get_opin_node(side_manager.get_side(), inode)), + rr_graph.node_ylow( + module_sb.get_opin_node(side_manager.get_side(), inode))); + std::string sink_sb_port_name = generate_sb_module_grid_port_name( + side_manager.get_side(), + get_rr_graph_single_node_side( + rr_graph, module_sb.get_opin_node(side_manager.get_side(), inode)), + grids, vpr_device_annotation, rr_graph, + module_sb.get_opin_node(side_manager.get_side(), inode)); + ModulePortId sink_sb_port_id = + module_manager.find_module_port(sink_sb_module, sink_sb_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(sink_sb_module, + sink_sb_port_id)); + BasicPort sink_sb_port = + module_manager.module_port(sink_sb_module, sink_sb_port_id); /* Source and sink port should match in size */ VTR_ASSERT(src_grid_port.get_width() == sink_sb_port.get_width()); - + /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < src_grid_port.pins().size(); ++pin_id) { - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, src_grid_module, src_grid_instance, src_grid_port_id, src_grid_port.pins()[pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, src_grid_module, src_grid_instance, + src_grid_port_id, src_grid_port.pins()[pin_id]); /* Configure the net sink */ - module_manager.add_module_net_sink(top_module, net, sink_sb_module, sink_sb_instance, sink_sb_port_id, sink_sb_port.pins()[pin_id]); + module_manager.add_module_net_sink(top_module, net, sink_sb_module, + sink_sb_instance, sink_sb_port_id, + sink_sb_port.pins()[pin_id]); } - } + } } } /******************************************************************** - * Add module nets to connect a GSB to adjacent grid ports/pins + * Add module nets to connect a GSB to adjacent grid ports/pins * as well as connection blocks * This function will create nets for the following types of connections * between grid output pins of Switch block and adjacent grids @@ -168,7 +200,7 @@ void add_top_module_nets_connect_grids_and_sb(ModuleManager& module_manager, * when creating the connecting nets. * The follow figure shows the different pin postfix to be considered when * connecting the grid pins to SB inputs - * + * * +------------+ +------------+ * | | | | * | Grid | | Grid | @@ -192,49 +224,51 @@ void add_top_module_nets_connect_grids_and_sb(ModuleManager& module_manager, * +------------+ +------------+ * *******************************************************************/ -static -void add_top_module_nets_connect_grids_and_sb_with_duplicated_pins(ModuleManager& module_manager, - const ModuleId& top_module, - const VprDeviceAnnotation& vpr_device_annotation, - const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, - const RRGSB& rr_gsb, - const vtr::Matrix& sb_instance_ids, - const bool& compact_routing_hierarchy) { - +static void add_top_module_nets_connect_grids_and_sb_with_duplicated_pins( + ModuleManager& module_manager, const ModuleId& top_module, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const vtr::Matrix& grid_instance_ids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, const RRGSB& rr_gsb, + const vtr::Matrix& sb_instance_ids, + const bool& compact_routing_hierarchy) { /* Skip those Switch blocks that do not exist */ if (false == rr_gsb.is_sb_exist()) { return; } - /* We could have two different coordinators, one is the instance, the other is the module */ - vtr::Point instance_sb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); + /* We could have two different coordinators, one is the instance, the other is + * the module */ + vtr::Point instance_sb_coordinate(rr_gsb.get_sb_x(), + rr_gsb.get_sb_y()); vtr::Point module_gsb_coordinate(rr_gsb.get_x(), rr_gsb.get_y()); - /* If we use compact routing hierarchy, we should find the unique module of CB, which is added to the top module */ + /* If we use compact routing hierarchy, we should find the unique module of + * CB, which is added to the top module */ if (true == compact_routing_hierarchy) { vtr::Point gsb_coord(rr_gsb.get_x(), rr_gsb.get_y()); const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(gsb_coord); - module_gsb_coordinate.set_x(unique_mirror.get_x()); - module_gsb_coordinate.set_y(unique_mirror.get_y()); - } + module_gsb_coordinate.set_x(unique_mirror.get_x()); + module_gsb_coordinate.set_y(unique_mirror.get_y()); + } /* This is the source cb that is added to the top module */ const RRGSB& module_sb = device_rr_gsb.get_gsb(module_gsb_coordinate); - vtr::Point module_sb_coordinate(module_sb.get_sb_x(), module_sb.get_sb_y()); + vtr::Point module_sb_coordinate(module_sb.get_sb_x(), + module_sb.get_sb_y()); /* Collect sink-related information */ - std::string sink_sb_module_name = generate_switch_block_module_name(module_sb_coordinate); + std::string sink_sb_module_name = + generate_switch_block_module_name(module_sb_coordinate); ModuleId sink_sb_module = module_manager.find_module(sink_sb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(sink_sb_module)); - size_t sink_sb_instance = sb_instance_ids[instance_sb_coordinate.x()][instance_sb_coordinate.y()]; + size_t sink_sb_instance = + sb_instance_ids[instance_sb_coordinate.x()][instance_sb_coordinate.y()]; - /* Create a truth table for the postfix to be used regarding to the different side of switch blocks */ + /* Create a truth table for the postfix to be used regarding to the different + * side of switch blocks */ std::map sb_side2postfix_map; - /* Boolean variable "true" indicates the upper postfix in naming functions - * Boolean variable "false" indicates the lower postfix in naming functions + /* Boolean variable "true" indicates the upper postfix in naming functions + * Boolean variable "false" indicates the lower postfix in naming functions */ sb_side2postfix_map[TOP] = false; sb_side2postfix_map[RIGHT] = true; @@ -244,140 +278,173 @@ void add_top_module_nets_connect_grids_and_sb_with_duplicated_pins(ModuleManager /* Connect grid output pins (OPIN) to switch block grid pins */ for (size_t side = 0; side < module_sb.get_num_sides(); ++side) { SideManager side_manager(side); - for (size_t inode = 0; inode < module_sb.get_num_opin_nodes(side_manager.get_side()); ++inode) { + for (size_t inode = 0; + inode < module_sb.get_num_opin_nodes(side_manager.get_side()); + ++inode) { /* Collect source-related information */ - /* Generate the grid module name by considering if it locates on the border */ - vtr::Point grid_coordinate(rr_graph.node_xlow(rr_gsb.get_opin_node(side_manager.get_side(), inode)), - rr_graph.node_ylow(rr_gsb.get_opin_node(side_manager.get_side(), inode))); - std::string src_grid_module_name = generate_grid_block_module_name_in_top_module(std::string(GRID_MODULE_NAME_PREFIX), grids, grid_coordinate); - ModuleId src_grid_module = module_manager.find_module(src_grid_module_name); + /* Generate the grid module name by considering if it locates on the + * border */ + vtr::Point grid_coordinate( + rr_graph.node_xlow( + rr_gsb.get_opin_node(side_manager.get_side(), inode)), + rr_graph.node_ylow( + rr_gsb.get_opin_node(side_manager.get_side(), inode))); + std::string src_grid_module_name = + generate_grid_block_module_name_in_top_module( + std::string(GRID_MODULE_NAME_PREFIX), grids, grid_coordinate); + ModuleId src_grid_module = + module_manager.find_module(src_grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(src_grid_module)); - size_t src_grid_instance = grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()]; - size_t src_grid_pin_index = rr_graph.node_pin_num(rr_gsb.get_opin_node(side_manager.get_side(), inode)); + size_t src_grid_instance = + grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()]; + size_t src_grid_pin_index = rr_graph.node_pin_num( + rr_gsb.get_opin_node(side_manager.get_side(), inode)); - t_physical_tile_type_ptr grid_type_descriptor = grids[grid_coordinate.x()][grid_coordinate.y()].type; - size_t src_grid_pin_width = grid_type_descriptor->pin_width_offset[src_grid_pin_index]; - size_t src_grid_pin_height = grid_type_descriptor->pin_height_offset[src_grid_pin_index]; + t_physical_tile_type_ptr grid_type_descriptor = + grids[grid_coordinate.x()][grid_coordinate.y()].type; + size_t src_grid_pin_width = + grid_type_descriptor->pin_width_offset[src_grid_pin_index]; + size_t src_grid_pin_height = + grid_type_descriptor->pin_height_offset[src_grid_pin_index]; - BasicPort src_grid_pin_info = vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor, src_grid_pin_index); + BasicPort src_grid_pin_info = + vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor, + src_grid_pin_index); VTR_ASSERT(true == src_grid_pin_info.is_valid()); - int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(grid_type_descriptor, src_grid_pin_index); - VTR_ASSERT(OPEN != subtile_index && subtile_index < grid_type_descriptor->capacity); + int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index( + grid_type_descriptor, src_grid_pin_index); + VTR_ASSERT(OPEN != subtile_index && + subtile_index < grid_type_descriptor->capacity); /* Pins for direct connection are NOT duplicated. - * Follow the traditional recipe when adding nets! - * Xifan: I assume that each direct connection pin must have Fc=0. + * Follow the traditional recipe when adding nets! + * Xifan: I assume that each direct connection pin must have Fc=0. * For other duplicated pins, we follow the new naming */ std::string src_grid_port_name; - if (0. == find_physical_tile_pin_Fc(grid_type_descriptor, src_grid_pin_index)) { - src_grid_port_name = generate_grid_port_name(src_grid_pin_width, src_grid_pin_height, subtile_index, - get_rr_graph_single_node_side(rr_graph, rr_gsb.get_opin_node(side_manager.get_side(), inode)), - src_grid_pin_info); + if (0. == + find_physical_tile_pin_Fc(grid_type_descriptor, src_grid_pin_index)) { + src_grid_port_name = generate_grid_port_name( + src_grid_pin_width, src_grid_pin_height, subtile_index, + get_rr_graph_single_node_side( + rr_graph, rr_gsb.get_opin_node(side_manager.get_side(), inode)), + src_grid_pin_info); } else { - src_grid_port_name = generate_grid_duplicated_port_name(src_grid_pin_width, src_grid_pin_height, subtile_index, - get_rr_graph_single_node_side(rr_graph, rr_gsb.get_opin_node(side_manager.get_side(), inode)), - src_grid_pin_info, sb_side2postfix_map[side_manager.get_side()]); + src_grid_port_name = generate_grid_duplicated_port_name( + src_grid_pin_width, src_grid_pin_height, subtile_index, + get_rr_graph_single_node_side( + rr_graph, rr_gsb.get_opin_node(side_manager.get_side(), inode)), + src_grid_pin_info, sb_side2postfix_map[side_manager.get_side()]); } - ModulePortId src_grid_port_id = module_manager.find_module_port(src_grid_module, src_grid_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(src_grid_module, src_grid_port_id)); - BasicPort src_grid_port = module_manager.module_port(src_grid_module, src_grid_port_id); + ModulePortId src_grid_port_id = + module_manager.find_module_port(src_grid_module, src_grid_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(src_grid_module, + src_grid_port_id)); + BasicPort src_grid_port = + module_manager.module_port(src_grid_module, src_grid_port_id); /* Collect sink-related information */ - vtr::Point sink_sb_port_coord(rr_graph.node_xlow(module_sb.get_opin_node(side_manager.get_side(), inode)), - rr_graph.node_ylow(module_sb.get_opin_node(side_manager.get_side(), inode))); - std::string sink_sb_port_name = generate_sb_module_grid_port_name(side_manager.get_side(), - get_rr_graph_single_node_side(rr_graph, module_sb.get_opin_node(side_manager.get_side(), inode)), - grids, - vpr_device_annotation, - rr_graph, - module_sb.get_opin_node(side_manager.get_side(), inode)); - ModulePortId sink_sb_port_id = module_manager.find_module_port(sink_sb_module, sink_sb_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(sink_sb_module, sink_sb_port_id)); - BasicPort sink_sb_port = module_manager.module_port(sink_sb_module, sink_sb_port_id); + vtr::Point sink_sb_port_coord( + rr_graph.node_xlow( + module_sb.get_opin_node(side_manager.get_side(), inode)), + rr_graph.node_ylow( + module_sb.get_opin_node(side_manager.get_side(), inode))); + std::string sink_sb_port_name = generate_sb_module_grid_port_name( + side_manager.get_side(), + get_rr_graph_single_node_side( + rr_graph, module_sb.get_opin_node(side_manager.get_side(), inode)), + grids, vpr_device_annotation, rr_graph, + module_sb.get_opin_node(side_manager.get_side(), inode)); + ModulePortId sink_sb_port_id = + module_manager.find_module_port(sink_sb_module, sink_sb_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(sink_sb_module, + sink_sb_port_id)); + BasicPort sink_sb_port = + module_manager.module_port(sink_sb_module, sink_sb_port_id); /* Source and sink port should match in size */ VTR_ASSERT(src_grid_port.get_width() == sink_sb_port.get_width()); - + /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < src_grid_port.pins().size(); ++pin_id) { - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, src_grid_module, src_grid_instance, src_grid_port_id, src_grid_port.pins()[pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, src_grid_module, src_grid_instance, + src_grid_port_id, src_grid_port.pins()[pin_id]); /* Configure the net sink */ - module_manager.add_module_net_sink(top_module, net, sink_sb_module, sink_sb_instance, sink_sb_port_id, sink_sb_port.pins()[pin_id]); + module_manager.add_module_net_sink(top_module, net, sink_sb_module, + sink_sb_instance, sink_sb_port_id, + sink_sb_port.pins()[pin_id]); } - } + } } } /******************************************************************** * This function will create nets for the connections * between grid input pins and connection blocks - * In this case, the net source is the connection block pin, + * In this case, the net source is the connection block pin, * while the net sink is the grid input * * +------------+ +------------------+ +------------+ * | | | | | | * | Grid |<-----| Connection Block |----->| Grid | - * | [x][y+1] | | Y-direction | | [x+1][y+1] | + * | [x][y+1] | | Y-direction | | [x+1][y+1] | * | | | [x][y+1] | | | * +------------+ +------------------+ +------------+ - * ^ - * | - * +------------+ +------------------+ - * | Connection | | | - * | Block | | Switch Block | - * | X-direction| | [x][y] | - * | [x][y] | | | - * +------------+ +------------------+ - * | - * v - * +------------+ - * | | - * | Grid | - * | [x][y] | - * | | - * +------------+ + * ^ + * | + * +------------+ +------------------+ + * | Connection | | | + * | Block | | Switch Block | + * | X-direction| | [x][y] | + * | [x][y] | | | + * +------------+ +------------------+ + * | + * v + * +------------+ + * | | + * | Grid | + * | [x][y] | + * | | + * +------------+ * * - * Relationship between source connection block and its unique module + * Relationship between source connection block and its unique module * Take an example of a CBY * * grid_pin name should follow unique module of Grid[x][y+1] * cb_pin name should follow unique module of CBY[x][y+1] - * - * However, instace id should follow the origin Grid and Connection block - * - * - * +------------+ +------------------+ - * | | | | + * + * However, instace id should follow the origin Grid and Connection block + * + * + * +------------+ +------------------+ + * | | | | * | Grid |<------------| Connection Block | - * | [x][y+1] | | Y-direction | + * | [x][y+1] | | Y-direction | * | | | [x][y+1] | * +------------+ +------------------+ * ^ * || unique mirror - * +------------+ +------------------+ - * | | | | + * +------------+ +------------------+ + * | | | | * | Grid |<------------| Connection Block | - * | [i][j+1] | | Y-direction | + * | [i][j+1] | | Y-direction | * | | | [i][j+1] | * +------------+ +------------------+ * *******************************************************************/ -static -void add_top_module_nets_connect_grids_and_cb(ModuleManager& module_manager, - const ModuleId& top_module, - const VprDeviceAnnotation& vpr_device_annotation, - const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, - const RRGSB& rr_gsb, - const t_rr_type& cb_type, - const vtr::Matrix& cb_instance_ids, - const bool& compact_routing_hierarchy) { - /* We could have two different coordinators, one is the instance, the other is the module */ - vtr::Point instance_cb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); +static void add_top_module_nets_connect_grids_and_cb( + ModuleManager& module_manager, const ModuleId& top_module, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const vtr::Matrix& grid_instance_ids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, const RRGSB& rr_gsb, + const t_rr_type& cb_type, const vtr::Matrix& cb_instance_ids, + const bool& compact_routing_hierarchy) { + /* We could have two different coordinators, one is the instance, the other is + * the module */ + vtr::Point instance_cb_coordinate(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); vtr::Point module_gsb_coordinate(rr_gsb.get_x(), rr_gsb.get_y()); /* Skip those Connection blocks that do not exist */ @@ -390,78 +457,106 @@ void add_top_module_nets_connect_grids_and_cb(ModuleManager& module_manager, return; } - /* If we use compact routing hierarchy, we should find the unique module of CB, which is added to the top module */ + /* If we use compact routing hierarchy, we should find the unique module of + * CB, which is added to the top module */ if (true == compact_routing_hierarchy) { vtr::Point gsb_coord(rr_gsb.get_x(), rr_gsb.get_y()); - const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(cb_type, gsb_coord); - module_gsb_coordinate.set_x(unique_mirror.get_x()); - module_gsb_coordinate.set_y(unique_mirror.get_y()); - } + const RRGSB& unique_mirror = + device_rr_gsb.get_cb_unique_module(cb_type, gsb_coord); + module_gsb_coordinate.set_x(unique_mirror.get_x()); + module_gsb_coordinate.set_y(unique_mirror.get_y()); + } /* This is the source cb that is added to the top module */ const RRGSB& module_cb = device_rr_gsb.get_gsb(module_gsb_coordinate); - vtr::Point module_cb_coordinate(module_cb.get_cb_x(cb_type), module_cb.get_cb_y(cb_type)); + vtr::Point module_cb_coordinate(module_cb.get_cb_x(cb_type), + module_cb.get_cb_y(cb_type)); /* Collect source-related information */ - std::string src_cb_module_name = generate_connection_block_module_name(cb_type, module_cb_coordinate); + std::string src_cb_module_name = + generate_connection_block_module_name(cb_type, module_cb_coordinate); ModuleId src_cb_module = module_manager.find_module(src_cb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(src_cb_module)); /* Instance id should follow the instance cb coordinate */ - size_t src_cb_instance = cb_instance_ids[instance_cb_coordinate.x()][instance_cb_coordinate.y()]; + size_t src_cb_instance = + cb_instance_ids[instance_cb_coordinate.x()][instance_cb_coordinate.y()]; /* Iterate over the output pins of the Connection Block */ std::vector cb_ipin_sides = module_cb.get_cb_ipin_sides(cb_type); for (size_t iside = 0; iside < cb_ipin_sides.size(); ++iside) { enum e_side cb_ipin_side = cb_ipin_sides[iside]; - for (size_t inode = 0; inode < module_cb.get_num_ipin_nodes(cb_ipin_side); ++inode) { + for (size_t inode = 0; inode < module_cb.get_num_ipin_nodes(cb_ipin_side); + ++inode) { /* Collect source-related information */ RRNodeId module_ipin_node = module_cb.get_ipin_node(cb_ipin_side, inode); - vtr::Point cb_src_port_coord(rr_graph.node_xlow(module_ipin_node), - rr_graph.node_ylow(module_ipin_node)); - std::string src_cb_port_name = generate_cb_module_grid_port_name(cb_ipin_side, - grids, - vpr_device_annotation, - rr_graph, - module_ipin_node); - ModulePortId src_cb_port_id = module_manager.find_module_port(src_cb_module, src_cb_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(src_cb_module, src_cb_port_id)); - BasicPort src_cb_port = module_manager.module_port(src_cb_module, src_cb_port_id); + vtr::Point cb_src_port_coord( + rr_graph.node_xlow(module_ipin_node), + rr_graph.node_ylow(module_ipin_node)); + std::string src_cb_port_name = generate_cb_module_grid_port_name( + cb_ipin_side, grids, vpr_device_annotation, rr_graph, module_ipin_node); + ModulePortId src_cb_port_id = + module_manager.find_module_port(src_cb_module, src_cb_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(src_cb_module, + src_cb_port_id)); + BasicPort src_cb_port = + module_manager.module_port(src_cb_module, src_cb_port_id); /* Collect sink-related information */ /* Note that we use the instance cb pin here!!! - * because it has the correct coordinator for the grid!!! + * because it has the correct coordinator for the grid!!! */ RRNodeId instance_ipin_node = rr_gsb.get_ipin_node(cb_ipin_side, inode); - vtr::Point grid_coordinate(rr_graph.node_xlow(instance_ipin_node), - rr_graph.node_ylow(instance_ipin_node)); - std::string sink_grid_module_name = generate_grid_block_module_name_in_top_module(std::string(GRID_MODULE_NAME_PREFIX), grids, grid_coordinate); - ModuleId sink_grid_module = module_manager.find_module(sink_grid_module_name); + vtr::Point grid_coordinate( + rr_graph.node_xlow(instance_ipin_node), + rr_graph.node_ylow(instance_ipin_node)); + std::string sink_grid_module_name = + generate_grid_block_module_name_in_top_module( + std::string(GRID_MODULE_NAME_PREFIX), grids, grid_coordinate); + ModuleId sink_grid_module = + module_manager.find_module(sink_grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(sink_grid_module)); - size_t sink_grid_instance = grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()]; + size_t sink_grid_instance = + grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()]; size_t sink_grid_pin_index = rr_graph.node_pin_num(instance_ipin_node); - t_physical_tile_type_ptr grid_type_descriptor = grids[grid_coordinate.x()][grid_coordinate.y()].type; - size_t sink_grid_pin_width = grid_type_descriptor->pin_width_offset[sink_grid_pin_index]; - size_t sink_grid_pin_height = grid_type_descriptor->pin_height_offset[sink_grid_pin_index]; - BasicPort sink_grid_pin_info = vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor, sink_grid_pin_index); + t_physical_tile_type_ptr grid_type_descriptor = + grids[grid_coordinate.x()][grid_coordinate.y()].type; + size_t sink_grid_pin_width = + grid_type_descriptor->pin_width_offset[sink_grid_pin_index]; + size_t sink_grid_pin_height = + grid_type_descriptor->pin_height_offset[sink_grid_pin_index]; + BasicPort sink_grid_pin_info = + vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor, + sink_grid_pin_index); VTR_ASSERT(true == sink_grid_pin_info.is_valid()); - int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(grid_type_descriptor, sink_grid_pin_index); - VTR_ASSERT(OPEN != subtile_index && subtile_index < grid_type_descriptor->capacity); - std::string sink_grid_port_name = generate_grid_port_name(sink_grid_pin_width, sink_grid_pin_height, subtile_index, - get_rr_graph_single_node_side(rr_graph, rr_gsb.get_ipin_node(cb_ipin_side, inode)), - sink_grid_pin_info); - ModulePortId sink_grid_port_id = module_manager.find_module_port(sink_grid_module, sink_grid_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(sink_grid_module, sink_grid_port_id)); - BasicPort sink_grid_port = module_manager.module_port(sink_grid_module, sink_grid_port_id); + int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index( + grid_type_descriptor, sink_grid_pin_index); + VTR_ASSERT(OPEN != subtile_index && + subtile_index < grid_type_descriptor->capacity); + std::string sink_grid_port_name = generate_grid_port_name( + sink_grid_pin_width, sink_grid_pin_height, subtile_index, + get_rr_graph_single_node_side( + rr_graph, rr_gsb.get_ipin_node(cb_ipin_side, inode)), + sink_grid_pin_info); + ModulePortId sink_grid_port_id = + module_manager.find_module_port(sink_grid_module, sink_grid_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id( + sink_grid_module, sink_grid_port_id)); + BasicPort sink_grid_port = + module_manager.module_port(sink_grid_module, sink_grid_port_id); /* Source and sink port should match in size */ VTR_ASSERT(src_cb_port.get_width() == sink_grid_port.get_width()); - + /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < src_cb_port.pins().size(); ++pin_id) { - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, src_cb_module, src_cb_instance, src_cb_port_id, src_cb_port.pins()[pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, src_cb_module, src_cb_instance, + src_cb_port_id, src_cb_port.pins()[pin_id]); /* Configure the net sink */ - module_manager.add_module_net_sink(top_module, net, sink_grid_module, sink_grid_instance, sink_grid_port_id, sink_grid_port.pins()[pin_id]); + module_manager.add_module_net_sink( + top_module, net, sink_grid_module, sink_grid_instance, + sink_grid_port_id, sink_grid_port.pins()[pin_id]); } } } @@ -475,13 +570,13 @@ void add_top_module_nets_connect_grids_and_cb(ModuleManager& module_manager, * The net source is an output of a routing track of connection block * while the net sink is an input of a routing track of switch block * b. The switch block pin denotes an output of a routing track - * The net source is an output of routing track of switch block + * The net source is an output of routing track of switch block * while the net sink is an input of a routing track of connection block * * +------------+ +------------------+ +------------+ * | | | | | | * | Grid | | Connection Block | | Grid | - * | [x][y+1] | | Y-direction | | [x+1][y+1] | + * | [x][y+1] | | Y-direction | | [x+1][y+1] | * | | | [x][y+1] | | | * +------------+ +------------------+ +------------+ * | ^ @@ -501,22 +596,21 @@ void add_top_module_nets_connect_grids_and_cb(ModuleManager& module_manager, * | | | [x][y] | | | * +------------+ +------------------+ +------------+ * - * Here, to achieve the purpose, we can simply iterate over the - * four sides of switch block and make connections to adjancent + * Here, to achieve the purpose, we can simply iterate over the + * four sides of switch block and make connections to adjancent * connection blocks * *******************************************************************/ -static -void add_top_module_nets_connect_sb_and_cb(ModuleManager& module_manager, - const ModuleId& top_module, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, - const RRGSB& rr_gsb, - const vtr::Matrix& sb_instance_ids, - const std::map>& cb_instance_ids, - const bool& compact_routing_hierarchy) { - /* We could have two different coordinators, one is the instance, the other is the module */ - vtr::Point instance_sb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); +static void add_top_module_nets_connect_sb_and_cb( + ModuleManager& module_manager, const ModuleId& top_module, + const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, + const RRGSB& rr_gsb, const vtr::Matrix& sb_instance_ids, + const std::map>& cb_instance_ids, + const bool& compact_routing_hierarchy) { + /* We could have two different coordinators, one is the instance, the other is + * the module */ + vtr::Point instance_sb_coordinate(rr_gsb.get_sb_x(), + rr_gsb.get_sb_y()); vtr::Point module_gsb_sb_coordinate(rr_gsb.get_x(), rr_gsb.get_y()); /* Skip those Switch blocks that do not exist */ @@ -524,21 +618,25 @@ void add_top_module_nets_connect_sb_and_cb(ModuleManager& module_manager, return; } - /* If we use compact routing hierarchy, we should find the unique module of CB, which is added to the top module */ + /* If we use compact routing hierarchy, we should find the unique module of + * CB, which is added to the top module */ if (true == compact_routing_hierarchy) { vtr::Point gsb_coord(rr_gsb.get_x(), rr_gsb.get_y()); const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(gsb_coord); - module_gsb_sb_coordinate.set_x(unique_mirror.get_x()); - module_gsb_sb_coordinate.set_y(unique_mirror.get_y()); - } + module_gsb_sb_coordinate.set_x(unique_mirror.get_x()); + module_gsb_sb_coordinate.set_y(unique_mirror.get_y()); + } /* This is the source cb that is added to the top module */ const RRGSB& module_sb = device_rr_gsb.get_gsb(module_gsb_sb_coordinate); - vtr::Point module_sb_coordinate(module_sb.get_sb_x(), module_sb.get_sb_y()); - std::string sb_module_name = generate_switch_block_module_name(module_sb_coordinate); + vtr::Point module_sb_coordinate(module_sb.get_sb_x(), + module_sb.get_sb_y()); + std::string sb_module_name = + generate_switch_block_module_name(module_sb_coordinate); ModuleId sb_module_id = module_manager.find_module(sb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(sb_module_id)); - size_t sb_instance = sb_instance_ids[instance_sb_coordinate.x()][instance_sb_coordinate.y()]; + size_t sb_instance = + sb_instance_ids[instance_sb_coordinate.x()][instance_sb_coordinate.y()]; /* Connect grid output pins (OPIN) to switch block grid pins */ for (size_t side = 0; side < module_sb.get_num_sides(); ++side) { @@ -549,88 +647,120 @@ void add_top_module_nets_connect_sb_and_cb(ModuleManager& module_manager, continue; } /* Find the Connection Block module */ - /* We find the original connection block and then spot its unique mirror! + /* We find the original connection block and then spot its unique mirror! * Do NOT use module_sb here!!! */ - t_rr_type cb_type = find_top_module_cb_type_by_sb_side(side_manager.get_side()); - vtr::Point instance_gsb_cb_coordinate = find_top_module_gsb_coordinate_by_sb_side(rr_gsb, side_manager.get_side()); - vtr::Point module_gsb_cb_coordinate = find_top_module_gsb_coordinate_by_sb_side(rr_gsb, side_manager.get_side()); + t_rr_type cb_type = + find_top_module_cb_type_by_sb_side(side_manager.get_side()); + vtr::Point instance_gsb_cb_coordinate = + find_top_module_gsb_coordinate_by_sb_side(rr_gsb, + side_manager.get_side()); + vtr::Point module_gsb_cb_coordinate = + find_top_module_gsb_coordinate_by_sb_side(rr_gsb, + side_manager.get_side()); /* Skip those Connection blocks that do not exist: - * 1. The CB does not exist in the device level! We should skip! - * 2. The CB does exist but we need to make sure if the GSB includes such CBs - * For TOP and LEFT side, check the existence using RRGSB method is_cb_exist() - * FOr RIGHT and BOTTOM side, find the adjacent RRGSB and then use is_cb_exist() + * 1. The CB does not exist in the device level! We should skip! + * 2. The CB does exist but we need to make sure if the GSB includes such + * CBs For TOP and LEFT side, check the existence using RRGSB method + * is_cb_exist() FOr RIGHT and BOTTOM side, find the adjacent RRGSB and then + * use is_cb_exist() */ - if ( TOP == side_manager.get_side() || LEFT == side_manager.get_side() ) { - if ( false == rr_gsb.is_cb_exist(cb_type)) { + if (TOP == side_manager.get_side() || LEFT == side_manager.get_side()) { + if (false == rr_gsb.is_cb_exist(cb_type)) { continue; } } - if ( RIGHT == side_manager.get_side() || BOTTOM == side_manager.get_side() ) { - const RRGSB& adjacent_gsb = device_rr_gsb.get_gsb(module_gsb_cb_coordinate); - if ( false == adjacent_gsb.is_cb_exist(cb_type)) { + if (RIGHT == side_manager.get_side() || BOTTOM == side_manager.get_side()) { + const RRGSB& adjacent_gsb = + device_rr_gsb.get_gsb(module_gsb_cb_coordinate); + if (false == adjacent_gsb.is_cb_exist(cb_type)) { continue; } } - /* If we use compact routing hierarchy, we should find the unique module of CB, which is added to the top module */ + /* If we use compact routing hierarchy, we should find the unique module of + * CB, which is added to the top module */ if (true == compact_routing_hierarchy) { - const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(cb_type, module_gsb_cb_coordinate); - module_gsb_cb_coordinate.set_x(unique_mirror.get_x()); - module_gsb_cb_coordinate.set_y(unique_mirror.get_y()); - } - + const RRGSB& unique_mirror = + device_rr_gsb.get_cb_unique_module(cb_type, module_gsb_cb_coordinate); + module_gsb_cb_coordinate.set_x(unique_mirror.get_x()); + module_gsb_cb_coordinate.set_y(unique_mirror.get_y()); + } + const RRGSB& module_cb = device_rr_gsb.get_gsb(module_gsb_cb_coordinate); - vtr::Point module_cb_coordinate(module_cb.get_cb_x(cb_type), module_cb.get_cb_y(cb_type)); - std::string cb_module_name = generate_connection_block_module_name(cb_type, module_cb_coordinate); + vtr::Point module_cb_coordinate(module_cb.get_cb_x(cb_type), + module_cb.get_cb_y(cb_type)); + std::string cb_module_name = + generate_connection_block_module_name(cb_type, module_cb_coordinate); ModuleId cb_module_id = module_manager.find_module(cb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(cb_module_id)); - const RRGSB& instance_cb = device_rr_gsb.get_gsb(instance_gsb_cb_coordinate); - vtr::Point instance_cb_coordinate(instance_cb.get_cb_x(cb_type), instance_cb.get_cb_y(cb_type)); - size_t cb_instance = cb_instance_ids.at(cb_type)[instance_cb_coordinate.x()][instance_cb_coordinate.y()]; - - for (size_t itrack = 0; itrack < module_sb.get_chan_width(side_manager.get_side()); ++itrack) { - std::string sb_port_name = generate_sb_module_track_port_name(rr_graph.node_type(module_sb.get_chan_node(side_manager.get_side(), itrack)), - side_manager.get_side(), - module_sb.get_chan_node_direction(side_manager.get_side(), itrack)); + const RRGSB& instance_cb = + device_rr_gsb.get_gsb(instance_gsb_cb_coordinate); + vtr::Point instance_cb_coordinate(instance_cb.get_cb_x(cb_type), + instance_cb.get_cb_y(cb_type)); + size_t cb_instance = cb_instance_ids.at( + cb_type)[instance_cb_coordinate.x()][instance_cb_coordinate.y()]; + + for (size_t itrack = 0; + itrack < module_sb.get_chan_width(side_manager.get_side()); ++itrack) { + std::string sb_port_name = generate_sb_module_track_port_name( + rr_graph.node_type( + module_sb.get_chan_node(side_manager.get_side(), itrack)), + side_manager.get_side(), + module_sb.get_chan_node_direction(side_manager.get_side(), itrack)); /* Prepare SB-related port information */ - ModulePortId sb_port_id = module_manager.find_module_port(sb_module_id, sb_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(sb_module_id, sb_port_id)); + ModulePortId sb_port_id = + module_manager.find_module_port(sb_module_id, sb_port_name); + VTR_ASSERT(true == + module_manager.valid_module_port_id(sb_module_id, sb_port_id)); BasicPort sb_port = module_manager.module_port(sb_module_id, sb_port_id); - - /* Prepare CB-related port information */ + + /* Prepare CB-related port information */ PORTS cb_port_direction = OUT_PORT; /* The cb port direction should be opposite to the sb port !!! */ - if (OUT_PORT == module_sb.get_chan_node_direction(side_manager.get_side(), itrack)) { + if (OUT_PORT == + module_sb.get_chan_node_direction(side_manager.get_side(), itrack)) { cb_port_direction = IN_PORT; } else { - VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction(side_manager.get_side(), itrack)); - } - - /* Upper CB port is required if the routing tracks are on the top or right sides of - * the switch block, which indicated bottom and left sides of the connection blocks + VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction( + side_manager.get_side(), itrack)); + } + + /* Upper CB port is required if the routing tracks are on the top or right + * sides of the switch block, which indicated bottom and left sides of the + * connection blocks */ - bool use_cb_upper_port = (TOP == side_manager.get_side()) || (RIGHT == side_manager.get_side()); - std::string cb_port_name = generate_cb_module_track_port_name(cb_type, - cb_port_direction, - use_cb_upper_port); - ModulePortId cb_port_id = module_manager.find_module_port(cb_module_id, cb_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module_id, cb_port_id)); + bool use_cb_upper_port = + (TOP == side_manager.get_side()) || (RIGHT == side_manager.get_side()); + std::string cb_port_name = generate_cb_module_track_port_name( + cb_type, cb_port_direction, use_cb_upper_port); + ModulePortId cb_port_id = + module_manager.find_module_port(cb_module_id, cb_port_name); + VTR_ASSERT(true == + module_manager.valid_module_port_id(cb_module_id, cb_port_id)); BasicPort cb_port = module_manager.module_port(cb_module_id, cb_port_id); /* Configure the net source and sink: - * If sb port is an output (source), cb port is an input (sink) - * If sb port is an input (sink), cb port is an output (source) + * If sb port is an output (source), cb port is an input (sink) + * If sb port is an input (sink), cb port is an output (source) */ - if (OUT_PORT == module_sb.get_chan_node_direction(side_manager.get_side(), itrack)) { - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, sb_module_id, sb_instance, sb_port_id, itrack / 2); - module_manager.add_module_net_sink(top_module, net, cb_module_id, cb_instance, cb_port_id, itrack / 2); + if (OUT_PORT == + module_sb.get_chan_node_direction(side_manager.get_side(), itrack)) { + ModuleNetId net = + create_module_source_pin_net(module_manager, top_module, sb_module_id, + sb_instance, sb_port_id, itrack / 2); + module_manager.add_module_net_sink(top_module, net, cb_module_id, + cb_instance, cb_port_id, itrack / 2); } else { - VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction(side_manager.get_side(), itrack)); - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, cb_module_id, cb_instance, cb_port_id, itrack / 2); - module_manager.add_module_net_sink(top_module, net, sb_module_id, sb_instance, sb_port_id, itrack / 2); + VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction( + side_manager.get_side(), itrack)); + ModuleNetId net = + create_module_source_pin_net(module_manager, top_module, cb_module_id, + cb_instance, cb_port_id, itrack / 2); + module_manager.add_module_net_sink(top_module, net, sb_module_id, + sb_instance, sb_port_id, itrack / 2); } } } @@ -641,7 +771,7 @@ void add_top_module_nets_connect_sb_and_cb(ModuleManager& module_manager, * and Switch Blocks * To make it easy, this function will iterate over all the General * Switch Blocks (GSBs), through which we can obtain the coordinates - * of all the grids, connection blocks and switch blocks that are + * of all the grids, connection blocks and switch blocks that are * supposed to be connected tightly. * * As such, we have completed all the connection for each grid. @@ -669,18 +799,13 @@ void add_top_module_nets_connect_sb_and_cb(ModuleManager& module_manager, * +-------------+ +---------------------------------+ * BOTTOM SIDE *******************************************************************/ -void add_top_module_nets_connect_grids_and_gsbs(ModuleManager& module_manager, - const ModuleId& top_module, - const VprDeviceAnnotation& vpr_device_annotation, - const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, - const vtr::Matrix& sb_instance_ids, - const std::map>& cb_instance_ids, - const bool& compact_routing_hierarchy, - const bool& duplicate_grid_pin) { - +void add_top_module_nets_connect_grids_and_gsbs( + ModuleManager& module_manager, const ModuleId& top_module, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const vtr::Matrix& grid_instance_ids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, const vtr::Matrix& sb_instance_ids, + const std::map>& cb_instance_ids, + const bool& compact_routing_hierarchy, const bool& duplicate_grid_pin) { vtr::ScopedStartFinishTimer timer("Add module nets between grids and GSBs"); vtr::Point gsb_range = device_rr_gsb.get_gsb_range(); @@ -692,69 +817,64 @@ void add_top_module_nets_connect_grids_and_gsbs(ModuleManager& module_manager, /* Connect the grid pins of the GSB to adjacent grids */ if (false == duplicate_grid_pin) { - add_top_module_nets_connect_grids_and_sb(module_manager, top_module, - vpr_device_annotation, - grids, grid_instance_ids, - rr_graph, device_rr_gsb, rr_gsb, sb_instance_ids, - compact_routing_hierarchy); + add_top_module_nets_connect_grids_and_sb( + module_manager, top_module, vpr_device_annotation, grids, + grid_instance_ids, rr_graph, device_rr_gsb, rr_gsb, sb_instance_ids, + compact_routing_hierarchy); } else { VTR_ASSERT_SAFE(true == duplicate_grid_pin); - add_top_module_nets_connect_grids_and_sb_with_duplicated_pins(module_manager, top_module, - vpr_device_annotation, - grids, grid_instance_ids, - rr_graph, device_rr_gsb, rr_gsb, sb_instance_ids, - compact_routing_hierarchy); + add_top_module_nets_connect_grids_and_sb_with_duplicated_pins( + module_manager, top_module, vpr_device_annotation, grids, + grid_instance_ids, rr_graph, device_rr_gsb, rr_gsb, sb_instance_ids, + compact_routing_hierarchy); } - add_top_module_nets_connect_grids_and_cb(module_manager, top_module, - vpr_device_annotation, - grids, grid_instance_ids, - rr_graph, device_rr_gsb, rr_gsb, CHANX, cb_instance_ids.at(CHANX), - compact_routing_hierarchy); + add_top_module_nets_connect_grids_and_cb( + module_manager, top_module, vpr_device_annotation, grids, + grid_instance_ids, rr_graph, device_rr_gsb, rr_gsb, CHANX, + cb_instance_ids.at(CHANX), compact_routing_hierarchy); - add_top_module_nets_connect_grids_and_cb(module_manager, top_module, - vpr_device_annotation, - grids, grid_instance_ids, - rr_graph, device_rr_gsb, rr_gsb, CHANY, cb_instance_ids.at(CHANY), - compact_routing_hierarchy); - - add_top_module_nets_connect_sb_and_cb(module_manager, top_module, - rr_graph, device_rr_gsb, rr_gsb, sb_instance_ids, cb_instance_ids, - compact_routing_hierarchy); + add_top_module_nets_connect_grids_and_cb( + module_manager, top_module, vpr_device_annotation, grids, + grid_instance_ids, rr_graph, device_rr_gsb, rr_gsb, CHANY, + cb_instance_ids.at(CHANY), compact_routing_hierarchy); + add_top_module_nets_connect_sb_and_cb( + module_manager, top_module, rr_graph, device_rr_gsb, rr_gsb, + sb_instance_ids, cb_instance_ids, compact_routing_hierarchy); } } } /******************************************************************** * Add global port connection for a given port of a physical tile - * that are defined as global in tile annotation + * that are defined as global in tile annotation *******************************************************************/ -static -int build_top_module_global_net_for_given_grid_module(ModuleManager& module_manager, - const ModuleId& top_module, - const ModulePortId& top_module_port, - const TileAnnotation& tile_annotation, - const TileGlobalPortId& tile_global_port, - const BasicPort& tile_port_to_connect, - const VprDeviceAnnotation& vpr_device_annotation, - const DeviceGrid& grids, - const vtr::Point& grid_coordinate, - const e_side& border_side, - const vtr::Matrix& grid_instance_ids) { +static int build_top_module_global_net_for_given_grid_module( + ModuleManager& module_manager, const ModuleId& top_module, + const ModulePortId& top_module_port, const TileAnnotation& tile_annotation, + const TileGlobalPortId& tile_global_port, + const BasicPort& tile_port_to_connect, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const vtr::Point& grid_coordinate, const e_side& border_side, + const vtr::Matrix& grid_instance_ids) { + t_physical_tile_type_ptr physical_tile = + grids[grid_coordinate.x()][grid_coordinate.y()].type; + /* Find the module name for this type of grid */ + std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); + std::string grid_module_name = generate_grid_block_module_name( + grid_module_name_prefix, std::string(physical_tile->name), + is_io_type(physical_tile), border_side); + ModuleId grid_module = module_manager.find_module(grid_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); + size_t grid_instance = + grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()]; + /* Find the source port at the top-level module */ + BasicPort src_port = module_manager.module_port(top_module, top_module_port); - t_physical_tile_type_ptr physical_tile = grids[grid_coordinate.x()][grid_coordinate.y()].type; - /* Find the module name for this type of grid */ - std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); - std::string grid_module_name = generate_grid_block_module_name(grid_module_name_prefix, std::string(physical_tile->name), is_io_type(physical_tile), border_side); - ModuleId grid_module = module_manager.find_module(grid_module_name); - VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); - size_t grid_instance = grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()]; - /* Find the source port at the top-level module */ - BasicPort src_port = module_manager.module_port(top_module, top_module_port); - - /* Walk through each instance considering the unique sub tile and capacity range, - * each instance may have an independent pin to be driven by a global net! */ + /* Walk through each instance considering the unique sub tile and capacity + * range, each instance may have an independent pin to be driven by a global + * net! */ for (const t_sub_tile& sub_tile : physical_tile->sub_tiles) { VTR_ASSERT(1 == sub_tile.equivalent_sites.size()); int grid_pin_start_index = physical_tile->num_pins; @@ -764,25 +884,29 @@ int build_top_module_global_net_for_given_grid_module(ModuleManager& module_mana /* Count the total number of pins for this type of sub tile */ int sub_tile_num_pins = sub_tile.num_phy_pins / sub_tile.capacity.total(); - /* For each instance of the same sub tile type, find the port of the grid module according to the tile annotation - * A tile may consist of multiple subtile, connect to all the pins from sub tiles */ - for (int subtile_index = sub_tile.capacity.low; subtile_index <= sub_tile.capacity.high; subtile_index++) { - for (const t_physical_tile_port& tile_port : sub_tile.ports) { + /* For each instance of the same sub tile type, find the port of the grid + * module according to the tile annotation A tile may consist of multiple + * subtile, connect to all the pins from sub tiles */ + for (int subtile_index = sub_tile.capacity.low; + subtile_index <= sub_tile.capacity.high; subtile_index++) { + for (const t_physical_tile_port& tile_port : sub_tile.ports) { if (std::string(tile_port.name) == tile_port_to_connect.get_name()) { BasicPort ref_tile_port(tile_port.name, tile_port.num_pins); /* Port size must match!!! */ if (false == ref_tile_port.contained(tile_port_to_connect)) { - VTR_LOG_ERROR("Tile annotation '%s' port '%s[%lu:%lu]' is out of the range of physical tile port '%s[%lu:%lu]'!", - tile_annotation.global_port_name(tile_global_port).c_str(), - tile_port_to_connect.get_name().c_str(), - tile_port_to_connect.get_lsb(), - tile_port_to_connect.get_msb(), - ref_tile_port.get_name().c_str(), - ref_tile_port.get_lsb(), - ref_tile_port.get_msb()); + VTR_LOG_ERROR( + "Tile annotation '%s' port '%s[%lu:%lu]' is out of the range of " + "physical tile port '%s[%lu:%lu]'!", + tile_annotation.global_port_name(tile_global_port).c_str(), + tile_port_to_connect.get_name().c_str(), + tile_port_to_connect.get_lsb(), tile_port_to_connect.get_msb(), + ref_tile_port.get_name().c_str(), ref_tile_port.get_lsb(), + ref_tile_port.get_msb()); return CMD_EXEC_FATAL_ERROR; } - grid_pin_start_index = (subtile_index - sub_tile.capacity.low) * sub_tile_num_pins + tile_port.absolute_first_pin_index; + grid_pin_start_index = + (subtile_index - sub_tile.capacity.low) * sub_tile_num_pins + + tile_port.absolute_first_pin_index; physical_tile_port = tile_port; break; } @@ -792,7 +916,8 @@ int build_top_module_global_net_for_given_grid_module(ModuleManager& module_mana /* Ensure port width is in range */ VTR_ASSERT(src_port.get_width() == tile_port_to_connect.get_width()); - /* Create a pin id mapping between the source port (top module) and the sink port (grid module) */ + /* Create a pin id mapping between the source port (top module) and the + * sink port (grid module) */ std::map sink2src_pin_map; for (size_t ipin = 0; ipin < tile_port_to_connect.get_width(); ++ipin) { size_t sink_pin = tile_port_to_connect.pins()[ipin]; @@ -801,34 +926,46 @@ int build_top_module_global_net_for_given_grid_module(ModuleManager& module_mana } /* Create the connections */ - for (size_t pin_id = tile_port_to_connect.get_lsb(); pin_id < tile_port_to_connect.get_msb() + 1; ++pin_id) { + for (size_t pin_id = tile_port_to_connect.get_lsb(); + pin_id < tile_port_to_connect.get_msb() + 1; ++pin_id) { int grid_pin_index = grid_pin_start_index + pin_id; /* Find the module pin */ size_t grid_pin_width = physical_tile->pin_width_offset[grid_pin_index]; - size_t grid_pin_height = physical_tile->pin_height_offset[grid_pin_index]; - std::vector pin_sides = find_physical_tile_pin_side(physical_tile, grid_pin_index, border_side); + size_t grid_pin_height = + physical_tile->pin_height_offset[grid_pin_index]; + std::vector pin_sides = find_physical_tile_pin_side( + physical_tile, grid_pin_index, border_side); - BasicPort grid_pin_info = vpr_device_annotation.physical_tile_pin_port_info(physical_tile, grid_pin_index); + BasicPort grid_pin_info = + vpr_device_annotation.physical_tile_pin_port_info(physical_tile, + grid_pin_index); VTR_ASSERT(true == grid_pin_info.is_valid()); /* Build nets */ for (const e_side& pin_side : pin_sides) { - std::string grid_port_name = generate_grid_port_name(grid_pin_width, grid_pin_height, subtile_index, - pin_side, - grid_pin_info); - ModulePortId grid_port_id = module_manager.find_module_port(grid_module, grid_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(grid_module, grid_port_id)); + std::string grid_port_name = + generate_grid_port_name(grid_pin_width, grid_pin_height, + subtile_index, pin_side, grid_pin_info); + ModulePortId grid_port_id = + module_manager.find_module_port(grid_module, grid_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(grid_module, + grid_port_id)); - VTR_ASSERT(1 == module_manager.module_port(grid_module, grid_port_id).get_width()); + VTR_ASSERT( + 1 == + module_manager.module_port(grid_module, grid_port_id).get_width()); - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - top_module, 0, - top_module_port, src_port.pins()[sink2src_pin_map[pin_id]]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, top_module, 0, top_module_port, + src_port.pins()[sink2src_pin_map[pin_id]]); VTR_ASSERT(ModuleNetId::INVALID() != net); - + /* Configure the net sink */ - BasicPort sink_port = module_manager.module_port(grid_module, grid_port_id); - module_manager.add_module_net_sink(top_module, net, grid_module, grid_instance, grid_port_id, sink_port.pins()[0]); + BasicPort sink_port = + module_manager.module_port(grid_module, grid_port_id); + module_manager.add_module_net_sink(top_module, net, grid_module, + grid_instance, grid_port_id, + sink_port.pins()[0]); } } } @@ -838,28 +975,33 @@ int build_top_module_global_net_for_given_grid_module(ModuleManager& module_mana } /******************************************************************** - * Add global ports from grid ports that are defined as global in tile annotation + * Add global ports from grid ports that are defined as global in tile + *annotation *******************************************************************/ -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) { +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) { int status = CMD_EXEC_SUCCESS; - /* Add the global ports which are NOT yet added to the top-level module + /* Add the global ports which are NOT yet added to the top-level module * (in different names than the global ports defined in circuit library */ std::vector global_ports_to_add; - for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) { - ModulePortId module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(tile_global_port)); - /* The global port size is derived from the maximum port size among all the tile port defintion */ + for (const TileGlobalPortId& tile_global_port : + tile_annotation.global_ports()) { + ModulePortId module_port = module_manager.find_module_port( + top_module, tile_annotation.global_port_name(tile_global_port)); + /* The global port size is derived from the maximum port size among all the + * tile port defintion */ if (ModulePortId::INVALID() == module_port) { - BasicPort global_port_to_add; - global_port_to_add.set_name(tile_annotation.global_port_name(tile_global_port)); + BasicPort global_port_to_add; + global_port_to_add.set_name( + tile_annotation.global_port_name(tile_global_port)); size_t max_port_size = 0; - for (const BasicPort& tile_port : tile_annotation.global_port_tile_ports(tile_global_port)) { + for (const BasicPort& tile_port : + tile_annotation.global_port_tile_ports(tile_global_port)) { max_port_size = std::max(tile_port.get_width(), max_port_size); } global_port_to_add.set_width(max_port_size); @@ -868,24 +1010,34 @@ int add_top_module_global_ports_from_grid_modules(ModuleManager& module_manager, } for (const BasicPort& global_port_to_add : global_ports_to_add) { - module_manager.add_port(top_module, global_port_to_add, ModuleManager::MODULE_GLOBAL_PORT); + module_manager.add_port(top_module, global_port_to_add, + ModuleManager::MODULE_GLOBAL_PORT); } /* Add module nets */ - std::map>> io_coordinates = generate_perimeter_grid_coordinates( grids); + std::map>> io_coordinates = + generate_perimeter_grid_coordinates(grids); - for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) { + for (const TileGlobalPortId& tile_global_port : + tile_annotation.global_ports()) { /* Must found one valid port! */ - ModulePortId top_module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(tile_global_port)); + ModulePortId top_module_port = module_manager.find_module_port( + 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]; + 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]; + 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 */ @@ -912,9 +1064,11 @@ int add_top_module_global_ports_from_grid_modules(ModuleManager& module_manager, /* 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()); + 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; } @@ -926,8 +1080,8 @@ int add_top_module_global_ports_from_grid_modules(ModuleManager& module_manager, continue; } /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ - if ( (0 < grids[ix][iy].width_offset) - || (0 < grids[ix][iy].height_offset)) { + if ((0 < grids[ix][iy].width_offset) || + (0 < grids[ix][iy].height_offset)) { continue; } @@ -937,17 +1091,10 @@ int add_top_module_global_ports_from_grid_modules(ModuleManager& module_manager, } /* 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); + 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; } @@ -956,26 +1103,32 @@ int add_top_module_global_ports_from_grid_modules(ModuleManager& module_manager, /* 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)) { + 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)) { + 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) { + 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 + * - 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; @@ -985,17 +1138,10 @@ int add_top_module_global_ports_from_grid_modules(ModuleManager& module_manager, } /* 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); + 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; } diff --git a/openfpga/src/fabric/build_top_module_connection.h b/openfpga/src/fabric/build_top_module_connection.h index c2219cb9d..3fb1860a1 100644 --- a/openfpga/src/fabric/build_top_module_connection.h +++ b/openfpga/src/fabric/build_top_module_connection.h @@ -5,14 +5,15 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "vtr_geometry.h" -#include "vtr_ndmatrix.h" + #include "device_grid.h" -#include "rr_graph_view.h" #include "device_rr_gsb.h" +#include "module_manager.h" +#include "rr_graph_view.h" #include "tile_annotation.h" #include "vpr_device_annotation.h" -#include "module_manager.h" +#include "vtr_geometry.h" +#include "vtr_ndmatrix.h" /******************************************************************** * Function declaration @@ -21,24 +22,19 @@ /* begin namespace openfpga */ namespace openfpga { -void add_top_module_nets_connect_grids_and_gsbs(ModuleManager& module_manager, - const ModuleId& top_module, - const VprDeviceAnnotation& vpr_device_annotation, - const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, - const vtr::Matrix& sb_instance_ids, - const std::map>& cb_instance_ids, - const bool& compact_routing_hierarchy, - const bool& duplicate_grid_pin); +void add_top_module_nets_connect_grids_and_gsbs( + ModuleManager& module_manager, const ModuleId& top_module, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const vtr::Matrix& grid_instance_ids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, const vtr::Matrix& sb_instance_ids, + const std::map>& cb_instance_ids, + const bool& compact_routing_hierarchy, const bool& duplicate_grid_pin); -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); +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); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_directs.cpp b/openfpga/src/fabric/build_top_module_directs.cpp index 91f0a1148..9b0179493 100644 --- a/openfpga/src/fabric/build_top_module_directs.cpp +++ b/openfpga/src/fabric/build_top_module_directs.cpp @@ -14,13 +14,11 @@ #include "openfpga_port.h" /* Headers from vpr library */ -#include "vpr_utils.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" -#include "module_manager_utils.h" - #include "build_top_module_directs.h" +#include "module_manager_utils.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "vpr_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -28,122 +26,177 @@ namespace openfpga { /******************************************************************** * Add module net for one direction connection between two CLBs or * two grids - * This function will + * This function will * 1. find the pin id and port id of the source clb port in module manager * 2. find the pin id and port id of the destination clb port in module manager - * 3. add a direct connection module to the top module - * 4. add a first module net and configure its source and sink, + * 3. add a direct connection module to the top module + * 4. add a first module net and configure its source and sink, * in order to connect the source pin to the input of the top module - * 4. add a second module net and configure its source and sink, + * 4. add a second module net and configure its source and sink, * in order to connect the sink pin to the output of the top module *******************************************************************/ -static -void add_module_nets_tile_direct_connection(ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const VprDeviceAnnotation& vpr_device_annotation, - const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, - const TileDirect& tile_direct, - const TileDirectId& tile_direct_id, - const ArchDirect& arch_direct) { +static void add_module_nets_tile_direct_connection( + ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const vtr::Matrix& grid_instance_ids, const TileDirect& tile_direct, + const TileDirectId& tile_direct_id, const ArchDirect& arch_direct) { vtr::Point device_size(grids.width(), grids.height()); /* Find the module name of source clb */ - vtr::Point src_clb_coord = tile_direct.from_tile_coordinate(tile_direct_id); - t_physical_tile_type_ptr src_grid_type = grids[src_clb_coord.x()][src_clb_coord.y()].type; - e_side src_grid_border_side = find_grid_border_side(device_size, src_clb_coord); + vtr::Point src_clb_coord = + tile_direct.from_tile_coordinate(tile_direct_id); + t_physical_tile_type_ptr src_grid_type = + grids[src_clb_coord.x()][src_clb_coord.y()].type; + e_side src_grid_border_side = + find_grid_border_side(device_size, src_clb_coord); std::string src_module_name_prefix(GRID_MODULE_NAME_PREFIX); - std::string src_module_name = generate_grid_block_module_name(src_module_name_prefix, std::string(src_grid_type->name), is_io_type(src_grid_type), src_grid_border_side); + std::string src_module_name = generate_grid_block_module_name( + src_module_name_prefix, std::string(src_grid_type->name), + is_io_type(src_grid_type), src_grid_border_side); ModuleId src_grid_module = module_manager.find_module(src_module_name); VTR_ASSERT(true == module_manager.valid_module_id(src_grid_module)); /* Record the instance id */ - size_t src_grid_instance = grid_instance_ids[src_clb_coord.x()][src_clb_coord.y()]; + size_t src_grid_instance = + grid_instance_ids[src_clb_coord.x()][src_clb_coord.y()]; /* Find the module name of sink clb */ - vtr::Point des_clb_coord = tile_direct.to_tile_coordinate(tile_direct_id); - t_physical_tile_type_ptr sink_grid_type = grids[des_clb_coord.x()][des_clb_coord.y()].type; - e_side sink_grid_border_side = find_grid_border_side(device_size, des_clb_coord); + vtr::Point des_clb_coord = + tile_direct.to_tile_coordinate(tile_direct_id); + t_physical_tile_type_ptr sink_grid_type = + grids[des_clb_coord.x()][des_clb_coord.y()].type; + e_side sink_grid_border_side = + find_grid_border_side(device_size, des_clb_coord); std::string sink_module_name_prefix(GRID_MODULE_NAME_PREFIX); - std::string sink_module_name = generate_grid_block_module_name(sink_module_name_prefix, std::string(sink_grid_type->name), is_io_type(sink_grid_type), sink_grid_border_side); + std::string sink_module_name = generate_grid_block_module_name( + sink_module_name_prefix, std::string(sink_grid_type->name), + is_io_type(sink_grid_type), sink_grid_border_side); ModuleId sink_grid_module = module_manager.find_module(sink_module_name); VTR_ASSERT(true == module_manager.valid_module_id(sink_grid_module)); /* Record the instance id */ - size_t sink_grid_instance = grid_instance_ids[des_clb_coord.x()][des_clb_coord.y()]; + size_t sink_grid_instance = + grid_instance_ids[des_clb_coord.x()][des_clb_coord.y()]; /* Find the module id of a direct connection module */ - CircuitModelId direct_circuit_model = arch_direct.circuit_model(tile_direct.arch_direct(tile_direct_id)); + CircuitModelId direct_circuit_model = + arch_direct.circuit_model(tile_direct.arch_direct(tile_direct_id)); std::string direct_module_name = circuit_lib.model_name(direct_circuit_model); ModuleId direct_module = module_manager.find_module(direct_module_name); VTR_ASSERT(true == module_manager.valid_module_id(direct_module)); /* Find inputs and outputs of the direct circuit module */ - std::vector direct_input_ports = circuit_lib.model_ports_by_type(direct_circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector direct_input_ports = + circuit_lib.model_ports_by_type(direct_circuit_model, + CIRCUIT_MODEL_PORT_INPUT, true); VTR_ASSERT(1 == direct_input_ports.size()); - ModulePortId direct_input_port_id = module_manager.find_module_port(direct_module, circuit_lib.port_prefix(direct_input_ports[0])); - VTR_ASSERT(true == module_manager.valid_module_port_id(direct_module, direct_input_port_id)); - VTR_ASSERT(1 == module_manager.module_port(direct_module, direct_input_port_id).get_width()); + ModulePortId direct_input_port_id = module_manager.find_module_port( + direct_module, circuit_lib.port_prefix(direct_input_ports[0])); + VTR_ASSERT(true == module_manager.valid_module_port_id(direct_module, + direct_input_port_id)); + VTR_ASSERT(1 == + module_manager.module_port(direct_module, direct_input_port_id) + .get_width()); - std::vector direct_output_ports = circuit_lib.model_ports_by_type(direct_circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector direct_output_ports = + circuit_lib.model_ports_by_type(direct_circuit_model, + CIRCUIT_MODEL_PORT_OUTPUT, true); VTR_ASSERT(1 == direct_output_ports.size()); - ModulePortId direct_output_port_id = module_manager.find_module_port(direct_module, circuit_lib.port_prefix(direct_output_ports[0])); - VTR_ASSERT(true == module_manager.valid_module_port_id(direct_module, direct_output_port_id)); - VTR_ASSERT(1 == module_manager.module_port(direct_module, direct_output_port_id).get_width()); + ModulePortId direct_output_port_id = module_manager.find_module_port( + direct_module, circuit_lib.port_prefix(direct_output_ports[0])); + VTR_ASSERT(true == module_manager.valid_module_port_id( + direct_module, direct_output_port_id)); + VTR_ASSERT(1 == + module_manager.module_port(direct_module, direct_output_port_id) + .get_width()); /* Generate the pin name of source port/pin in the grid */ e_side src_pin_grid_side = tile_direct.from_tile_side(tile_direct_id); size_t src_tile_pin = tile_direct.from_tile_pin(tile_direct_id); - t_physical_tile_type_ptr src_grid_type_descriptor = grids[src_clb_coord.x()][src_clb_coord.y()].type; - size_t src_pin_width = src_grid_type_descriptor->pin_width_offset[src_tile_pin]; - size_t src_pin_height = src_grid_type_descriptor->pin_height_offset[src_tile_pin]; + t_physical_tile_type_ptr src_grid_type_descriptor = + grids[src_clb_coord.x()][src_clb_coord.y()].type; + size_t src_pin_width = + src_grid_type_descriptor->pin_width_offset[src_tile_pin]; + size_t src_pin_height = + src_grid_type_descriptor->pin_height_offset[src_tile_pin]; - BasicPort src_pin_info = vpr_device_annotation.physical_tile_pin_port_info(src_grid_type_descriptor, src_tile_pin); + BasicPort src_pin_info = vpr_device_annotation.physical_tile_pin_port_info( + src_grid_type_descriptor, src_tile_pin); VTR_ASSERT(true == src_pin_info.is_valid()); - int src_subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(src_grid_type_descriptor, src_tile_pin); - VTR_ASSERT(OPEN != src_subtile_index && src_subtile_index < src_grid_type_descriptor->capacity); - std::string src_port_name = generate_grid_port_name(src_pin_width, src_pin_height, src_subtile_index, src_pin_grid_side, src_pin_info); - ModulePortId src_port_id = module_manager.find_module_port(src_grid_module, src_port_name); - if (true != module_manager.valid_module_port_id(src_grid_module, src_port_id)) { + int src_subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index( + src_grid_type_descriptor, src_tile_pin); + VTR_ASSERT(OPEN != src_subtile_index && + src_subtile_index < src_grid_type_descriptor->capacity); + std::string src_port_name = + generate_grid_port_name(src_pin_width, src_pin_height, src_subtile_index, + src_pin_grid_side, src_pin_info); + ModulePortId src_port_id = + module_manager.find_module_port(src_grid_module, src_port_name); + if (true != + module_manager.valid_module_port_id(src_grid_module, src_port_id)) { VTR_LOG_ERROR("Fail to find port '%s[%lu][%lu].%s'\n", src_module_name.c_str(), src_clb_coord.x(), src_clb_coord.y(), src_port_name.c_str()); } - VTR_ASSERT(true == module_manager.valid_module_port_id(src_grid_module, src_port_id)); - VTR_ASSERT(1 == module_manager.module_port(src_grid_module, src_port_id).get_width()); + VTR_ASSERT(true == + module_manager.valid_module_port_id(src_grid_module, src_port_id)); + VTR_ASSERT( + 1 == module_manager.module_port(src_grid_module, src_port_id).get_width()); /* Generate the pin name of sink port/pin in the grid */ e_side sink_pin_grid_side = tile_direct.to_tile_side(tile_direct_id); size_t sink_tile_pin = tile_direct.to_tile_pin(tile_direct_id); - t_physical_tile_type_ptr sink_grid_type_descriptor = grids[des_clb_coord.x()][des_clb_coord.y()].type; - size_t sink_pin_width = sink_grid_type_descriptor->pin_width_offset[src_tile_pin]; - size_t sink_pin_height = sink_grid_type_descriptor->pin_height_offset[src_tile_pin]; + t_physical_tile_type_ptr sink_grid_type_descriptor = + grids[des_clb_coord.x()][des_clb_coord.y()].type; + size_t sink_pin_width = + sink_grid_type_descriptor->pin_width_offset[src_tile_pin]; + size_t sink_pin_height = + sink_grid_type_descriptor->pin_height_offset[src_tile_pin]; - BasicPort sink_pin_info = vpr_device_annotation.physical_tile_pin_port_info(sink_grid_type_descriptor, sink_tile_pin); + BasicPort sink_pin_info = vpr_device_annotation.physical_tile_pin_port_info( + sink_grid_type_descriptor, sink_tile_pin); VTR_ASSERT(true == sink_pin_info.is_valid()); - int sink_subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(sink_grid_type_descriptor, sink_tile_pin); - VTR_ASSERT(OPEN != src_subtile_index && src_subtile_index < sink_grid_type_descriptor->capacity); - std::string sink_port_name = generate_grid_port_name(sink_pin_width, sink_pin_height, sink_subtile_index, sink_pin_grid_side, sink_pin_info); - ModulePortId sink_port_id = module_manager.find_module_port(sink_grid_module, sink_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(sink_grid_module, sink_port_id)); - VTR_ASSERT(1 == module_manager.module_port(sink_grid_module, sink_port_id).get_width()); + int sink_subtile_index = + vpr_device_annotation.physical_tile_pin_subtile_index( + sink_grid_type_descriptor, sink_tile_pin); + VTR_ASSERT(OPEN != src_subtile_index && + src_subtile_index < sink_grid_type_descriptor->capacity); + std::string sink_port_name = + generate_grid_port_name(sink_pin_width, sink_pin_height, sink_subtile_index, + sink_pin_grid_side, sink_pin_info); + ModulePortId sink_port_id = + module_manager.find_module_port(sink_grid_module, sink_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(sink_grid_module, + sink_port_id)); + VTR_ASSERT( + 1 == + module_manager.module_port(sink_grid_module, sink_port_id).get_width()); /* Add a submodule of direct connection module to the top-level module */ - size_t direct_instance_id = module_manager.num_instance(top_module, direct_module); + size_t direct_instance_id = + module_manager.num_instance(top_module, direct_module); module_manager.add_child_module(top_module, direct_module, false); /* Create the 1st module net */ - ModuleNetId net_direct_src = module_manager.create_module_net(top_module); + ModuleNetId net_direct_src = module_manager.create_module_net(top_module); /* Connect the wire between src_pin of clb and direct_instance input*/ - module_manager.add_module_net_source(top_module, net_direct_src, src_grid_module, src_grid_instance, src_port_id, 0); - module_manager.add_module_net_sink(top_module, net_direct_src, direct_module, direct_instance_id, direct_input_port_id, 0); + module_manager.add_module_net_source(top_module, net_direct_src, + src_grid_module, src_grid_instance, + src_port_id, 0); + module_manager.add_module_net_sink(top_module, net_direct_src, direct_module, + direct_instance_id, direct_input_port_id, + 0); /* Create the 2nd module net * Connect the wire between direct_instance output and sink_pin of clb */ - ModuleNetId net_direct_sink = create_module_source_pin_net(module_manager, top_module, direct_module, direct_instance_id, direct_output_port_id, 0); - module_manager.add_module_net_sink(top_module, net_direct_sink, sink_grid_module, sink_grid_instance, sink_port_id, 0); + ModuleNetId net_direct_sink = + create_module_source_pin_net(module_manager, top_module, direct_module, + direct_instance_id, direct_output_port_id, 0); + module_manager.add_module_net_sink(top_module, net_direct_sink, + sink_grid_module, sink_grid_instance, + sink_port_id, 0); } /******************************************************************** @@ -152,23 +205,19 @@ void add_module_nets_tile_direct_connection(ModuleManager& module_manager, * It can be more generic and thus cover all the grid types, * such as heterogeneous blocks *******************************************************************/ -void add_top_module_nets_tile_direct_connections(ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const VprDeviceAnnotation& vpr_device_annotation, - const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, - const TileDirect& tile_direct, - const ArchDirect& arch_direct) { - - vtr::ScopedStartFinishTimer timer("Add module nets for inter-tile connections"); +void add_top_module_nets_tile_direct_connections( + ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const vtr::Matrix& grid_instance_ids, const TileDirect& tile_direct, + const ArchDirect& arch_direct) { + vtr::ScopedStartFinishTimer timer( + "Add module nets for inter-tile connections"); for (const TileDirectId& tile_direct_id : tile_direct.directs()) { - add_module_nets_tile_direct_connection(module_manager, top_module, circuit_lib, - vpr_device_annotation, - grids, grid_instance_ids, - tile_direct, tile_direct_id, - arch_direct); + add_module_nets_tile_direct_connection( + module_manager, top_module, circuit_lib, vpr_device_annotation, grids, + grid_instance_ids, tile_direct, tile_direct_id, arch_direct); } } diff --git a/openfpga/src/fabric/build_top_module_directs.h b/openfpga/src/fabric/build_top_module_directs.h index aa46f0ec8..4de48efb7 100644 --- a/openfpga/src/fabric/build_top_module_directs.h +++ b/openfpga/src/fabric/build_top_module_directs.h @@ -5,14 +5,15 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "vtr_geometry.h" -#include "vtr_ndmatrix.h" + #include "arch_direct.h" -#include "tile_direct.h" -#include "vpr_device_annotation.h" +#include "circuit_library.h" #include "device_grid.h" #include "module_manager.h" -#include "circuit_library.h" +#include "tile_direct.h" +#include "vpr_device_annotation.h" +#include "vtr_geometry.h" +#include "vtr_ndmatrix.h" /******************************************************************** * Function declaration @@ -21,14 +22,12 @@ /* begin namespace openfpga */ namespace openfpga { -void add_top_module_nets_tile_direct_connections(ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const VprDeviceAnnotation& vpr_device_annotation, - const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, - const TileDirect& tile_direct, - const ArchDirect& arch_direct); +void add_top_module_nets_tile_direct_connections( + ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const vtr::Matrix& grid_instance_ids, const TileDirect& tile_direct, + const ArchDirect& arch_direct); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index b974b0dc5..9b61e0a55 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * This file includes functions that are used to organize memories + * This file includes functions that are used to organize memories * in the top module of FPGA fabric *******************************************************************/ #include @@ -13,42 +13,36 @@ #include "vpr_utils.h" /* Headers from openfpgashell library */ -#include "command_exit_codes.h" - -#include "rr_gsb_utils.h" -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" - -#include "memory_utils.h" -#include "memory_bank_utils.h" -#include "decoder_library_utils.h" -#include "module_manager_utils.h" #include "build_decoder_modules.h" -#include "build_top_module_memory_bank.h" #include "build_top_module_memory.h" +#include "build_top_module_memory_bank.h" +#include "command_exit_codes.h" +#include "decoder_library_utils.h" +#include "memory_bank_utils.h" +#include "memory_utils.h" +#include "module_manager_utils.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "rr_gsb_utils.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** * This function adds the CBX/CBY of a tile - * to the memory modules and memory instances + * to the memory modules and memory instances * This function is designed for organizing memory modules in top-level * module *******************************************************************/ -static -void organize_top_module_tile_cb_modules(ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - const vtr::Matrix& cb_instance_ids, - const DeviceRRGSB& device_rr_gsb, - const RRGSB& rr_gsb, - const t_rr_type& cb_type, - const bool& compact_routing_hierarchy) { +static void organize_top_module_tile_cb_modules( + ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, const vtr::Matrix& cb_instance_ids, + const DeviceRRGSB& device_rr_gsb, const RRGSB& rr_gsb, + const t_rr_type& cb_type, const bool& compact_routing_hierarchy) { /* If the CB does not exist, we can skip addition */ - if ( false == rr_gsb.is_cb_exist(cb_type)) { + if (false == rr_gsb.is_cb_exist(cb_type)) { return; } @@ -57,163 +51,175 @@ void organize_top_module_tile_cb_modules(ModuleManager& module_manager, return; } - vtr::Point cb_coord(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); - /* If we use compact routing hierarchy, we should instanciate the unique module of SB */ + vtr::Point cb_coord(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); + /* If we use compact routing hierarchy, we should instanciate the unique + * module of SB */ if (true == compact_routing_hierarchy) { /* Note: use GSB coordinate when inquire for unique modules!!! */ - const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(cb_type, vtr::Point(rr_gsb.get_x(), rr_gsb.get_y())); - cb_coord.set_x(unique_mirror.get_cb_x(cb_type)); - cb_coord.set_y(unique_mirror.get_cb_y(cb_type)); - } + const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module( + cb_type, vtr::Point(rr_gsb.get_x(), rr_gsb.get_y())); + cb_coord.set_x(unique_mirror.get_cb_x(cb_type)); + cb_coord.set_y(unique_mirror.get_cb_y(cb_type)); + } - std::string cb_module_name = generate_connection_block_module_name(cb_type, cb_coord); + std::string cb_module_name = + generate_connection_block_module_name(cb_type, cb_coord); ModuleId cb_module = module_manager.find_module(cb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); - /* Identify if this sub module includes configuration bits, + /* Identify if this sub module includes configuration bits, * we will update the memory module and instance list */ - if (0 < find_module_num_config_bits(module_manager, cb_module, - circuit_lib, sram_model, - sram_orgz_type)) { + if (0 < find_module_num_config_bits(module_manager, cb_module, circuit_lib, + sram_model, sram_orgz_type)) { /* CBX coordinate conversion calculation: (1,0) -> (2,1) */ - vtr::Point config_coord(rr_gsb.get_cb_x(cb_type) * 2, rr_gsb.get_cb_y(cb_type) * 2 + 1); + vtr::Point config_coord(rr_gsb.get_cb_x(cb_type) * 2, + rr_gsb.get_cb_y(cb_type) * 2 + 1); if (cb_type == CHANY) { - /* CBY has a different coordinate conversion calculation: (0,1) -> (1,2) */ - config_coord.set(rr_gsb.get_cb_x(cb_type) * 2 + 1, rr_gsb.get_cb_y(cb_type) * 2); + /* CBY has a different coordinate conversion calculation: (0,1) -> (1,2) + */ + config_coord.set(rr_gsb.get_cb_x(cb_type) * 2 + 1, + rr_gsb.get_cb_y(cb_type) * 2); } /* Note that use the original CB coodinate for instance id searching ! */ - module_manager.add_configurable_child(top_module, cb_module, cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)], config_coord); + module_manager.add_configurable_child( + top_module, cb_module, + cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)], + config_coord); } } /******************************************************************** * This function adds the SB, CBX, CBY and Grid of a tile - * to the memory modules and memory instances + * to the memory modules and memory instances * This function is designed for organizing memory modules in top-level * module - * This function also adds coordindates for each configurable child under the top-level module - * of a FPGA fabric. A configurable child could be a programmable block (grid), + * This function also adds coordindates for each configurable child under the + top-level module + * of a FPGA fabric. A configurable child could be a programmable block (grid), * a Connection Block (CBx/y) or a Switch block (SB). * This function, we consider a coordinate system as follows * - Each row may consist of either (1) grid and CBy or (2) CBx and SB * - Each column may consist of either (1) grid and CBx or (2) CBy and SB * - * Column 0 Column 1 + * Column 0 Column 1 * * +---------------+----------+ * | | | * | | | * | Grid | CBY | Row 3 - * | | | + * | | | * | | | * +---------------+----------+ - * | | | + * | | | * | CBX | SB | Row 2 * | | | * +---------------+----------+ * | | | * | | | * | Grid | CBY | Row 1 - * | | | + * | | | * | | | * +---------------+----------+ - * | | | + * | | | * | CBX | SB | Row 0 * | | | * +---------------+----------+ - - *******************************************************************/ -static -void organize_top_module_tile_memory_modules(ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, - const DeviceRRGSB& device_rr_gsb, - const vtr::Matrix& sb_instance_ids, - const std::map>& cb_instance_ids, - const bool& compact_routing_hierarchy, - const vtr::Point& tile_coord, - const e_side& tile_border_side) { + *******************************************************************/ +static void organize_top_module_tile_memory_modules( + ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, const DeviceGrid& grids, + const vtr::Matrix& grid_instance_ids, + const DeviceRRGSB& device_rr_gsb, const vtr::Matrix& sb_instance_ids, + const std::map>& cb_instance_ids, + const bool& compact_routing_hierarchy, const vtr::Point& tile_coord, + const e_side& tile_border_side) { vtr::Point gsb_coord_range = device_rr_gsb.get_gsb_range(); vtr::Point gsb_coord(tile_coord.x(), tile_coord.y() - 1); /* We do NOT consider SB and CBs if the gsb is not in the range! */ - if ( (gsb_coord.x() < gsb_coord_range.x()) - && (gsb_coord.y() < gsb_coord_range.y()) ) { + if ((gsb_coord.x() < gsb_coord_range.x()) && + (gsb_coord.y() < gsb_coord_range.y())) { const RRGSB& rr_gsb = device_rr_gsb.get_gsb(gsb_coord.x(), gsb_coord.y()); /* Find Switch Block: unique module id and instance id! * Note that switch block does always exist in a GSB */ vtr::Point sb_coord(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); - /* If we use compact routing hierarchy, we should instanciate the unique module of SB */ + /* If we use compact routing hierarchy, we should instanciate the unique + * module of SB */ if (true == compact_routing_hierarchy) { const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(sb_coord); - sb_coord.set_x(unique_mirror.get_sb_x()); - sb_coord.set_y(unique_mirror.get_sb_y()); - } + sb_coord.set_x(unique_mirror.get_sb_x()); + sb_coord.set_y(unique_mirror.get_sb_y()); + } std::string sb_module_name = generate_switch_block_module_name(sb_coord); ModuleId sb_module = module_manager.find_module(sb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); - /* Identify if this sub module includes configuration bits, + /* Identify if this sub module includes configuration bits, * we will update the memory module and instance list */ /* If the CB does not exist, we can skip addition */ - if ( true == rr_gsb.is_sb_exist()) { + if (true == rr_gsb.is_sb_exist()) { if (0 < find_module_num_config_bits(module_manager, sb_module, - circuit_lib, sram_model, + circuit_lib, sram_model, sram_orgz_type)) { - vtr::Point config_coord(rr_gsb.get_sb_x() * 2 + 1, rr_gsb.get_sb_y() * 2 + 1); - module_manager.add_configurable_child(top_module, sb_module, sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()], config_coord); + vtr::Point config_coord(rr_gsb.get_sb_x() * 2 + 1, + rr_gsb.get_sb_y() * 2 + 1); + module_manager.add_configurable_child( + top_module, sb_module, + sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()], config_coord); } } - - /* Try to find and add CBX and CBY */ - organize_top_module_tile_cb_modules(module_manager, top_module, circuit_lib, - sram_orgz_type, sram_model, - cb_instance_ids.at(CHANX), - device_rr_gsb, rr_gsb, CHANX, - compact_routing_hierarchy); - organize_top_module_tile_cb_modules(module_manager, top_module, circuit_lib, - sram_orgz_type, sram_model, - cb_instance_ids.at(CHANY), - device_rr_gsb, rr_gsb, CHANY, - compact_routing_hierarchy); + /* Try to find and add CBX and CBY */ + organize_top_module_tile_cb_modules( + module_manager, top_module, circuit_lib, sram_orgz_type, sram_model, + cb_instance_ids.at(CHANX), device_rr_gsb, rr_gsb, CHANX, + compact_routing_hierarchy); + + organize_top_module_tile_cb_modules( + module_manager, top_module, circuit_lib, sram_orgz_type, sram_model, + cb_instance_ids.at(CHANY), device_rr_gsb, rr_gsb, CHANY, + compact_routing_hierarchy); } /* Find the module name for this type of grid */ - t_physical_tile_type_ptr grid_type = grids[tile_coord.x()][tile_coord.y()].type; + t_physical_tile_type_ptr grid_type = + grids[tile_coord.x()][tile_coord.y()].type; /* Skip EMPTY Grid */ if (true == is_empty_type(grid_type)) { return; } - /* Skip width > 1 or height > 1 Grid, which should already been processed when offset=0 */ - if ( (0 < grids[tile_coord.x()][tile_coord.y()].width_offset) - || (0 < grids[tile_coord.x()][tile_coord.y()].height_offset) ) { + /* Skip width > 1 or height > 1 Grid, which should already been processed when + * offset=0 */ + if ((0 < grids[tile_coord.x()][tile_coord.y()].width_offset) || + (0 < grids[tile_coord.x()][tile_coord.y()].height_offset)) { return; } std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); - std::string grid_module_name = generate_grid_block_module_name(grid_module_name_prefix, std::string(grid_type->name), is_io_type(grid_type), tile_border_side); + std::string grid_module_name = generate_grid_block_module_name( + grid_module_name_prefix, std::string(grid_type->name), + is_io_type(grid_type), tile_border_side); ModuleId grid_module = module_manager.find_module(grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); - /* Identify if this sub module includes configuration bits, + /* Identify if this sub module includes configuration bits, * we will update the memory module and instance list */ - if (0 < find_module_num_config_bits(module_manager, grid_module, - circuit_lib, sram_model, - sram_orgz_type)) { + if (0 < find_module_num_config_bits(module_manager, grid_module, circuit_lib, + sram_model, sram_orgz_type)) { vtr::Point config_coord(tile_coord.x() * 2, tile_coord.y() * 2); - module_manager.add_configurable_child(top_module, grid_module, grid_instance_ids[tile_coord.x()][tile_coord.y()], config_coord); + module_manager.add_configurable_child( + top_module, grid_module, + grid_instance_ids[tile_coord.x()][tile_coord.y()], config_coord); } } @@ -256,12 +262,11 @@ void organize_top_module_tile_memory_modules(ModuleManager& module_manager, * - This function should NOT modify configurable children * *******************************************************************/ -static -void build_top_module_configurable_regions(ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigProtocol& config_protocol) { - - vtr::ScopedStartFinishTimer timer("Build configurable regions for the top module"); +static void build_top_module_configurable_regions( + ModuleManager& module_manager, const ModuleId& top_module, + const ConfigProtocol& config_protocol) { + vtr::ScopedStartFinishTimer timer( + "Build configurable regions for the top module"); /* Ensure we have valid configurable children */ VTR_ASSERT(false == module_manager.configurable_children(top_module).empty()); @@ -270,45 +275,51 @@ void build_top_module_configurable_regions(ModuleManager& module_manager, VTR_ASSERT(1 <= config_protocol.num_regions()); /* Exclude decoders from the list */ - size_t num_configurable_children = module_manager.configurable_children(top_module).size(); - if (CONFIG_MEM_MEMORY_BANK == config_protocol.type() - || CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) { + size_t num_configurable_children = + module_manager.configurable_children(top_module).size(); + if (CONFIG_MEM_MEMORY_BANK == config_protocol.type() || + CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) { num_configurable_children -= 2; } else if (CONFIG_MEM_FRAME_BASED == config_protocol.type()) { num_configurable_children -= 1; } /* Evenly place each configurable child to each region */ - size_t num_children_per_region = num_configurable_children / config_protocol.num_regions(); + size_t num_children_per_region = + num_configurable_children / config_protocol.num_regions(); size_t region_child_counter = 0; bool create_region = true; ConfigRegionId curr_region = ConfigRegionId::INVALID(); - for (size_t ichild = 0; ichild < module_manager.configurable_children(top_module).size(); ++ichild) { + for (size_t ichild = 0; + ichild < module_manager.configurable_children(top_module).size(); + ++ichild) { if (true == create_region) { curr_region = module_manager.add_config_region(top_module); } /* Add the child to a region */ - module_manager.add_configurable_child_to_region(top_module, - curr_region, - module_manager.configurable_children(top_module)[ichild], - module_manager.configurable_child_instances(top_module)[ichild], - ichild); + module_manager.add_configurable_child_to_region( + top_module, curr_region, + module_manager.configurable_children(top_module)[ichild], + module_manager.configurable_child_instances(top_module)[ichild], ichild); /* See if the current region is full or not: - * For the last region, we will keep adding until we finish all the children + * For the last region, we will keep adding until we finish all the children */ region_child_counter++; if (region_child_counter < num_children_per_region) { create_region = false; - } else if (size_t(curr_region) < (size_t)config_protocol.num_regions() - 1) { + } else if (size_t(curr_region) < + (size_t)config_protocol.num_regions() - 1) { create_region = true; region_child_counter = 0; } } - /* Ensure that the number of configurable regions created matches the definition */ - VTR_ASSERT((size_t)config_protocol.num_regions() == module_manager.regions(top_module).size()); + /* Ensure that the number of configurable regions created matches the + * definition */ + VTR_ASSERT((size_t)config_protocol.num_regions() == + module_manager.regions(top_module).size()); } /******************************************************************** @@ -323,7 +334,7 @@ void build_top_module_configurable_regions(ModuleManager& module_manager, * * Inter-tile connection: * - * Inter-tile connection always start from the I/O peripherals + * Inter-tile connection always start from the I/O peripherals * and the core tiles (CLBs and heterogeneous blocks). * The sequence of configuration memory will be organized as follows: * - I/O peripherals @@ -336,9 +347,9 @@ void build_top_module_configurable_regions(ModuleManager& module_manager, * - One row upper, i.e. Tile[i+1 .. j] (From right to left) * - Repeat until we finish all the rows * - * Note: the tail may not always be on the top-right corner as shown in the figure. - * It may exit at the top-left corner. - * This really depends on the number of rows your have in the core tile array. + * Note: the tail may not always be on the top-right corner as shown in the + *figure. It may exit at the top-left corner. This really depends on the number + *of rows your have in the core tile array. * * Note: the organization of inter-tile aims to reduce the wire length * to connect between tiles. Therefore, it is organized as a snake @@ -383,20 +394,22 @@ void build_top_module_configurable_regions(ModuleManager& module_manager, * - Switch Block (SB) * - X-directional Connection Block (CBX) * - Y-directional Connection Block (CBY) - * - Configurable Logic Block (CLB), which could also be heterogeneous blocks + * - Configurable Logic Block (CLB), which could also be heterogeneous + *blocks * * Note: * Due to multi-column and multi-width hetergeoenous blocks, * each tile may not have one or more of SB, CBX, CBY, CLB * In such case, the sequence will be respected. - * The missing block will just be skipped when organizing the configuration memories. + * The missing block will just be skipped when organizing the configuration + *memories. * * Tile * +---------------+----------+ * <-+---------------+ + | * | | | | * | CLB | | CBY | - * | +-|-+ | + * | +-|-+ | * | | | | * +---------------+----------+ * | +-+----+-----+---<--- @@ -405,24 +418,20 @@ void build_top_module_configurable_regions(ModuleManager& module_manager, * +---------------+----------+ * *******************************************************************/ -void organize_top_module_memory_modules(ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const CircuitModelId& sram_model, - const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, - const DeviceRRGSB& device_rr_gsb, - const vtr::Matrix& sb_instance_ids, - const std::map>& cb_instance_ids, - const bool& compact_routing_hierarchy) { - +void organize_top_module_memory_modules( + ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const CircuitModelId& sram_model, const DeviceGrid& grids, + const vtr::Matrix& grid_instance_ids, + const DeviceRRGSB& device_rr_gsb, const vtr::Matrix& sb_instance_ids, + const std::map>& cb_instance_ids, + const bool& compact_routing_hierarchy) { /* Ensure clean vectors to return */ VTR_ASSERT(true == module_manager.configurable_children(top_module).empty()); /* First, organize the I/O tiles on the border */ /* Special for the I/O tileas on RIGHT and BOTTOM, - * which are only I/O blocks, which do NOT contain CBs and SBs + * which are only I/O blocks, which do NOT contain CBs and SBs */ std::vector io_sides{BOTTOM, RIGHT, TOP, LEFT}; std::map>> io_coords; @@ -437,11 +446,11 @@ void organize_top_module_memory_modules(ModuleManager& module_manager, io_coords[RIGHT].push_back(vtr::Point(grids.width() - 1, iy)); } - /* TOP side I/Os - * Special case for TOP side: We need tile at ix = 0, which has a SB!!! + /* TOP side I/Os + * Special case for TOP side: We need tile at ix = 0, which has a SB!!! * * TOP-LEFT CORNER of FPGA fabric - * + * * +--------+ +-------+ * | EMPTY | | EMPTY | * | Grid | | CBX | @@ -451,7 +460,7 @@ void organize_top_module_memory_modules(ModuleManager& module_manager, * | EMPTY | | SB | * | CBX | | [0][x] | * +--------+ +--------+ - * + * */ for (size_t ix = grids.width() - 2; ix >= 1; --ix) { io_coords[TOP].push_back(vtr::Point(ix, grids.height() - 1)); @@ -466,12 +475,10 @@ void organize_top_module_memory_modules(ModuleManager& module_manager, for (const e_side& io_side : io_sides) { for (const vtr::Point& io_coord : io_coords[io_side]) { /* Identify the GSB that surrounds the grid */ - organize_top_module_tile_memory_modules(module_manager, top_module, - circuit_lib, config_protocol.type(), sram_model, - grids, grid_instance_ids, - device_rr_gsb, sb_instance_ids, cb_instance_ids, - compact_routing_hierarchy, - io_coord, io_side); + organize_top_module_tile_memory_modules( + module_manager, top_module, circuit_lib, config_protocol.type(), + sram_model, grids, grid_instance_ids, device_rr_gsb, sb_instance_ids, + cb_instance_ids, compact_routing_hierarchy, io_coord, io_side); } } @@ -482,13 +489,13 @@ void organize_top_module_memory_modules(ModuleManager& module_manager, /* For positive direction: -----> */ if (true == positive_direction) { for (size_t ix = 1; ix < grids.width() - 1; ++ix) { - core_coords.push_back(vtr::Point(ix, iy)); + core_coords.push_back(vtr::Point(ix, iy)); } } else { VTR_ASSERT(false == positive_direction); /* For negative direction: -----> */ for (size_t ix = grids.width() - 2; ix >= 1; --ix) { - core_coords.push_back(vtr::Point(ix, iy)); + core_coords.push_back(vtr::Point(ix, iy)); } } /* Flip the positive direction to be negative */ @@ -496,35 +503,33 @@ void organize_top_module_memory_modules(ModuleManager& module_manager, } for (const vtr::Point& core_coord : core_coords) { - organize_top_module_tile_memory_modules(module_manager, top_module, - circuit_lib, config_protocol.type(), sram_model, - grids, grid_instance_ids, - device_rr_gsb, sb_instance_ids, cb_instance_ids, - compact_routing_hierarchy, - core_coord, NUM_SIDES); + organize_top_module_tile_memory_modules( + module_manager, top_module, circuit_lib, config_protocol.type(), + sram_model, grids, grid_instance_ids, device_rr_gsb, sb_instance_ids, + cb_instance_ids, compact_routing_hierarchy, core_coord, NUM_SIDES); } /* Split memory modules into different regions */ - build_top_module_configurable_regions(module_manager, top_module, config_protocol); + build_top_module_configurable_regions(module_manager, top_module, + config_protocol); } - /******************************************************************** - * Shuffle the configurable children in a random sequence + * Shuffle the configurable children in a random sequence * * TODO: May use a more customized shuffle mechanism * TODO: Apply region-based shuffling - * The shuffling will be applied to each separated regions + * The shuffling will be applied to each separated regions * Configurable children will not shuffled from a region * to another, instead they should stay in the same region * - * Note: - * - This function should NOT be called + * Note: + * - This function should NOT be called * before allocating any configurable child ********************************************************************/ -void shuffle_top_module_configurable_children(ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigProtocol& config_protocol) { +void shuffle_top_module_configurable_children( + ModuleManager& module_manager, const ModuleId& top_module, + const ConfigProtocol& config_protocol) { size_t num_keys = module_manager.configurable_children(top_module).size(); std::vector shuffled_keys; shuffled_keys.reserve(num_keys); @@ -535,40 +540,43 @@ void shuffle_top_module_configurable_children(ModuleManager& module_manager, std::random_shuffle(shuffled_keys.begin(), shuffled_keys.end()); /* Cache the configurable children and their instances */ - std::vector orig_configurable_children = module_manager.configurable_children(top_module); - std::vector orig_configurable_child_instances = module_manager.configurable_child_instances(top_module); - std::vector> orig_configurable_child_coordinates = module_manager.configurable_child_coordinates(top_module); - + std::vector orig_configurable_children = + module_manager.configurable_children(top_module); + std::vector orig_configurable_child_instances = + module_manager.configurable_child_instances(top_module); + std::vector> orig_configurable_child_coordinates = + module_manager.configurable_child_coordinates(top_module); + /* Reorganize the configurable children */ module_manager.clear_configurable_children(top_module); for (size_t ikey = 0; ikey < num_keys; ++ikey) { - module_manager.add_configurable_child(top_module, - orig_configurable_children[shuffled_keys[ikey]], - orig_configurable_child_instances[shuffled_keys[ikey]], - orig_configurable_child_coordinates[shuffled_keys[ikey]]); + module_manager.add_configurable_child( + top_module, orig_configurable_children[shuffled_keys[ikey]], + orig_configurable_child_instances[shuffled_keys[ikey]], + orig_configurable_child_coordinates[shuffled_keys[ikey]]); } /* Reset configurable regions */ module_manager.clear_config_region(top_module); - build_top_module_configurable_regions(module_manager, top_module, config_protocol); + build_top_module_configurable_regions(module_manager, top_module, + config_protocol); } /******************************************************************** * Load configurable children from a fabric key to top-level module * - * Note: + * Note: * - This function will overwrite any exisiting configurable children * under the top module * * Return 0 - Success * Return 1 - Fatal errors ********************************************************************/ -int load_top_module_memory_modules_from_fabric_key(ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const FabricKey& fabric_key) { +int load_top_module_memory_modules_from_fabric_key( + ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const FabricKey& fabric_key) { /* Ensure a clean start */ module_manager.clear_configurable_children(top_module); @@ -576,7 +584,8 @@ int load_top_module_memory_modules_from_fabric_key(ModuleManager& module_manager for (const FabricRegionId& region : fabric_key.regions()) { /* Create a configurable region in the top module */ - ConfigRegionId top_module_config_region = module_manager.add_config_region(top_module); + ConfigRegionId top_module_config_region = + module_manager.add_config_region(top_module); for (const FabricKeyId& key : fabric_key.region_keys(region)) { /* Find if instance id is valid */ std::pair instance_info(ModuleId::INVALID(), 0); @@ -586,204 +595,228 @@ int load_top_module_memory_modules_from_fabric_key(ModuleManager& module_manager * Otherwise, we have to exhaustively find the module id and instance id */ if (!fabric_key.key_name(key).empty()) { - instance_info.first = module_manager.find_module(fabric_key.key_name(key)); - instance_info.second = module_manager.instance_id(top_module, instance_info.first, fabric_key.key_alias(key)); + instance_info.first = + module_manager.find_module(fabric_key.key_name(key)); + instance_info.second = module_manager.instance_id( + top_module, instance_info.first, fabric_key.key_alias(key)); } else { - instance_info = find_module_manager_instance_module_info(module_manager, top_module, fabric_key.key_alias(key)); + instance_info = find_module_manager_instance_module_info( + module_manager, top_module, fabric_key.key_alias(key)); } - } else { - /* If we do not have an alias, we use the name and value to build the info deck */ - instance_info.first = module_manager.find_module(fabric_key.key_name(key)); + } else { + /* If we do not have an alias, we use the name and value to build the + * info deck */ + instance_info.first = + module_manager.find_module(fabric_key.key_name(key)); instance_info.second = fabric_key.key_value(key); } if (false == module_manager.valid_module_id(instance_info.first)) { if (!fabric_key.key_alias(key).empty()) { VTR_LOG_ERROR("Invalid key alias '%s'!\n", - fabric_key.key_alias(key).c_str()); + fabric_key.key_alias(key).c_str()); } else { VTR_LOG_ERROR("Invalid key name '%s'!\n", - fabric_key.key_name(key).c_str()); + fabric_key.key_name(key).c_str()); } - return CMD_EXEC_FATAL_ERROR; + return CMD_EXEC_FATAL_ERROR; } - if (false == module_manager.valid_module_instance_id(top_module, instance_info.first, instance_info.second)) { + if (false == module_manager.valid_module_instance_id( + top_module, instance_info.first, instance_info.second)) { if (!fabric_key.key_alias(key).empty()) { VTR_LOG_ERROR("Invalid key alias '%s'!\n", - fabric_key.key_alias(key).c_str()); + fabric_key.key_alias(key).c_str()); } else { - VTR_LOG_ERROR("Invalid key value '%ld'!\n", - instance_info.second); + VTR_LOG_ERROR("Invalid key value '%ld'!\n", instance_info.second); } - return CMD_EXEC_FATAL_ERROR; + return CMD_EXEC_FATAL_ERROR; } /* If the the child has not configuration bits, error out */ - if (0 == find_module_num_config_bits(module_manager, instance_info.first, - circuit_lib, config_protocol.memory_model(), - config_protocol.type())) { + if (0 == find_module_num_config_bits( + module_manager, instance_info.first, circuit_lib, + config_protocol.memory_model(), config_protocol.type())) { if (!fabric_key.key_alias(key).empty()) { - VTR_LOG_ERROR("Invalid key alias '%s' which has zero configuration bits!\n", - fabric_key.key_alias(key).c_str()); + VTR_LOG_ERROR( + "Invalid key alias '%s' which has zero configuration bits!\n", + fabric_key.key_alias(key).c_str()); } else { - VTR_LOG_ERROR("Invalid key name '%s' which has zero configuration bits!\n", - fabric_key.key_name(key).c_str()); + VTR_LOG_ERROR( + "Invalid key name '%s' which has zero configuration bits!\n", + fabric_key.key_name(key).c_str()); } - return CMD_EXEC_FATAL_ERROR; + return CMD_EXEC_FATAL_ERROR; } /* Now we can add the child to configurable children of the top module */ - module_manager.add_configurable_child(top_module, - instance_info.first, + module_manager.add_configurable_child(top_module, instance_info.first, instance_info.second, fabric_key.key_coordinate(key)); - module_manager.add_configurable_child_to_region(top_module, - top_module_config_region, - instance_info.first, - instance_info.second, - curr_configurable_child_id); + module_manager.add_configurable_child_to_region( + top_module, top_module_config_region, instance_info.first, + instance_info.second, curr_configurable_child_id); curr_configurable_child_id++; } } return CMD_EXEC_SUCCESS; -} +} /******************************************************************** - * Find the number of configuration bits in each region of + * Find the number of configuration bits in each region of * the top-level module. * - * Note: + * Note: * - This function should be called after the configurable children * is loaded to the top-level module! ********************************************************************/ -TopModuleNumConfigBits find_top_module_regional_num_config_bit(const ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& config_protocol_type) { +TopModuleNumConfigBits find_top_module_regional_num_config_bit( + const ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type& config_protocol_type) { /* Initialize the number of configuration bits for each region */ - TopModuleNumConfigBits num_config_bits(module_manager.regions(top_module).size(), std::pair(0, 0)); + TopModuleNumConfigBits num_config_bits( + module_manager.regions(top_module).size(), std::pair(0, 0)); switch (config_protocol_type) { - case CONFIG_MEM_STANDALONE: - case CONFIG_MEM_SCAN_CHAIN: - case CONFIG_MEM_MEMORY_BANK: { - /* For flatten, chain and memory bank configuration protocol - * The number of configuration bits is the sum of configuration bits - * per configurable children in each region - */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - for (const ModuleId& child_module : module_manager.region_configurable_children(top_module, config_region)) { - num_config_bits[config_region].first += find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type); - } - } - break; - } - case CONFIG_MEM_QL_MEMORY_BANK: { - /* For QL memory bank: we will use the row and column information for each configuration child - * in order to identify the number of unique BLs and WLs - * In this configuration protocol, - * - all the configurable child in the same row will share the same WLs - * - the number of WLs per row is limited by the configurable child which requires most WLs - * - each row has independent WLs - * - all the configurable child in the same column will share the same BLs - * - the number of BLs per column is limited by the configurable child which requires most BLs - * - each column has independent BLs - */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - std::map num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module, - config_region, - circuit_lib, sram_model); - std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, - config_region, - circuit_lib, sram_model); - for (const auto& kv : num_bls_per_tile) { - num_config_bits[config_region].first += kv.second; - } - for (const auto& kv : num_wls_per_tile) { - num_config_bits[config_region].second += kv.second; - } - } - break; - } - case CONFIG_MEM_FRAME_BASED: { - /* For frame-based configuration protocol - * The number of configuration bits is the sum of - * - the maximum of configuration bits among configurable children - * - and the number of configurable children - */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - for (const ModuleId& child_module : module_manager.region_configurable_children(top_module, config_region)) { - size_t temp_num_config_bits = find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type); - num_config_bits[config_region].first = std::max(temp_num_config_bits, num_config_bits[config_region].first); - } - - /* If there are more than 2 configurable children, we need a decoder - * Otherwise, we can just short wire the address port to the children + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_SCAN_CHAIN: + case CONFIG_MEM_MEMORY_BANK: { + /* For flatten, chain and memory bank configuration protocol + * The number of configuration bits is the sum of configuration bits + * per configurable children in each region */ - if (1 < module_manager.region_configurable_children(top_module, config_region).size()) { - num_config_bits[config_region].first += find_mux_local_decoder_addr_size(module_manager.region_configurable_children(top_module, config_region).size()); + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + for (const ModuleId& child_module : + module_manager.region_configurable_children(top_module, + config_region)) { + num_config_bits[config_region].first += find_module_num_config_bits( + module_manager, child_module, circuit_lib, sram_model, + config_protocol_type); + } } - } + break; + } + case CONFIG_MEM_QL_MEMORY_BANK: { + /* For QL memory bank: we will use the row and column information for each + * configuration child in order to identify the number of unique BLs and + * WLs In this configuration protocol, + * - all the configurable child in the same row will share the same WLs + * - the number of WLs per row is limited by the configurable child which + * requires most WLs + * - each row has independent WLs + * - all the configurable child in the same column will share the same BLs + * - the number of BLs per column is limited by the configurable child + * which requires most BLs + * - each column has independent BLs + */ + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + std::map num_bls_per_tile = + compute_memory_bank_regional_bitline_numbers_per_tile( + module_manager, top_module, config_region, circuit_lib, sram_model); + std::map num_wls_per_tile = + compute_memory_bank_regional_wordline_numbers_per_tile( + module_manager, top_module, config_region, circuit_lib, sram_model); + for (const auto& kv : num_bls_per_tile) { + num_config_bits[config_region].first += kv.second; + } + for (const auto& kv : num_wls_per_tile) { + num_config_bits[config_region].second += kv.second; + } + } + break; + } + case CONFIG_MEM_FRAME_BASED: { + /* For frame-based configuration protocol + * The number of configuration bits is the sum of + * - the maximum of configuration bits among configurable children + * - and the number of configurable children + */ + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + for (const ModuleId& child_module : + module_manager.region_configurable_children(top_module, + config_region)) { + size_t temp_num_config_bits = find_module_num_config_bits( + module_manager, child_module, circuit_lib, sram_model, + config_protocol_type); + num_config_bits[config_region].first = std::max( + temp_num_config_bits, num_config_bits[config_region].first); + } - break; - } + /* If there are more than 2 configurable children, we need a decoder + * Otherwise, we can just short wire the address port to the children + */ + if (1 < module_manager + .region_configurable_children(top_module, config_region) + .size()) { + num_config_bits[config_region].first += + find_mux_local_decoder_addr_size( + module_manager + .region_configurable_children(top_module, config_region) + .size()); + } + } - default: - VTR_LOG_ERROR("Invalid type of SRAM organization !\n"); - exit(1); + break; + } + + default: + VTR_LOG_ERROR("Invalid type of SRAM organization !\n"); + exit(1); } return num_config_bits; } /******************************************************************** - * Generate a list of ports that are used for SRAM configuration + * Generate a list of ports that are used for SRAM configuration * to the top-level module - * 1. Standalone SRAMs: - * use the suggested port_size + * 1. Standalone SRAMs: + * use the suggested port_size * 2. Scan-chain Flip-flops: - * IMPORTANT: the port size will be limited by the number of configurable regions + * IMPORTANT: the port size will be limited by the number of configurable + *regions * 3. Memory decoders: - * use the suggested port_size + * use the suggested port_size ********************************************************************/ -static -size_t generate_top_module_sram_port_size(const ConfigProtocol& config_protocol, - const size_t& num_config_bits) { +static size_t generate_top_module_sram_port_size( + const ConfigProtocol& config_protocol, const size_t& num_config_bits) { size_t sram_port_size = num_config_bits; switch (config_protocol.type()) { - case CONFIG_MEM_STANDALONE: - break; - case CONFIG_MEM_SCAN_CHAIN: - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: - case CONFIG_MEM_FRAME_BASED: - /* CCFF head/tail, data input could be multi-bit ports */ - sram_port_size = config_protocol.num_regions(); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization!\n"); - exit(1); + case CONFIG_MEM_STANDALONE: + break; + case CONFIG_MEM_SCAN_CHAIN: + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: + case CONFIG_MEM_FRAME_BASED: + /* CCFF head/tail, data input could be multi-bit ports */ + sram_port_size = config_protocol.num_regions(); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization!\n"); + exit(1); } return sram_port_size; } /******************************************************************** - * Add a list of ports that are used for SRAM configuration to the FPGA + * Add a list of ports that are used for SRAM configuration to the FPGA * top-level module - * The type and names of added ports strongly depend on the + * The type and names of added ports strongly depend on the * organization of SRAMs. - * - Standalone SRAMs: - * two ports will be added, which are BL and WL + * - Standalone SRAMs: + * two ports will be added, which are BL and WL * - Scan-chain Flip-flops: - * two ports will be added, which are the head of scan-chain + * two ports will be added, which are the head of scan-chain * and the tail of scan-chain - * IMPORTANT: the port size will be forced to 1 in this case + * IMPORTANT: the port size will be forced to 1 in this case * because the head and tail are both 1-bit ports!!! * - Memory decoders: * - An enable signal @@ -795,108 +828,134 @@ size_t generate_top_module_sram_port_size(const ConfigProtocol& config_protocol, * - An BL address port * - A WL address port * - A data-in port for the BL decoder - * @note In this memory decoders, the address size will be computed in a different way than the regular one + * @note In this memory decoders, the address size will be computed in a + *different way than the regular one * - Frame-based memory: * - An Enable signal - * - An address port, whose size depends on the number of config bits + * - An address port, whose size depends on the number of config bits * and the maximum size of address ports of configurable children * - An data_in port (single-bit) ********************************************************************/ -void add_top_module_sram_ports(ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const ConfigProtocol& config_protocol, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const TopModuleNumConfigBits& num_config_bits) { - std::vector sram_port_names = generate_sram_port_names(circuit_lib, sram_model, config_protocol.type()); +void add_top_module_sram_ports( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const ConfigProtocol& config_protocol, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const TopModuleNumConfigBits& num_config_bits) { + std::vector sram_port_names = + generate_sram_port_names(circuit_lib, sram_model, config_protocol.type()); size_t total_num_config_bits = 0; for (const auto& curr_num_config_bits : num_config_bits) { total_num_config_bits += curr_num_config_bits.first; } - size_t sram_port_size = generate_top_module_sram_port_size(config_protocol, total_num_config_bits); + size_t sram_port_size = + generate_top_module_sram_port_size(config_protocol, total_num_config_bits); /* Add ports to the module manager */ switch (config_protocol.type()) { - case CONFIG_MEM_STANDALONE: { - for (const std::string& sram_port_name : sram_port_names) { - /* Add generated ports to the ModuleManager */ - BasicPort sram_port(sram_port_name, sram_port_size); - module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_INPUT_PORT); - } - break; - } - case CONFIG_MEM_MEMORY_BANK: { - BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); - module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); - - /* BL address size is the largest among all the regions */ - size_t bl_addr_size = 0; - for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - bl_addr_size = std::max(bl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].first)); - } - BasicPort bl_addr_port(std::string(DECODER_BL_ADDRESS_PORT_NAME), bl_addr_size); - module_manager.add_port(module_id, bl_addr_port, ModuleManager::MODULE_INPUT_PORT); - - /* WL address size is the largest among all the regions */ - size_t wl_addr_size = 0; - for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - wl_addr_size = std::max(wl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].first)); - } - BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size); - module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT); - - /* Data input should be dependent on the number of configuration regions*/ - BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), config_protocol.num_regions()); - module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT); - - break; - } - case CONFIG_MEM_QL_MEMORY_BANK: { - add_top_module_ql_memory_bank_sram_ports(module_manager, module_id, circuit_lib, config_protocol, blwl_sr_banks, num_config_bits); - break; - } - case CONFIG_MEM_SCAN_CHAIN: { - /* Note that configuration chain tail is an output while head is an input - * IMPORTANT: this is co-designed with function generate_sram_port_names() - * If the return vector is changed, the following codes MUST be adapted! - */ - VTR_ASSERT(2 == sram_port_names.size()); - size_t port_counter = 0; - for (const std::string& sram_port_name : sram_port_names) { - /* Add generated ports to the ModuleManager */ - BasicPort sram_port(sram_port_name, sram_port_size); - if (0 == port_counter) { - module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_INPUT_PORT); - } else { - VTR_ASSERT(1 == port_counter); - module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_OUTPUT_PORT); + case CONFIG_MEM_STANDALONE: { + for (const std::string& sram_port_name : sram_port_names) { + /* Add generated ports to the ModuleManager */ + BasicPort sram_port(sram_port_name, sram_port_size); + module_manager.add_port(module_id, sram_port, + ModuleManager::MODULE_INPUT_PORT); } - port_counter++; + break; } - break; - } - case CONFIG_MEM_FRAME_BASED: { - BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); - module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); + case CONFIG_MEM_MEMORY_BANK: { + BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); + module_manager.add_port(module_id, en_port, + ModuleManager::MODULE_INPUT_PORT); - size_t max_num_config_bits = 0; - for (const auto& curr_num_config_bits : num_config_bits) { - max_num_config_bits = std::max(max_num_config_bits, curr_num_config_bits.first); + /* BL address size is the largest among all the regions */ + size_t bl_addr_size = 0; + for (const ConfigRegionId& config_region : + module_manager.regions(module_id)) { + bl_addr_size = std::max( + bl_addr_size, + find_memory_decoder_addr_size(num_config_bits[config_region].first)); + } + BasicPort bl_addr_port(std::string(DECODER_BL_ADDRESS_PORT_NAME), + bl_addr_size); + module_manager.add_port(module_id, bl_addr_port, + ModuleManager::MODULE_INPUT_PORT); + + /* WL address size is the largest among all the regions */ + size_t wl_addr_size = 0; + for (const ConfigRegionId& config_region : + module_manager.regions(module_id)) { + wl_addr_size = std::max( + wl_addr_size, + find_memory_decoder_addr_size(num_config_bits[config_region].first)); + } + BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), + wl_addr_size); + module_manager.add_port(module_id, wl_addr_port, + ModuleManager::MODULE_INPUT_PORT); + + /* Data input should be dependent on the number of configuration regions*/ + BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), + config_protocol.num_regions()); + module_manager.add_port(module_id, din_port, + ModuleManager::MODULE_INPUT_PORT); + + break; } + case CONFIG_MEM_QL_MEMORY_BANK: { + add_top_module_ql_memory_bank_sram_ports(module_manager, module_id, + circuit_lib, config_protocol, + blwl_sr_banks, num_config_bits); + break; + } + case CONFIG_MEM_SCAN_CHAIN: { + /* Note that configuration chain tail is an output while head is an input + * IMPORTANT: this is co-designed with function generate_sram_port_names() + * If the return vector is changed, the following codes MUST be adapted! + */ + VTR_ASSERT(2 == sram_port_names.size()); + size_t port_counter = 0; + for (const std::string& sram_port_name : sram_port_names) { + /* Add generated ports to the ModuleManager */ + BasicPort sram_port(sram_port_name, sram_port_size); + if (0 == port_counter) { + module_manager.add_port(module_id, sram_port, + ModuleManager::MODULE_INPUT_PORT); + } else { + VTR_ASSERT(1 == port_counter); + module_manager.add_port(module_id, sram_port, + ModuleManager::MODULE_OUTPUT_PORT); + } + port_counter++; + } + break; + } + case CONFIG_MEM_FRAME_BASED: { + BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); + module_manager.add_port(module_id, en_port, + ModuleManager::MODULE_INPUT_PORT); - BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), max_num_config_bits); - module_manager.add_port(module_id, addr_port, ModuleManager::MODULE_INPUT_PORT); + size_t max_num_config_bits = 0; + for (const auto& curr_num_config_bits : num_config_bits) { + max_num_config_bits = + std::max(max_num_config_bits, curr_num_config_bits.first); + } - BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), sram_port_size); - module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), + max_num_config_bits); + module_manager.add_port(module_id, addr_port, + ModuleManager::MODULE_INPUT_PORT); - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization !\n"); - exit(1); + BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), + sram_port_size); + module_manager.add_port(module_id, din_port, + ModuleManager::MODULE_INPUT_PORT); + + break; + } + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization !\n"); + exit(1); } } @@ -906,11 +965,12 @@ void add_top_module_sram_ports(ModuleManager& module_manager, * - Find the number of BLs and WLs required for each region * - Create BL and WL decoders, and add them to decoder library * - Create nets to connect from top-level module inputs to inputs of decoders - * - Create nets to connect from outputs of decoders to BL/WL of configurable children + * - Create nets to connect from outputs of decoders to BL/WL of configurable + *children * * Detailed schematic of how memory banks are connected in the top-level: - * Consider a random Region X, local BL address lines are aligned to the LSB of the - * top-level BL address lines + * Consider a random Region X, local BL address lines are aligned to the LSB of + *the top-level BL address lines * * top_bl_addr[N-1:0] * ^ @@ -923,12 +983,12 @@ void add_top_module_sram_ports(ModuleManager& module_manager, * | +-------------------+ | * | | * - * The BL/WL decoders should have the same circuit designs no matter what region - * they are placed even when the number of configuration bits are different + * The BL/WL decoders should have the same circuit designs no matter what region + * they are placed even when the number of configuration bits are different * from one region to another! * This is designed to avoid any address collision between memory banks * since they are programmed in the same clock cycle - * For example: + * For example: * - Memory Bank A has 36 memory cells. * Its BL decoder has 3 address bit and 6 data output bit * Its WL decoder has 3 address bit and 6 data output bit @@ -943,43 +1003,36 @@ void add_top_module_sram_ports(ModuleManager& module_manager, * the BL address will be 3'b010 * the WL address will be 3'b010 * the data input will be 1'b1 - * However, in both cases, this will trigger a parasitic programming in bank B - * the BL address will be 2'b10 - * the WL address will be 2'b10 - * Assume the data input is expected to be 1'b1 for bank B - * but it will be overwritten to 1'b0 when programming the 36th cell in bank A! + * However, in both cases, this will trigger a parasitic programming in bank + *B the BL address will be 2'b10 the WL address will be 2'b10 Assume the data + *input is expected to be 1'b1 for bank B but it will be overwritten to 1'b0 + *when programming the 36th cell in bank A! * * Detailed schematic of each memory bank: * - * WL_enable WL address + * WL_enable WL address * | | * v v * +-----------------------------------------------+ * | Word Line Decoder | * +-----------------------------------------------+ - * +---------+ | | | + * +---------+ | | | * BL | | | | | - * enable ---->| |-----------+--------------+---- ... |------+--> BL[0] - * | | | | | | | | - * | | | v | v | v - * | Bit | | +------+ | +------+ | +------+ - * BL | Line | +-->| SRAM | +-->| SRAM | +->| SRAM | - * address ---->| Decoder | | | [0] | | | [1] | ... | | [i] | - * | | | +------+ | +------+ | +------+ - * | | | | | - * | |-----------+--------------+---- --- | -----+--> BL[1] - * | | | | | | | | - * | | | v | v | v - * | | | +------+ | +------+ | +------+ - * | | +-->| SRAM | | | SRAM | +->| SRAM | - * | | | | [x] | | | [x+1]| ... | | [x+i]| - * | | | +------+ | +------+ | +------+ - * | | | | - * | | | ... ... ... | ... - * | | | | | - * | |-----------+--------------+---- --- | -----+--> BL[y] - * | | | | | | | | - * | | | v | v | v + * enable ---->| |-----------+--------------+---- ... |------+--> + *BL[0] | | | | | | | | | | | + *v | v | v | Bit | | +------+ | +------+ + *| +------+ BL | Line | +-->| SRAM | +-->| SRAM | +->| + *SRAM | address ---->| Decoder | | | [0] | | | [1] | ... | | [i] + *| | | | +------+ | +------+ | +------+ | | | + *| | | |-----------+--------------+---- --- | + *-----+--> BL[1] | | | | | | | | | | + *| v | v | v | | | +------+ | + *+------+ | +------+ | | +-->| SRAM | | | SRAM | +->| + *SRAM | | | | | [x] | | | [x+1]| ... | | [x+i]| | | | + *+------+ | +------+ | +------+ | | | | | | | + *... ... ... | ... | | | | | | + *|-----------+--------------+---- --- | -----+--> BL[y] | | | | | + *| | | | | | v | v | v * | | | +------+ | +------+ | +------+ * | | +-->| SRAM | +-->| SRAM | +->| SRAM | * | | | | [y] | | |[y+1] | ... | |[y+i] | @@ -989,181 +1042,215 @@ void add_top_module_sram_ports(ModuleManager& module_manager, * +---------+ * **********************************************************************/ -static -void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const ModuleId& top_module, - const TopModuleNumConfigBits& num_config_bits) { - /* Find Enable port from the top-level module */ - ModulePortId en_port = module_manager.find_module_port(top_module, std::string(DECODER_ENABLE_PORT_NAME)); +static void add_top_module_nets_cmos_memory_bank_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const ModuleId& top_module, const TopModuleNumConfigBits& num_config_bits) { + /* Find Enable port from the top-level module */ + ModulePortId en_port = module_manager.find_module_port( + top_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort en_port_info = module_manager.module_port(top_module, en_port); - /* Find data-in port from the top-level module */ - ModulePortId din_port = module_manager.find_module_port(top_module, std::string(DECODER_DATA_IN_PORT_NAME)); + /* Find data-in port from the top-level module */ + ModulePortId din_port = module_manager.find_module_port( + top_module, std::string(DECODER_DATA_IN_PORT_NAME)); BasicPort din_port_info = module_manager.module_port(top_module, din_port); /* Data in port should match the number of configuration regions */ - VTR_ASSERT(din_port_info.get_width() == module_manager.regions(top_module).size()); + VTR_ASSERT(din_port_info.get_width() == + module_manager.regions(top_module).size()); - /* Find BL and WL address port from the top-level module */ - ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); - BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port); + /* Find BL and WL address port from the top-level module */ + ModulePortId bl_addr_port = module_manager.find_module_port( + top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); + BasicPort bl_addr_port_info = + module_manager.module_port(top_module, bl_addr_port); - ModulePortId wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); - BasicPort wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port); + ModulePortId wl_addr_port = module_manager.find_module_port( + top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); + BasicPort wl_addr_port_info = + module_manager.module_port(top_module, wl_addr_port); - /* Find the top-level number of BLs and WLs required to access each memory bit */ + /* Find the top-level number of BLs and WLs required to access each memory bit + */ size_t bl_addr_size = bl_addr_port_info.get_width(); size_t wl_addr_size = wl_addr_port_info.get_width(); /* Each memory bank has a unified number of BL/WLs */ size_t num_bls = 0; for (const auto& curr_config_bits : num_config_bits) { - num_bls = std::max(num_bls, find_memory_decoder_data_size(curr_config_bits.first)); + num_bls = + std::max(num_bls, find_memory_decoder_data_size(curr_config_bits.first)); } size_t num_wls = 0; for (const auto& curr_config_bits : num_config_bits) { - num_wls = std::max(num_wls, find_memory_decoder_data_size(curr_config_bits.first)); + num_wls = + std::max(num_wls, find_memory_decoder_data_size(curr_config_bits.first)); } - /* Create separated memory bank circuitry, i.e., BL/WL decoders for each region */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - /************************************************************** - * Add the BL decoder module + /* Create separated memory bank circuitry, i.e., BL/WL decoders for each + * region */ + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + /************************************************************** + * Add the BL decoder module * Search the decoder library * If we find one, we use the module. * Otherwise, we create one and add it to the decoder library */ - DecoderId bl_decoder_id = decoder_lib.find_decoder(bl_addr_size, num_bls, - true, true, false, false); + DecoderId bl_decoder_id = + decoder_lib.find_decoder(bl_addr_size, num_bls, true, true, false, false); if (DecoderId::INVALID() == bl_decoder_id) { - bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false, false); + bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, + false, false); } VTR_ASSERT(DecoderId::INVALID() != bl_decoder_id); /* Create a module if not existed yet */ - std::string bl_decoder_module_name = generate_memory_decoder_with_data_in_subckt_name(bl_addr_size, num_bls); - ModuleId bl_decoder_module = module_manager.find_module(bl_decoder_module_name); + std::string bl_decoder_module_name = + generate_memory_decoder_with_data_in_subckt_name(bl_addr_size, num_bls); + ModuleId bl_decoder_module = + module_manager.find_module(bl_decoder_module_name); if (ModuleId::INVALID() == bl_decoder_module) { /* BL decoder has the same ports as the frame-based decoders * We reuse it here */ - bl_decoder_module = build_bl_memory_decoder_module(module_manager, - decoder_lib, - bl_decoder_id); + bl_decoder_module = build_bl_memory_decoder_module( + module_manager, decoder_lib, bl_decoder_id); } VTR_ASSERT(ModuleId::INVALID() != bl_decoder_module); - size_t curr_bl_decoder_instance_id = module_manager.num_instance(top_module, bl_decoder_module); + size_t curr_bl_decoder_instance_id = + module_manager.num_instance(top_module, bl_decoder_module); module_manager.add_child_module(top_module, bl_decoder_module, false); - /************************************************************** - * Add the WL decoder module + /************************************************************** + * Add the WL decoder module * Search the decoder library * If we find one, we use the module. * Otherwise, we create one and add it to the decoder library */ - DecoderId wl_decoder_id = decoder_lib.find_decoder(wl_addr_size, num_wls, - true, false, false, false); + DecoderId wl_decoder_id = decoder_lib.find_decoder( + wl_addr_size, num_wls, true, false, false, false); if (DecoderId::INVALID() == wl_decoder_id) { - wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false, false); + wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, + false, false, false); } VTR_ASSERT(DecoderId::INVALID() != wl_decoder_id); /* Create a module if not existed yet */ - std::string wl_decoder_module_name = generate_memory_decoder_subckt_name(wl_addr_size, num_wls); - ModuleId wl_decoder_module = module_manager.find_module(wl_decoder_module_name); + std::string wl_decoder_module_name = + generate_memory_decoder_subckt_name(wl_addr_size, num_wls); + ModuleId wl_decoder_module = + module_manager.find_module(wl_decoder_module_name); if (ModuleId::INVALID() == wl_decoder_module) { /* BL decoder has the same ports as the frame-based decoders * We reuse it here */ - wl_decoder_module = build_wl_memory_decoder_module(module_manager, - decoder_lib, - wl_decoder_id); + wl_decoder_module = build_wl_memory_decoder_module( + module_manager, decoder_lib, wl_decoder_id); } VTR_ASSERT(ModuleId::INVALID() != wl_decoder_module); - size_t curr_wl_decoder_instance_id = module_manager.num_instance(top_module, wl_decoder_module); + size_t curr_wl_decoder_instance_id = + module_manager.num_instance(top_module, wl_decoder_module); module_manager.add_child_module(top_module, wl_decoder_module, false); - /************************************************************** + /************************************************************** * Add module nets from the top module to BL decoder's inputs */ - ModulePortId bl_decoder_en_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); - BasicPort bl_decoder_en_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_en_port); + ModulePortId bl_decoder_en_port = module_manager.find_module_port( + bl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); + BasicPort bl_decoder_en_port_info = + module_manager.module_port(bl_decoder_module, bl_decoder_en_port); - ModulePortId bl_decoder_addr_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort bl_decoder_addr_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_addr_port); + ModulePortId bl_decoder_addr_port = module_manager.find_module_port( + bl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort bl_decoder_addr_port_info = + module_manager.module_port(bl_decoder_module, bl_decoder_addr_port); - ModulePortId bl_decoder_din_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_IN_PORT_NAME)); - BasicPort bl_decoder_din_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_din_port); + ModulePortId bl_decoder_din_port = module_manager.find_module_port( + bl_decoder_module, std::string(DECODER_DATA_IN_PORT_NAME)); + BasicPort bl_decoder_din_port_info = + module_manager.module_port(bl_decoder_module, bl_decoder_din_port); /* Data in port of the local BL decoder should always be 1 */ VTR_ASSERT(1 == bl_decoder_din_port_info.get_width()); /* Top module Enable port -> BL Decoder Enable port */ - add_module_bus_nets(module_manager, - top_module, - top_module, 0, en_port, - bl_decoder_module, curr_bl_decoder_instance_id, bl_decoder_en_port); + add_module_bus_nets(module_manager, top_module, top_module, 0, en_port, + bl_decoder_module, curr_bl_decoder_instance_id, + bl_decoder_en_port); /* Top module Address port -> BL Decoder Address port */ - add_module_bus_nets(module_manager, - top_module, - top_module, 0, bl_addr_port, - bl_decoder_module, curr_bl_decoder_instance_id, bl_decoder_addr_port); + add_module_bus_nets(module_manager, top_module, top_module, 0, bl_addr_port, + bl_decoder_module, curr_bl_decoder_instance_id, + bl_decoder_addr_port); /* Top module data_in port -> BL Decoder data_in port: - * Note that each region has independent data_in connection from the top-level module - * The pin index is the configuration region index + * Note that each region has independent data_in connection from the + * top-level module The pin index is the configuration region index */ - ModuleNetId din_net = create_module_source_pin_net(module_manager, top_module, - top_module, 0, - din_port, - din_port_info.pins()[size_t(config_region)]); + ModuleNetId din_net = create_module_source_pin_net( + module_manager, top_module, top_module, 0, din_port, + din_port_info.pins()[size_t(config_region)]); VTR_ASSERT(ModuleNetId::INVALID() != din_net); /* Configure the net sink */ - module_manager.add_module_net_sink(top_module, din_net, bl_decoder_module, curr_bl_decoder_instance_id, bl_decoder_din_port, bl_decoder_din_port_info.pins()[0]); + module_manager.add_module_net_sink( + top_module, din_net, bl_decoder_module, curr_bl_decoder_instance_id, + bl_decoder_din_port, bl_decoder_din_port_info.pins()[0]); - /************************************************************** - * Add module nets from the top module to WL decoder's inputs + /************************************************************** + * Add module nets from the top module to WL decoder's inputs */ - ModulePortId wl_decoder_en_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); - BasicPort wl_decoder_en_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_en_port); + ModulePortId wl_decoder_en_port = module_manager.find_module_port( + wl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); + BasicPort wl_decoder_en_port_info = + module_manager.module_port(wl_decoder_module, wl_decoder_en_port); - ModulePortId wl_decoder_addr_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort wl_decoder_addr_port_info = module_manager.module_port(wl_decoder_module, bl_decoder_addr_port); + ModulePortId wl_decoder_addr_port = module_manager.find_module_port( + wl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort wl_decoder_addr_port_info = + module_manager.module_port(wl_decoder_module, bl_decoder_addr_port); /* Top module Enable port -> WL Decoder Enable port */ - add_module_bus_nets(module_manager, - top_module, - top_module, 0, en_port, - wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_en_port); + add_module_bus_nets(module_manager, top_module, top_module, 0, en_port, + wl_decoder_module, curr_wl_decoder_instance_id, + wl_decoder_en_port); /* Top module Address port -> WL Decoder Address port */ - add_module_bus_nets(module_manager, - top_module, - top_module, 0, wl_addr_port, - wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_addr_port); + add_module_bus_nets(module_manager, top_module, top_module, 0, wl_addr_port, + wl_decoder_module, curr_wl_decoder_instance_id, + wl_decoder_addr_port); - /************************************************************** + /************************************************************** * Add nets from BL data out to each configurable child */ size_t cur_bl_index = 0; - ModulePortId bl_decoder_dout_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); - BasicPort bl_decoder_dout_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_dout_port); + ModulePortId bl_decoder_dout_port = module_manager.find_module_port( + bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort bl_decoder_dout_port_info = + module_manager.module_port(bl_decoder_module, bl_decoder_dout_port); - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + for (size_t child_id = 0; + child_id < + module_manager.region_configurable_children(top_module, config_region) + .size(); + ++child_id) { + ModuleId child_module = module_manager.region_configurable_children( + top_module, config_region)[child_id]; + size_t child_instance = + module_manager.region_configurable_child_instances( + top_module, config_region)[child_id]; /* Find the BL port */ - ModulePortId child_bl_port = module_manager.find_module_port(child_module, std::string(MEMORY_BL_PORT_NAME)); - BasicPort child_bl_port_info = module_manager.module_port(child_module, child_bl_port); + ModulePortId child_bl_port = module_manager.find_module_port( + child_module, std::string(MEMORY_BL_PORT_NAME)); + BasicPort child_bl_port_info = + module_manager.module_port(child_module, child_bl_port); for (const size_t& sink_bl_pin : child_bl_port_info.pins()) { - /* Find the BL decoder data index: + /* Find the BL decoder data index: * It should be the residual when divided by the number of BLs */ size_t bl_pin_id = std::floor(cur_bl_index / num_bls); @@ -1171,94 +1258,106 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag VTR_ASSERT(bl_pin_id < bl_decoder_dout_port_info.pins().size()); /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - bl_decoder_module, curr_bl_decoder_instance_id, - bl_decoder_dout_port, - bl_decoder_dout_port_info.pins()[bl_pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, bl_decoder_module, + curr_bl_decoder_instance_id, bl_decoder_dout_port, + bl_decoder_dout_port_info.pins()[bl_pin_id]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_bl_port, sink_bl_pin); + module_manager.add_module_net_sink(top_module, net, child_module, + child_instance, child_bl_port, + sink_bl_pin); /* Increment the BL index */ cur_bl_index++; } } - /************************************************************** + /************************************************************** * Add nets from WL data out to each configurable child */ size_t cur_wl_index = 0; - ModulePortId wl_decoder_dout_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); - BasicPort wl_decoder_dout_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_dout_port); + ModulePortId wl_decoder_dout_port = module_manager.find_module_port( + wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort wl_decoder_dout_port_info = + module_manager.module_port(wl_decoder_module, wl_decoder_dout_port); - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + for (size_t child_id = 0; + child_id < + module_manager.region_configurable_children(top_module, config_region) + .size(); + ++child_id) { + ModuleId child_module = module_manager.region_configurable_children( + top_module, config_region)[child_id]; + size_t child_instance = + module_manager.region_configurable_child_instances( + top_module, config_region)[child_id]; /* Find the WL port */ - ModulePortId child_wl_port = module_manager.find_module_port(child_module, std::string(MEMORY_WL_PORT_NAME)); - BasicPort child_wl_port_info = module_manager.module_port(child_module, child_wl_port); + ModulePortId child_wl_port = module_manager.find_module_port( + child_module, std::string(MEMORY_WL_PORT_NAME)); + BasicPort child_wl_port_info = + module_manager.module_port(child_module, child_wl_port); for (const size_t& sink_wl_pin : child_wl_port_info.pins()) { - /* Find the BL decoder data index: + /* Find the BL decoder data index: * It should be the residual when divided by the number of BLs */ size_t wl_pin_id = cur_wl_index % num_wls; /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - wl_decoder_module, curr_wl_decoder_instance_id, - wl_decoder_dout_port, - wl_decoder_dout_port_info.pins()[wl_pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, wl_decoder_module, + curr_wl_decoder_instance_id, wl_decoder_dout_port, + wl_decoder_dout_port_info.pins()[wl_pin_id]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_wl_port, sink_wl_pin); + module_manager.add_module_net_sink(top_module, net, child_module, + child_instance, child_wl_port, + sink_wl_pin); /* Increment the WL index */ cur_wl_index++; } } - /************************************************************** + /************************************************************** * Add the BL and WL decoders to the end of configurable children list - * Note: this MUST be done after adding all the module nets to other regular configurable children + * Note: this MUST be done after adding all the module nets to other regular + * configurable children */ - module_manager.add_configurable_child(top_module, bl_decoder_module, curr_bl_decoder_instance_id); - module_manager.add_configurable_child_to_region(top_module, - config_region, - bl_decoder_module, - curr_bl_decoder_instance_id, - module_manager.configurable_children(top_module).size() - 1); + module_manager.add_configurable_child(top_module, bl_decoder_module, + curr_bl_decoder_instance_id); + module_manager.add_configurable_child_to_region( + top_module, config_region, bl_decoder_module, curr_bl_decoder_instance_id, + module_manager.configurable_children(top_module).size() - 1); - module_manager.add_configurable_child(top_module, wl_decoder_module, curr_wl_decoder_instance_id); - module_manager.add_configurable_child_to_region(top_module, - config_region, - wl_decoder_module, - curr_wl_decoder_instance_id, - module_manager.configurable_children(top_module).size() - 1); + module_manager.add_configurable_child(top_module, wl_decoder_module, + curr_wl_decoder_instance_id); + module_manager.add_configurable_child_to_region( + top_module, config_region, wl_decoder_module, curr_wl_decoder_instance_id, + module_manager.configurable_children(top_module).size() - 1); } } /******************************************************************** * Connect all the memory modules under the parent module in a chain - * - * Region 0: + * + * Region 0: * +--------+ +--------+ +--------+ - * ccff_head[0] --->| Memory |--->| Memory |--->... --->| Memory |----> ccff_tail[0] - * | Module | | Module | | Module | - * | [0] | | [1] | | [N-1] | + * ccff_head[0] --->| Memory |--->| Memory |--->... --->| Memory |----> + *ccff_tail[0] | Module | | Module | | Module | | [0] | | + *[1] | | [N-1] | * +--------+ +--------+ +--------+ * - * Region 1: + * Region 1: * +--------+ +--------+ +--------+ - * ccff_head[1] --->| Memory |--->| Memory |--->... --->| Memory |----> ccff_tail[1] - * | Module | | Module | | Module | - * | [0] | | [1] | | [N-1] | + * ccff_head[1] --->| Memory |--->| Memory |--->... --->| Memory |----> + *ccff_tail[1] | Module | | Module | | Module | | [0] | | + *[1] | | [N-1] | * +--------+ +--------+ +--------+ * * For the 1st memory module: @@ -1269,12 +1368,16 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag * net source is the configuration chain tail of the previous memory module * net sink is the configuration chain head of the next memory module *********************************************************************/ -static -void add_top_module_nets_cmos_memory_chain_config_bus(ModuleManager& module_manager, - const ModuleId& parent_module, - const ConfigProtocol& config_protocol) { - for (const ConfigRegionId& config_region : module_manager.regions(parent_module)) { - for (size_t mem_index = 0; mem_index < module_manager.region_configurable_children(parent_module, config_region).size(); ++mem_index) { +static void add_top_module_nets_cmos_memory_chain_config_bus( + ModuleManager& module_manager, const ModuleId& parent_module, + const ConfigProtocol& config_protocol) { + for (const ConfigRegionId& config_region : + module_manager.regions(parent_module)) { + for (size_t mem_index = 0; mem_index < module_manager + .region_configurable_children( + parent_module, config_region) + .size(); + ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; ModulePortId net_src_port_id; @@ -1287,78 +1390,112 @@ void add_top_module_nets_cmos_memory_chain_config_bus(ModuleManager& module_mana if (0 == mem_index) { /* Find the port name of configuration chain head */ - std::string src_port_name = generate_sram_port_name(config_protocol.type(), CIRCUIT_MODEL_PORT_INPUT); - net_src_module_id = parent_module; + std::string src_port_name = generate_sram_port_name( + config_protocol.type(), CIRCUIT_MODEL_PORT_INPUT); + net_src_module_id = parent_module; net_src_instance_id = 0; - net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); net_src_pin_id = size_t(config_region); /* Find the port name of next memory module */ std::string sink_port_name = generate_configuration_chain_head_name(); - net_sink_module_id = module_manager.region_configurable_children(parent_module, config_region)[mem_index]; - net_sink_instance_id = module_manager.region_configurable_child_instances(parent_module, config_region)[mem_index]; - net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + net_sink_module_id = module_manager.region_configurable_children( + parent_module, config_region)[mem_index]; + net_sink_instance_id = + module_manager.region_configurable_child_instances( + parent_module, config_region)[mem_index]; + net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); net_sink_pin_id = 0; } else { /* Find the port name of previous memory module */ std::string src_port_name = generate_configuration_chain_tail_name(); - net_src_module_id = module_manager.region_configurable_children(parent_module, config_region)[mem_index - 1]; - net_src_instance_id = module_manager.region_configurable_child_instances(parent_module, config_region)[mem_index - 1]; - net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + net_src_module_id = module_manager.region_configurable_children( + parent_module, config_region)[mem_index - 1]; + net_src_instance_id = + module_manager.region_configurable_child_instances( + parent_module, config_region)[mem_index - 1]; + net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); net_src_pin_id = 0; /* Find the port name of next memory module */ std::string sink_port_name = generate_configuration_chain_head_name(); - net_sink_module_id = module_manager.region_configurable_children(parent_module, config_region)[mem_index]; - net_sink_instance_id = module_manager.region_configurable_child_instances(parent_module, config_region)[mem_index]; - net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + net_sink_module_id = module_manager.region_configurable_children( + parent_module, config_region)[mem_index]; + net_sink_instance_id = + module_manager.region_configurable_child_instances( + parent_module, config_region)[mem_index]; + net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); net_sink_pin_id = 0; } /* Get the pin id for source port */ - BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); /* Get the pin id for sink port */ - BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); VTR_ASSERT(net_src_pin_id < net_src_port.get_width()); VTR_ASSERT(net_sink_pin_id < net_sink_port.get_width()); /* Create a net and add source and sink to it */ - ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[net_src_pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, parent_module, net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[net_src_pin_id]); /* Add net sink */ - module_manager.add_module_net_sink(parent_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(parent_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[net_sink_pin_id]); } /* For the last memory module: - * net source is the configuration chain tail of the previous memory module - * net sink is the configuration chain tail of the primitive module + * net source is the configuration chain tail of the previous memory + * module net sink is the configuration chain tail of the primitive module */ /* Find the port name of previous memory module */ std::string src_port_name = generate_configuration_chain_tail_name(); - ModuleId net_src_module_id = module_manager.region_configurable_children(parent_module, config_region).back(); - size_t net_src_instance_id = module_manager.region_configurable_child_instances(parent_module, config_region).back(); - ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + ModuleId net_src_module_id = + module_manager.region_configurable_children(parent_module, config_region) + .back(); + size_t net_src_instance_id = + module_manager + .region_configurable_child_instances(parent_module, config_region) + .back(); + ModulePortId net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); size_t net_src_pin_id = 0; /* Find the port name of next memory module */ - std::string sink_port_name = generate_sram_port_name(config_protocol.type(), CIRCUIT_MODEL_PORT_OUTPUT); - ModuleId net_sink_module_id = parent_module; + std::string sink_port_name = generate_sram_port_name( + config_protocol.type(), CIRCUIT_MODEL_PORT_OUTPUT); + ModuleId net_sink_module_id = parent_module; size_t net_sink_instance_id = 0; - ModulePortId net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + ModulePortId net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); size_t net_sink_pin_id = size_t(config_region); /* Get the pin id for source port */ - BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); /* Get the pin id for sink port */ - BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); VTR_ASSERT(net_src_pin_id < net_src_port.get_width()); VTR_ASSERT(net_sink_pin_id < net_sink_port.get_width()); - + /* Create a net and add source and sink to it */ - ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[net_src_pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, parent_module, net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[net_src_pin_id]); /* Add net sink */ - module_manager.add_module_net_sink(parent_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(parent_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[net_sink_pin_id]); } } @@ -1367,7 +1504,7 @@ void add_top_module_nets_cmos_memory_chain_config_bus(ModuleManager& module_mana * - Connect the enable signal to the EN of memory module * - Connect the address port to the address port of memory module * - Connect the data_in (Din) to the data_in of the memory module - * Note that the top-level module may have multiple regions and + * Note that the top-level module may have multiple regions and * therefore the Din port have multiple pins. The Din of local decoder * should be connected the Din pin indexed by current configuration region * @@ -1376,7 +1513,7 @@ void add_top_module_nets_cmos_memory_chain_config_bus(ModuleManager& module_mana * | | | Top module * +----+-----+------------+------------------ * | | | | - * | v v v + * | v v v * | +-------------------------------+ * | | EN ADDR[X-1:0] DATA_IN[N-1:0] | * | | | @@ -1386,74 +1523,87 @@ void add_top_module_nets_cmos_memory_chain_config_bus(ModuleManager& module_mana * * Note: * - This function is ONLY applicable to single configurable child case!!! - * - This function is applicable to the configurable child in a specific region!!! + * - This function is applicable to the configurable child in a specific + *region!!! *********************************************************************/ -static -void add_top_module_nets_cmos_memory_frame_short_config_bus(ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigRegionId& config_region) { - std::vector configurable_children = module_manager.region_configurable_children(top_module, config_region); +static void add_top_module_nets_cmos_memory_frame_short_config_bus( + ModuleManager& module_manager, const ModuleId& top_module, + const ConfigRegionId& config_region) { + std::vector configurable_children = + module_manager.region_configurable_children(top_module, config_region); VTR_ASSERT(1 == configurable_children.size()); - ModuleId child_module = configurable_children[0]; - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[0]; + ModuleId child_module = configurable_children[0]; + size_t child_instance = module_manager.region_configurable_child_instances( + top_module, config_region)[0]; /* Connect the enable (EN) port of the parent module * to the EN port of memory module */ - ModulePortId parent_en_port = module_manager.find_module_port(top_module, std::string(DECODER_ENABLE_PORT_NAME)); - ModulePortId child_en_port = module_manager.find_module_port(child_module, std::string(DECODER_ENABLE_PORT_NAME)); - add_module_bus_nets(module_manager, top_module, - top_module, 0, parent_en_port, + ModulePortId parent_en_port = module_manager.find_module_port( + top_module, std::string(DECODER_ENABLE_PORT_NAME)); + ModulePortId child_en_port = module_manager.find_module_port( + child_module, std::string(DECODER_ENABLE_PORT_NAME)); + add_module_bus_nets(module_manager, top_module, top_module, 0, parent_en_port, child_module, child_instance, child_en_port); - /* Connect the address port of the parent module to the child module address port */ - ModulePortId parent_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_ADDRESS_PORT_NAME)); - ModulePortId child_addr_port = module_manager.find_module_port(child_module, std::string(DECODER_ADDRESS_PORT_NAME)); - add_module_bus_nets(module_manager, top_module, - top_module, 0, parent_addr_port, - child_module, child_instance, child_addr_port); + /* Connect the address port of the parent module to the child module address + * port */ + ModulePortId parent_addr_port = module_manager.find_module_port( + top_module, std::string(DECODER_ADDRESS_PORT_NAME)); + ModulePortId child_addr_port = module_manager.find_module_port( + child_module, std::string(DECODER_ADDRESS_PORT_NAME)); + add_module_bus_nets(module_manager, top_module, top_module, 0, + parent_addr_port, child_module, child_instance, + child_addr_port); - /* Connect the data_in (Din) of parent module to the data_in of the memory module + /* Connect the data_in (Din) of parent module to the data_in of the memory + * module */ - ModulePortId parent_din_port = module_manager.find_module_port(top_module, std::string(DECODER_DATA_IN_PORT_NAME)); - BasicPort parent_din_port_info = module_manager.module_port(top_module, parent_din_port); - ModulePortId child_din_port = module_manager.find_module_port(child_module, std::string(DECODER_DATA_IN_PORT_NAME)); - BasicPort child_din_port_info = module_manager.module_port(child_module, child_din_port); + ModulePortId parent_din_port = module_manager.find_module_port( + top_module, std::string(DECODER_DATA_IN_PORT_NAME)); + BasicPort parent_din_port_info = + module_manager.module_port(top_module, parent_din_port); + ModulePortId child_din_port = module_manager.find_module_port( + child_module, std::string(DECODER_DATA_IN_PORT_NAME)); + BasicPort child_din_port_info = + module_manager.module_port(child_module, child_din_port); /* Ensure pin indices are in range! */ VTR_ASSERT(size_t(config_region) < parent_din_port_info.get_width()); VTR_ASSERT(1 == child_din_port_info.get_width()); /* Create a net for the Din[config_region] pin */ - ModuleNetId din_net = create_module_source_pin_net(module_manager, top_module, - top_module, 0, - parent_din_port, - parent_din_port_info.pins()[size_t(config_region)]); + ModuleNetId din_net = create_module_source_pin_net( + module_manager, top_module, top_module, 0, parent_din_port, + parent_din_port_info.pins()[size_t(config_region)]); VTR_ASSERT(ModuleNetId::INVALID() != din_net); /* Configure the net sink */ - module_manager.add_module_net_sink(top_module, din_net, child_module, child_instance, child_din_port, child_din_port_info.pins()[0]); + module_manager.add_module_net_sink(top_module, din_net, child_module, + child_instance, child_din_port, + child_din_port_info.pins()[0]); } /******************************************************************** - * This function will - * - Add a frame decoder to the parent module + * This function will + * - Add a frame decoder to the parent module * - If the decoder exists in the library, we use the module * - If the decoder does not exist, we create a new module and use it * - Create nets for the following types of connections: - * - Connect the EN signal, first few bits of address of parent module + * - Connect the EN signal, first few bits of address of parent module * to the frame decoder inputs * Note that the top-level module may have more address bits than * what is required for this configuration region. - * A decoder will be created anyway to avoid address collision + * A decoder will be created anyway to avoid address collision * to other configuration regions - * The address lines will be aligned from the MSB of top-level address lines!!! + * The address lines will be aligned from the MSB of top-level address + *lines!!! * - Connect the enable (EN) port of memory modules under the parent module * to the frame decoder outputs * - Connect the data_in (Din) of parent module to the data_in of the all * the memory modules - * Note that the top-level module may have multiple regions and + * Note that the top-level module may have multiple regions and * therefore the Din port have multiple pins. The Din of local decoder * should be connected the Din pin indexed by current configuration region * @@ -1461,11 +1611,11 @@ void add_top_module_nets_cmos_memory_frame_short_config_bus(ModuleManager& modul * | | | * | | | Top module * +--------+-------+------------+------------------ - * | | | - * | v v + * | | | + * | v v * | EN ADDR[X - 1: X - log(N)/log2] * | | | - * | v v + * | v v * | +--------------------------------------------+ * | | Frame-based decoder | * | | | @@ -1473,15 +1623,15 @@ void add_top_module_nets_cmos_memory_frame_short_config_bus(ModuleManager& modul * | +--------------------------------------------+ * | | * | +-------------+--------------------+ - * | | | | - * | Din | Din | Din | + * | | | | + * | Din | Din | Din | * | [Y] | [Y] | [Y] | * | | | | | | | * | v v v v v v * | +--------+ +--------+ +--------+ * | | Memory | | Memory | ... | Memory | * | | Module | | Module | | Module | - * | | [0] | | [1] | | [N-1] | + * | | [0] | | [1] | | [N-1] | * | +--------+ +--------+ +--------+ * | ^ ^ ^ * | | | | @@ -1491,96 +1641,110 @@ void add_top_module_nets_cmos_memory_frame_short_config_bus(ModuleManager& modul * * Note: * - X is the port size of address port of the parent module - * - the address port of child memory modules may be smaller than + * - the address port of child memory modules may be smaller than * X - log(N)/log2. In such case, we will drop the MSBs until it fit *********************************************************************/ -static -void add_top_module_nets_cmos_memory_frame_decoder_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const ModuleId& parent_module, - const ConfigRegionId& config_region) { - std::vector configurable_children = module_manager.region_configurable_children(parent_module, config_region); - std::vector configurable_child_instances = module_manager.region_configurable_child_instances(parent_module, config_region); +static void add_top_module_nets_cmos_memory_frame_decoder_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const ModuleId& parent_module, const ConfigRegionId& config_region) { + std::vector configurable_children = + module_manager.region_configurable_children(parent_module, config_region); + std::vector configurable_child_instances = + module_manager.region_configurable_child_instances(parent_module, + config_region); - ModulePortId parent_addr_port = module_manager.find_module_port(parent_module, std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort parent_addr_port_info = module_manager.module_port(parent_module, parent_addr_port); + ModulePortId parent_addr_port = module_manager.find_module_port( + parent_module, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort parent_addr_port_info = + module_manager.module_port(parent_module, parent_addr_port); /* Find the decoder specification */ - size_t addr_size = find_mux_local_decoder_addr_size(configurable_children.size()); + size_t addr_size = + find_mux_local_decoder_addr_size(configurable_children.size()); /* Data input should match the WL (data_in) of a SRAM */ - size_t data_size = configurable_children.size(); + size_t data_size = configurable_children.size(); - /* Search the decoder library and try to find one - * If not found, create a new module and add it to the module manager + /* Search the decoder library and try to find one + * If not found, create a new module and add it to the module manager */ - DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, true, false, false, false); + DecoderId decoder_id = + decoder_lib.find_decoder(addr_size, data_size, true, false, false, false); if (DecoderId::INVALID() == decoder_id) { - decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, false, false, false); + decoder_id = + decoder_lib.add_decoder(addr_size, data_size, true, false, false, false); } VTR_ASSERT(DecoderId::INVALID() != decoder_id); /* Create a module if not existed yet */ - std::string decoder_module_name = generate_memory_decoder_subckt_name(addr_size, data_size); + std::string decoder_module_name = + generate_memory_decoder_subckt_name(addr_size, data_size); ModuleId decoder_module = module_manager.find_module(decoder_module_name); if (ModuleId::INVALID() == decoder_module) { decoder_module = build_frame_memory_decoder_module(module_manager, - decoder_lib, - decoder_id); + decoder_lib, decoder_id); } VTR_ASSERT(ModuleId::INVALID() != decoder_module); /* Instanciate the decoder module here */ - size_t decoder_instance = module_manager.num_instance(parent_module, decoder_module); + size_t decoder_instance = + module_manager.num_instance(parent_module, decoder_module); module_manager.add_child_module(parent_module, decoder_module, false); /* Connect the enable (EN) port of memory modules under the parent module * to the frame decoder inputs */ - ModulePortId parent_en_port = module_manager.find_module_port(parent_module, std::string(DECODER_ENABLE_PORT_NAME)); - ModulePortId decoder_en_port = module_manager.find_module_port(decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); - add_module_bus_nets(module_manager, parent_module, - parent_module, 0, parent_en_port, - decoder_module, decoder_instance, decoder_en_port); + ModulePortId parent_en_port = module_manager.find_module_port( + parent_module, std::string(DECODER_ENABLE_PORT_NAME)); + ModulePortId decoder_en_port = module_manager.find_module_port( + decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); + add_module_bus_nets(module_manager, parent_module, parent_module, 0, + parent_en_port, decoder_module, decoder_instance, + decoder_en_port); - /* Connect the address port of the parent module to the frame decoder address port - * Note that we only connect to the first few bits of address port + /* Connect the address port of the parent module to the frame decoder address + * port Note that we only connect to the first few bits of address port */ - ModulePortId decoder_addr_port = module_manager.find_module_port(decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort decoder_addr_port_info = module_manager.module_port(decoder_module, decoder_addr_port); + ModulePortId decoder_addr_port = module_manager.find_module_port( + decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort decoder_addr_port_info = + module_manager.module_port(decoder_module, decoder_addr_port); for (size_t ipin = 0; ipin < decoder_addr_port_info.get_width(); ++ipin) { /* Create a net for the addr pin */ - ModuleNetId addr_net = create_module_source_pin_net(module_manager, parent_module, - parent_module, 0, - parent_addr_port, - parent_addr_port_info.pins()[parent_addr_port_info.get_width() - 1 - ipin]); + ModuleNetId addr_net = create_module_source_pin_net( + module_manager, parent_module, parent_module, 0, parent_addr_port, + parent_addr_port_info + .pins()[parent_addr_port_info.get_width() - 1 - ipin]); VTR_ASSERT(ModuleNetId::INVALID() != addr_net); /* Configure the net sink */ - module_manager.add_module_net_sink(parent_module, addr_net, - decoder_module, decoder_instance, - decoder_addr_port, - decoder_addr_port_info.pins()[decoder_addr_port_info.get_width() - 1 - ipin]); - } + module_manager.add_module_net_sink( + parent_module, addr_net, decoder_module, decoder_instance, + decoder_addr_port, + decoder_addr_port_info + .pins()[decoder_addr_port_info.get_width() - 1 - ipin]); + } - /* Connect the address port of the parent module to the address port of configurable children - * Note that we only connect to the last few bits of address port + /* Connect the address port of the parent module to the address port of + * configurable children Note that we only connect to the last few bits of + * address port */ - for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { - ModuleId child_module = configurable_children[mem_index]; + for (size_t mem_index = 0; mem_index < configurable_children.size(); + ++mem_index) { + ModuleId child_module = configurable_children[mem_index]; size_t child_instance = configurable_child_instances[mem_index]; - ModulePortId child_addr_port = module_manager.find_module_port(child_module, std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort child_addr_port_info = module_manager.module_port(child_module, child_addr_port); + ModulePortId child_addr_port = module_manager.find_module_port( + child_module, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort child_addr_port_info = + module_manager.module_port(child_module, child_addr_port); for (size_t ipin = 0; ipin < child_addr_port_info.get_width(); ++ipin) { - ModuleNetId addr_net = create_module_source_pin_net(module_manager, parent_module, - parent_module, 0, - parent_addr_port, - parent_addr_port_info.pins()[ipin]); + ModuleNetId addr_net = create_module_source_pin_net( + module_manager, parent_module, parent_module, 0, parent_addr_port, + parent_addr_port_info.pins()[ipin]); VTR_ASSERT(ModuleNetId::INVALID() != addr_net); /* Configure the net sink */ - module_manager.add_module_net_sink(parent_module, addr_net, - child_module, child_instance, - child_addr_port, + module_manager.add_module_net_sink(parent_module, addr_net, child_module, + child_instance, child_addr_port, child_addr_port_info.pins()[ipin]); } } @@ -1588,118 +1752,139 @@ void add_top_module_nets_cmos_memory_frame_decoder_config_bus(ModuleManager& mod /* Connect the data_in (Din) of parent module to the data_in of the all * the memory modules */ - ModulePortId parent_din_port = module_manager.find_module_port(parent_module, std::string(DECODER_DATA_IN_PORT_NAME)); - BasicPort parent_din_port_info = module_manager.module_port(parent_module, parent_din_port); - for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { - ModuleId child_module = configurable_children[mem_index]; - size_t child_instance = module_manager.configurable_child_instances(parent_module)[mem_index]; - ModulePortId child_din_port = module_manager.find_module_port(child_module, std::string(DECODER_DATA_IN_PORT_NAME)); - BasicPort child_din_port_info = module_manager.module_port(child_module, child_din_port); + ModulePortId parent_din_port = module_manager.find_module_port( + parent_module, std::string(DECODER_DATA_IN_PORT_NAME)); + BasicPort parent_din_port_info = + module_manager.module_port(parent_module, parent_din_port); + for (size_t mem_index = 0; mem_index < configurable_children.size(); + ++mem_index) { + ModuleId child_module = configurable_children[mem_index]; + size_t child_instance = + module_manager.configurable_child_instances(parent_module)[mem_index]; + ModulePortId child_din_port = module_manager.find_module_port( + child_module, std::string(DECODER_DATA_IN_PORT_NAME)); + BasicPort child_din_port_info = + module_manager.module_port(child_module, child_din_port); /* Ensure pin indices are in range! */ VTR_ASSERT(size_t(config_region) < parent_din_port_info.get_width()); VTR_ASSERT(1 == child_din_port_info.get_width()); /* Create a net for the Din[config_region] pin */ - ModuleNetId din_net = create_module_source_pin_net(module_manager, parent_module, - parent_module, 0, - parent_din_port, - parent_din_port_info.pins()[size_t(config_region)]); + ModuleNetId din_net = create_module_source_pin_net( + module_manager, parent_module, parent_module, 0, parent_din_port, + parent_din_port_info.pins()[size_t(config_region)]); VTR_ASSERT(ModuleNetId::INVALID() != din_net); /* Configure the net sink */ - module_manager.add_module_net_sink(parent_module, din_net, child_module, child_instance, child_din_port, child_din_port_info.pins()[0]); + module_manager.add_module_net_sink(parent_module, din_net, child_module, + child_instance, child_din_port, + child_din_port_info.pins()[0]); } - /* Connect the data_out port of the decoder module + /* Connect the data_out port of the decoder module * to the enable port of configurable children */ - ModulePortId decoder_dout_port = module_manager.find_module_port(decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); - BasicPort decoder_dout_port_info = module_manager.module_port(decoder_module, decoder_dout_port); - VTR_ASSERT(decoder_dout_port_info.get_width() == configurable_children.size()); - for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { - ModuleId child_module = configurable_children[mem_index]; - size_t child_instance = module_manager.configurable_child_instances(parent_module)[mem_index]; - ModulePortId child_en_port = module_manager.find_module_port(child_module, std::string(DECODER_ENABLE_PORT_NAME)); - BasicPort child_en_port_info = module_manager.module_port(child_module, child_en_port); + ModulePortId decoder_dout_port = module_manager.find_module_port( + decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort decoder_dout_port_info = + module_manager.module_port(decoder_module, decoder_dout_port); + VTR_ASSERT(decoder_dout_port_info.get_width() == + configurable_children.size()); + for (size_t mem_index = 0; mem_index < configurable_children.size(); + ++mem_index) { + ModuleId child_module = configurable_children[mem_index]; + size_t child_instance = + module_manager.configurable_child_instances(parent_module)[mem_index]; + ModulePortId child_en_port = module_manager.find_module_port( + child_module, std::string(DECODER_ENABLE_PORT_NAME)); + BasicPort child_en_port_info = + module_manager.module_port(child_module, child_en_port); for (size_t ipin = 0; ipin < child_en_port_info.get_width(); ++ipin) { - ModuleNetId en_net = create_module_source_pin_net(module_manager, parent_module, - decoder_module, decoder_instance, - decoder_dout_port, - decoder_dout_port_info.pins()[mem_index]); + ModuleNetId en_net = create_module_source_pin_net( + module_manager, parent_module, decoder_module, decoder_instance, + decoder_dout_port, decoder_dout_port_info.pins()[mem_index]); VTR_ASSERT(ModuleNetId::INVALID() != en_net); /* Configure the net sink */ - module_manager.add_module_net_sink(parent_module, en_net, - child_module, child_instance, - child_en_port, + module_manager.add_module_net_sink(parent_module, en_net, child_module, + child_instance, child_en_port, child_en_port_info.pins()[ipin]); } } /* Add the decoder as the last configurable children */ - module_manager.add_configurable_child(parent_module, decoder_module, decoder_instance); + module_manager.add_configurable_child(parent_module, decoder_module, + decoder_instance); /* Register the configurable child to configuration region */ - module_manager.add_configurable_child_to_region(parent_module, - config_region, - decoder_module, - decoder_instance, - module_manager.configurable_children(parent_module).size() - 1); + module_manager.add_configurable_child_to_region( + parent_module, config_region, decoder_module, decoder_instance, + module_manager.configurable_children(parent_module).size() - 1); } /********************************************************************* * Add framed-based decoders to the top-level module * and build net connections between decoders and subblocks - * + * * For each configuration region, we create an independent decoder * Note that to avoid parasitic programming, all the decoders will * be in the same size, sharing the same principle as memory banks * * For each region, decoder and net addition will depend on the following cases: * - If there is no configurable child, nothing to do. - * - If there is only one configurable child, short wire the EN, ADDR and DATA_IN to it - * - If there are more than two configurable childern, add a decoder and build interconnection - * between it and the children + * - If there is only one configurable child, short wire the EN, ADDR and + *DATA_IN to it + * - If there are more than two configurable childern, add a decoder and build + *interconnection between it and the children **********************************************************************/ -static -void add_top_module_nets_cmos_memory_frame_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const ModuleId& top_module, - const TopModuleNumConfigBits& num_config_bits) { +static void add_top_module_nets_cmos_memory_frame_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const ModuleId& top_module, const TopModuleNumConfigBits& num_config_bits) { /* Find the number of address bits for the top-level module */ - ModulePortId top_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort top_addr_port_info = module_manager.module_port(top_module, top_addr_port); + ModulePortId top_addr_port = module_manager.find_module_port( + top_module, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort top_addr_port_info = + module_manager.module_port(top_module, top_addr_port); size_t top_addr_size = top_addr_port_info.get_width(); - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - if (0 == module_manager.region_configurable_children(top_module, config_region).size()) { - continue; + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + if (0 == + module_manager.region_configurable_children(top_module, config_region) + .size()) { + continue; } - - /* Short-wiring is applicable only when all the following situations are met: + + /* Short-wiring is applicable only when all the following situations are + * met: * - There is only 1 configurable child in the region - * - The number of address bits of the configurable child is the same as top-level + * - The number of address bits of the configurable child is the same as + * top-level */ - if ( (1 == module_manager.region_configurable_children(top_module, config_region).size()) - && (num_config_bits[config_region].first == top_addr_size)) { - add_top_module_nets_cmos_memory_frame_short_config_bus(module_manager, top_module, config_region); + if ((1 == + module_manager.region_configurable_children(top_module, config_region) + .size()) && + (num_config_bits[config_region].first == top_addr_size)) { + add_top_module_nets_cmos_memory_frame_short_config_bus( + module_manager, top_module, config_region); } else { - add_top_module_nets_cmos_memory_frame_decoder_config_bus(module_manager, decoder_lib, top_module, config_region); + add_top_module_nets_cmos_memory_frame_decoder_config_bus( + module_manager, decoder_lib, top_module, config_region); } - } + } } /********************************************************************* - * Add the port-to-port connection between all the memory modules + * Add the port-to-port connection between all the memory modules * and their parent module * - * Create nets to wire the control signals of memory module to + * Create nets to wire the control signals of memory module to * the configuration ports of primitive module * - * Configuration Chain + * Configuration Chain * ------------------- * - * config_bus (head) config_bus (tail) + * config_bus (head) config_bus (tail) * | ^ * primitive | | * +---------------------------------------------+ @@ -1714,10 +1899,10 @@ void add_top_module_nets_cmos_memory_frame_config_bus(ModuleManager& module_mana * | | * +---------------------------------------------+ * - * Memory bank + * Memory bank * ----------- * - * config_bus (BL) config_bus (WL) + * config_bus (BL) config_bus (WL) * | | * primitive | | * +---------------------------------------------+ @@ -1733,49 +1918,51 @@ void add_top_module_nets_cmos_memory_frame_config_bus(ModuleManager& module_mana * +---------------------------------------------+ * **********************************************************************/ -static -void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - MemoryBankShiftRegisterBanks& blwl_sr_banks, - const ModuleId& parent_module, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const TopModuleNumConfigBits& num_config_bits) { +static void add_top_module_nets_cmos_memory_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const ModuleId& parent_module, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const TopModuleNumConfigBits& num_config_bits) { switch (config_protocol.type()) { - case CONFIG_MEM_STANDALONE: - add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, - config_protocol.type(), CIRCUIT_MODEL_PORT_BL); - add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, - config_protocol.type(), CIRCUIT_MODEL_PORT_WL); - break; - case CONFIG_MEM_SCAN_CHAIN: { - add_top_module_nets_cmos_memory_chain_config_bus(module_manager, parent_module, config_protocol); - break; - } - case CONFIG_MEM_MEMORY_BANK: - add_top_module_nets_cmos_memory_bank_config_bus(module_manager, decoder_lib, parent_module, num_config_bits); - break; - case CONFIG_MEM_QL_MEMORY_BANK: - add_top_module_nets_cmos_ql_memory_bank_config_bus(module_manager, decoder_lib, blwl_sr_banks, - parent_module, circuit_lib, config_protocol, num_config_bits); - break; - case CONFIG_MEM_FRAME_BASED: - add_top_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, parent_module, num_config_bits); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization!\n"); - exit(1); + case CONFIG_MEM_STANDALONE: + add_module_nets_cmos_flatten_memory_config_bus( + module_manager, parent_module, config_protocol.type(), + CIRCUIT_MODEL_PORT_BL); + add_module_nets_cmos_flatten_memory_config_bus( + module_manager, parent_module, config_protocol.type(), + CIRCUIT_MODEL_PORT_WL); + break; + case CONFIG_MEM_SCAN_CHAIN: { + add_top_module_nets_cmos_memory_chain_config_bus( + module_manager, parent_module, config_protocol); + break; + } + case CONFIG_MEM_MEMORY_BANK: + add_top_module_nets_cmos_memory_bank_config_bus( + module_manager, decoder_lib, parent_module, num_config_bits); + break; + case CONFIG_MEM_QL_MEMORY_BANK: + add_top_module_nets_cmos_ql_memory_bank_config_bus( + module_manager, decoder_lib, blwl_sr_banks, parent_module, circuit_lib, + config_protocol, num_config_bits); + break; + case CONFIG_MEM_FRAME_BASED: + add_top_module_nets_cmos_memory_frame_config_bus( + module_manager, decoder_lib, parent_module, num_config_bits); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization!\n"); + exit(1); } } - /******************************************************************** * TODO: - * Add the port-to-port connection between a memory module + * Add the port-to-port connection between a memory module * and the configuration bus of a primitive module * - * Create nets to wire the control signals of memory module to + * Create nets to wire the control signals of memory module to * the configuration ports of primitive module * * Primitive module @@ -1788,46 +1975,40 @@ void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, * | +--------+ | * +----------------------------+ * The detailed config ports really depend on the type - * of SRAM organization. + * of SRAM organization. * * The config_bus in the argument is the reserved address of configuration * bus in the parent_module for this memory module * - * The configuration bus connection will depend not only - * the design technology of the memory cells but also the + * The configuration bus connection will depend not only + * the design technology of the memory cells but also the * configuration styles of FPGA fabric. * Here we will branch on the design technology * * Note: this function SHOULD be called after the pb_type_module is created - * and its child module (logic_module and memory_module) is created! + * and its child module (logic_module and memory_module) is created! *******************************************************************/ -void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - MemoryBankShiftRegisterBanks& blwl_sr_banks, - const ModuleId& parent_module, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const e_circuit_model_design_tech& mem_tech, - const TopModuleNumConfigBits& num_config_bits) { - +void add_top_module_nets_memory_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const ModuleId& parent_module, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const e_circuit_model_design_tech& mem_tech, + const TopModuleNumConfigBits& num_config_bits) { vtr::ScopedStartFinishTimer timer("Add module nets for configuration buses"); switch (mem_tech) { - case CIRCUIT_MODEL_DESIGN_CMOS: - add_top_module_nets_cmos_memory_config_bus(module_manager, decoder_lib, - blwl_sr_banks, - parent_module, - circuit_lib, - config_protocol, - num_config_bits); - break; - case CIRCUIT_MODEL_DESIGN_RRAM: - /* TODO: */ - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of memory design technology!\n"); - exit(1); + case CIRCUIT_MODEL_DESIGN_CMOS: + add_top_module_nets_cmos_memory_config_bus( + module_manager, decoder_lib, blwl_sr_banks, parent_module, circuit_lib, + config_protocol, num_config_bits); + break; + case CIRCUIT_MODEL_DESIGN_RRAM: + /* TODO: */ + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of memory design technology!\n"); + exit(1); } } diff --git a/openfpga/src/fabric/build_top_module_memory.h b/openfpga/src/fabric/build_top_module_memory.h index 244f6bfee..0f4a17d6a 100644 --- a/openfpga/src/fabric/build_top_module_memory.h +++ b/openfpga/src/fabric/build_top_module_memory.h @@ -5,21 +5,21 @@ * Include header files that are required by function declaration *******************************************************************/ -#include #include -#include "vtr_vector.h" -#include "vtr_ndmatrix.h" -#include "module_manager.h" -#include "circuit_types.h" +#include + +#include "build_top_module_memory_utils.h" #include "circuit_library.h" +#include "circuit_types.h" #include "config_protocol.h" #include "decoder_library.h" #include "device_grid.h" #include "device_rr_gsb.h" #include "fabric_key.h" -#include "config_protocol.h" #include "memory_bank_shift_register_banks.h" -#include "build_top_module_memory_utils.h" +#include "module_manager.h" +#include "vtr_ndmatrix.h" +#include "vtr_vector.h" /******************************************************************** * Function declaration @@ -28,50 +28,42 @@ /* begin namespace openfpga */ namespace openfpga { -void organize_top_module_memory_modules(ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const CircuitModelId& sram_model, - const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, - const DeviceRRGSB& device_rr_gsb, - const vtr::Matrix& sb_instance_ids, - const std::map>& cb_instance_ids, - const bool& compact_routing_hierarchy); +void organize_top_module_memory_modules( + ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const CircuitModelId& sram_model, const DeviceGrid& grids, + const vtr::Matrix& grid_instance_ids, + const DeviceRRGSB& device_rr_gsb, const vtr::Matrix& sb_instance_ids, + const std::map>& cb_instance_ids, + const bool& compact_routing_hierarchy); -void shuffle_top_module_configurable_children(ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigProtocol& config_protocol); +void shuffle_top_module_configurable_children( + ModuleManager& module_manager, const ModuleId& top_module, + const ConfigProtocol& config_protocol); -int load_top_module_memory_modules_from_fabric_key(ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const FabricKey& fabric_key); +int load_top_module_memory_modules_from_fabric_key( + ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const FabricKey& fabric_key); -TopModuleNumConfigBits find_top_module_regional_num_config_bit(const ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& config_protocol_type); +TopModuleNumConfigBits find_top_module_regional_num_config_bit( + const ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type& config_protocol_type); -void add_top_module_sram_ports(ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const ConfigProtocol& config_protocol, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const TopModuleNumConfigBits& num_config_bits); +void add_top_module_sram_ports( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const ConfigProtocol& config_protocol, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const TopModuleNumConfigBits& num_config_bits); -void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - MemoryBankShiftRegisterBanks& blwl_sr_banks, - const ModuleId& parent_module, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const e_circuit_model_design_tech& mem_tech, - const TopModuleNumConfigBits& num_config_bits); +void add_top_module_nets_memory_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const ModuleId& parent_module, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const e_circuit_model_design_tech& mem_tech, + const TopModuleNumConfigBits& num_config_bits); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 881b9ce86..0e5823ae2 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * This file includes functions that are used to organize memories + * This file includes functions that are used to organize memories * in the top module of FPGA fabric *******************************************************************/ #include @@ -14,31 +14,29 @@ #include "vpr_utils.h" /* Headers from openfpgashell library */ -#include "command_exit_codes.h" - -#include "rr_gsb_utils.h" -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" - -#include "memory_utils.h" -#include "decoder_library_utils.h" -#include "module_manager_utils.h" -#include "memory_bank_utils.h" -#include "build_memory_modules.h" #include "build_decoder_modules.h" -#include "memory_bank_shift_register_banks.h" +#include "build_memory_modules.h" #include "build_top_module_memory_bank.h" +#include "command_exit_codes.h" +#include "decoder_library_utils.h" +#include "memory_bank_shift_register_banks.h" +#include "memory_bank_utils.h" +#include "memory_utils.h" +#include "module_manager_utils.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "rr_gsb_utils.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** * Connect all the memory modules under the parent module in a chain - * + * * +--------+ +--------+ +--------+ * ccff_head --->| Memory |--->| Memory |--->... --->| Memory |----> ccff_tail * | Module | | Module | | Module | - * | [0] | | [1] | | [N-1] | + * | [0] | | [1] | | [N-1] | * +--------+ +--------+ +--------+ * For the 1st memory module: * net source is the configuration chain head of the primitive module @@ -50,18 +48,18 @@ namespace openfpga { * * Note that: * This function is designed for memory modules ONLY! - * Do not use it to replace the + * Do not use it to replace the * add_module_nets_cmos_memory_chain_config_bus() !!! *********************************************************************/ -static -void add_module_nets_to_ql_memory_bank_shift_register_module(ModuleManager& module_manager, - const ModuleId& parent_module, - const CircuitLibrary& circuit_lib, - const CircuitPortId& model_input_port, - const CircuitPortId& model_output_port, - const std::string& chain_head_port_name, - const std::string& chain_tail_port_name) { - for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) { +static void add_module_nets_to_ql_memory_bank_shift_register_module( + ModuleManager& module_manager, const ModuleId& parent_module, + const CircuitLibrary& circuit_lib, const CircuitPortId& model_input_port, + const CircuitPortId& model_output_port, + const std::string& chain_head_port_name, + const std::string& chain_tail_port_name) { + for (size_t mem_index = 0; + mem_index < module_manager.configurable_children(parent_module).size(); + ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; ModulePortId net_src_port_id; @@ -73,42 +71,58 @@ void add_module_nets_to_ql_memory_bank_shift_register_module(ModuleManager& modu if (0 == mem_index) { /* Find the port name of configuration chain head */ std::string src_port_name = chain_head_port_name; - net_src_module_id = parent_module; + net_src_module_id = parent_module; net_src_instance_id = 0; - net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; - net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + net_sink_module_id = + module_manager.configurable_children(parent_module)[mem_index]; + net_sink_instance_id = + module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); } else { /* Find the port name of previous memory module */ std::string src_port_name = circuit_lib.port_prefix(model_output_port); - net_src_module_id = module_manager.configurable_children(parent_module)[mem_index - 1]; - net_src_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index - 1]; - net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + net_src_module_id = + module_manager.configurable_children(parent_module)[mem_index - 1]; + net_src_instance_id = module_manager.configurable_child_instances( + parent_module)[mem_index - 1]; + net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; - net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + net_sink_module_id = + module_manager.configurable_children(parent_module)[mem_index]; + net_sink_instance_id = + module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); } /* Get the pin id for source port */ - BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); /* Get the pin id for sink port */ - BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); /* Port sizes of source and sink should match */ VTR_ASSERT(net_src_port.get_width() == net_sink_port.get_width()); - + /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) { /* Create a net and add source and sink to it */ - ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, parent_module, net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[pin_id]); /* Add net sink */ - module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[pin_id]); } } @@ -118,35 +132,45 @@ void add_module_nets_to_ql_memory_bank_shift_register_module(ModuleManager& modu */ /* Find the port name of previous memory module */ std::string src_port_name = circuit_lib.port_prefix(model_output_port); - ModuleId net_src_module_id = module_manager.configurable_children(parent_module).back(); - size_t net_src_instance_id = module_manager.configurable_child_instances(parent_module).back(); - ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + ModuleId net_src_module_id = + module_manager.configurable_children(parent_module).back(); + size_t net_src_instance_id = + module_manager.configurable_child_instances(parent_module).back(); + ModulePortId net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = chain_tail_port_name; - ModuleId net_sink_module_id = parent_module; + ModuleId net_sink_module_id = parent_module; size_t net_sink_instance_id = 0; - ModulePortId net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + ModulePortId net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); /* Get the pin id for source port */ - BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); /* Get the pin id for sink port */ - BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); /* Port sizes of source and sink should match */ VTR_ASSERT(net_src_port.get_width() == net_sink_port.get_width()); - + /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) { /* Create a net and add source and sink to it */ - ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, parent_module, net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[pin_id]); /* Add net sink */ - module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[pin_id]); } } /********************************************************************* * BL shift register chain module organization - * + * * +-------+ +-------+ +-------+ * chain --->| CCFF |--->| CCFF |--->... --->| CCFF |---->chain * input&clock | [0] | | [1] | | [N-1] | output @@ -157,83 +181,93 @@ void add_module_nets_to_ql_memory_bank_shift_register_module(ModuleManager& modu * | BLs of configurable modules | * ********************************************************************/ -static -ModuleId build_bl_shift_register_chain_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const std::string& module_name, - const CircuitModelId& sram_model, - const size_t& num_mems) { - +static ModuleId build_bl_shift_register_chain_module( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const std::string& module_name, const CircuitModelId& sram_model, + const size_t& num_mems) { /* Get the input ports from the SRAM */ - std::vector sram_input_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector sram_input_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true); VTR_ASSERT(1 == sram_input_ports.size()); /* Get the output ports from the SRAM */ - std::vector sram_output_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector sram_output_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, + true); VTR_ASSERT(1 == sram_output_ports.size()); /* Get the BL ports from the SRAM */ - std::vector sram_bl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BL, true); + std::vector sram_bl_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BL, true); VTR_ASSERT(1 == sram_bl_ports.size()); /* Create a module and add to the module manager */ - ModuleId mem_module = module_manager.add_module(module_name); + ModuleId mem_module = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); /* Label module usage */ module_manager.set_module_usage(mem_module, ModuleManager::MODULE_CONFIG); - - /* Add an input port, which is the head of configuration chain in the module */ + + /* Add an input port, which is the head of configuration chain in the module + */ /* TODO: restriction!!! * consider only the first input of the CCFF model as the D port, * which will be connected to the head of the chain */ - BasicPort chain_head_port(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME, + BasicPort chain_head_port(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME, circuit_lib.port_size(sram_input_ports[0])); - module_manager.add_port(mem_module, chain_head_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(mem_module, chain_head_port, + ModuleManager::MODULE_INPUT_PORT); - /* Add an output port, which is the tail of configuration chain in the module */ + /* Add an output port, which is the tail of configuration chain in the module + */ /* TODO: restriction!!! * consider only the first output of the CCFF model as the Q port, * which will be connected to the tail of the chain */ - BasicPort chain_tail_port(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME, + BasicPort chain_tail_port(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME, circuit_lib.port_size(sram_output_ports[0])); - module_manager.add_port(mem_module, chain_tail_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(mem_module, chain_tail_port, + ModuleManager::MODULE_OUTPUT_PORT); /* Add the output ports to output BL signals */ - BasicPort chain_bl_port(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME, - num_mems); - module_manager.add_port(mem_module, chain_bl_port, ModuleManager::MODULE_OUTPUT_PORT); + BasicPort chain_bl_port(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME, num_mems); + module_manager.add_port(mem_module, chain_bl_port, + ModuleManager::MODULE_OUTPUT_PORT); /* Find the sram module in the module manager */ - ModuleId sram_mem_module = module_manager.find_module(circuit_lib.model_name(sram_model)); + ModuleId sram_mem_module = + module_manager.find_module(circuit_lib.model_name(sram_model)); /* Instanciate each submodule */ for (size_t i = 0; i < num_mems; ++i) { - size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module); + size_t sram_mem_instance = + module_manager.num_instance(mem_module, sram_mem_module); module_manager.add_child_module(mem_module, sram_mem_module); - module_manager.add_configurable_child(mem_module, sram_mem_module, sram_mem_instance); + module_manager.add_configurable_child(mem_module, sram_mem_module, + sram_mem_instance); - /* Build module nets to wire bl outputs of sram modules to BL outputs of memory module */ + /* Build module nets to wire bl outputs of sram modules to BL outputs of + * memory module */ for (const auto& child_module_output_port : sram_bl_ports) { - std::string chain_output_port_name = std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME); - add_module_output_nets_to_chain_mem_modules(module_manager, mem_module, - chain_output_port_name, circuit_lib, - child_module_output_port, - sram_mem_module, i, sram_mem_instance); + std::string chain_output_port_name = + std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME); + add_module_output_nets_to_chain_mem_modules( + module_manager, mem_module, chain_output_port_name, circuit_lib, + child_module_output_port, sram_mem_module, i, sram_mem_instance); } } /* Build module nets to wire the configuration chain */ - add_module_nets_to_ql_memory_bank_shift_register_module(module_manager, mem_module, - circuit_lib, sram_input_ports[0], sram_output_ports[0], - std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), - std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); + add_module_nets_to_ql_memory_bank_shift_register_module( + module_manager, mem_module, circuit_lib, sram_input_ports[0], + sram_output_ports[0], std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), + std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); /* Add global ports to the pb_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 a list of it + * 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 + * a list of it */ add_module_global_ports_from_child_modules(module_manager, mem_module); @@ -242,7 +276,7 @@ ModuleId build_bl_shift_register_chain_module(ModuleManager& module_manager, /********************************************************************* * WL shift register chain module organization - * + * * +-------+ +-------+ +-------+ * chain --->| CCFF |--->| CCFF |--->... --->| CCFF |---->chain * input&clock | [0] | | [1] | | [N-1] | output @@ -253,103 +287,115 @@ ModuleId build_bl_shift_register_chain_module(ModuleManager& module_manager, * | WL/WLRs of configurable modules | * ********************************************************************/ -static -ModuleId build_wl_shift_register_chain_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const std::string& module_name, - const CircuitModelId& sram_model, - const size_t& num_mems) { - +static ModuleId build_wl_shift_register_chain_module( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const std::string& module_name, const CircuitModelId& sram_model, + const size_t& num_mems) { /* Get the input ports from the SRAM */ - std::vector sram_input_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector sram_input_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true); VTR_ASSERT(1 == sram_input_ports.size()); /* Get the output ports from the SRAM */ - std::vector sram_output_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector sram_output_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, + true); VTR_ASSERT(1 == sram_output_ports.size()); /* Get the WL ports from the SRAM */ - std::vector sram_wl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WL, true); + std::vector sram_wl_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WL, true); VTR_ASSERT(1 == sram_wl_ports.size()); /* Get the optional WLR ports from the SRAM */ - std::vector sram_wlr_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR, true); + std::vector sram_wlr_ports = + circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR, true); VTR_ASSERT(0 == sram_wlr_ports.size() || 1 == sram_wlr_ports.size()); /* Create a module and add to the module manager */ - ModuleId mem_module = module_manager.add_module(module_name); + ModuleId mem_module = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); /* Label module usage */ module_manager.set_module_usage(mem_module, ModuleManager::MODULE_CONFIG); - - /* Add an input port, which is the head of configuration chain in the module */ + + /* Add an input port, which is the head of configuration chain in the module + */ /* TODO: restriction!!! * consider only the first input of the CCFF model as the D port, * which will be connected to the head of the chain */ - BasicPort chain_head_port(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME, + BasicPort chain_head_port(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME, circuit_lib.port_size(sram_input_ports[0])); - module_manager.add_port(mem_module, chain_head_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(mem_module, chain_head_port, + ModuleManager::MODULE_INPUT_PORT); - /* Add an output port, which is the tail of configuration chain in the module */ + /* Add an output port, which is the tail of configuration chain in the module + */ /* TODO: restriction!!! * consider only the first output of the CCFF model as the Q port, * which will be connected to the tail of the chain */ - BasicPort chain_tail_port(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME, + BasicPort chain_tail_port(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME, circuit_lib.port_size(sram_output_ports[0])); - module_manager.add_port(mem_module, chain_tail_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(mem_module, chain_tail_port, + ModuleManager::MODULE_OUTPUT_PORT); /* Add the output ports to output BL/WL signals */ - BasicPort chain_wl_port(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME, - num_mems); - module_manager.add_port(mem_module, chain_wl_port, ModuleManager::MODULE_OUTPUT_PORT); + BasicPort chain_wl_port(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME, num_mems); + module_manager.add_port(mem_module, chain_wl_port, + ModuleManager::MODULE_OUTPUT_PORT); /* Add the output ports to output WLR signals */ if (!sram_wlr_ports.empty()) { - BasicPort chain_wlr_port(WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME, - num_mems); - module_manager.add_port(mem_module, chain_wlr_port, ModuleManager::MODULE_OUTPUT_PORT); + BasicPort chain_wlr_port(WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME, num_mems); + module_manager.add_port(mem_module, chain_wlr_port, + ModuleManager::MODULE_OUTPUT_PORT); } /* Find the sram module in the module manager */ - ModuleId sram_mem_module = module_manager.find_module(circuit_lib.model_name(sram_model)); + ModuleId sram_mem_module = + module_manager.find_module(circuit_lib.model_name(sram_model)); /* Instanciate each submodule */ for (size_t i = 0; i < num_mems; ++i) { - size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module); + size_t sram_mem_instance = + module_manager.num_instance(mem_module, sram_mem_module); module_manager.add_child_module(mem_module, sram_mem_module); - module_manager.add_configurable_child(mem_module, sram_mem_module, sram_mem_instance); + module_manager.add_configurable_child(mem_module, sram_mem_module, + sram_mem_instance); - /* Build module nets to wire wl outputs of sram modules to WL outputs of memory module */ + /* Build module nets to wire wl outputs of sram modules to WL outputs of + * memory module */ for (const auto& child_module_output_port : sram_wl_ports) { - std::string chain_output_port_name = std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME); - add_module_output_nets_to_chain_mem_modules(module_manager, mem_module, - chain_output_port_name, circuit_lib, - child_module_output_port, - sram_mem_module, i, sram_mem_instance); + std::string chain_output_port_name = + std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME); + add_module_output_nets_to_chain_mem_modules( + module_manager, mem_module, chain_output_port_name, circuit_lib, + child_module_output_port, sram_mem_module, i, sram_mem_instance); } - /* Build module nets to wire wlr outputs of sram modules to WLR outputs of memory module */ + /* Build module nets to wire wlr outputs of sram modules to WLR outputs of + * memory module */ for (const auto& child_module_output_port : sram_wlr_ports) { - std::string chain_output_port_name = std::string(WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME); - add_module_output_nets_to_chain_mem_modules(module_manager, mem_module, - chain_output_port_name, circuit_lib, - child_module_output_port, - sram_mem_module, i, sram_mem_instance); + std::string chain_output_port_name = + std::string(WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME); + add_module_output_nets_to_chain_mem_modules( + module_manager, mem_module, chain_output_port_name, circuit_lib, + child_module_output_port, sram_mem_module, i, sram_mem_instance); } } /* Build module nets to wire the configuration chain */ - add_module_nets_to_ql_memory_bank_shift_register_module(module_manager, mem_module, - circuit_lib, sram_input_ports[0], sram_output_ports[0], - std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), - std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); + add_module_nets_to_ql_memory_bank_shift_register_module( + module_manager, mem_module, circuit_lib, sram_input_ports[0], + sram_output_ports[0], std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), + std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); /* Add global ports to the pb_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 a list of it + * 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 + * a list of it */ add_module_global_ports_from_child_modules(module_manager, mem_module); @@ -362,13 +408,14 @@ ModuleId build_wl_shift_register_chain_module(ModuleManager& module_manager, * - Find the number of BLs and WLs required for each region * - Create BL and WL decoders, and add them to decoder library * - Create nets to connect from top-level module inputs to inputs of decoders - * - Create nets to connect from outputs of decoders to BL/WL of configurable children + * - Create nets to connect from outputs of decoders to BL/WL of configurable + *children * * @note this function only adds the BL configuration bus for decoders * * Detailed schematic of how memory banks are connected in the top-level: - * Consider a random Region X, local BL address lines are aligned to the LSB of the - * top-level BL address lines + * Consider a random Region X, local BL address lines are aligned to the LSB of + *the top-level BL address lines * * top_bl_addr[N-1:0] * ^ @@ -381,12 +428,12 @@ ModuleId build_wl_shift_register_chain_module(ModuleManager& module_manager, * | +-------------------+ | * | | * - * The BL/WL decoders should have the same circuit designs no matter what region - * they are placed even when the number of configuration bits are different + * The BL/WL decoders should have the same circuit designs no matter what region + * they are placed even when the number of configuration bits are different * from one region to another! * This is designed to avoid any address collision between memory banks * since they are programmed in the same clock cycle - * For example: + * For example: * - Memory Bank A has 36 memory cells. * Its BL decoder has 3 address bit and 6 data output bit * Its WL decoder has 3 address bit and 6 data output bit @@ -401,233 +448,261 @@ ModuleId build_wl_shift_register_chain_module(ModuleManager& module_manager, * the BL address will be 3'b010 * the WL address will be 3'b010 * the data input will be 1'b1 - * However, in both cases, this will trigger a parasitic programming in bank B - * the BL address will be 2'b10 - * the WL address will be 2'b10 - * Assume the data input is expected to be 1'b1 for bank B - * but it will be overwritten to 1'b0 when programming the 36th cell in bank A! + * However, in both cases, this will trigger a parasitic programming in bank + *B the BL address will be 2'b10 the WL address will be 2'b10 Assume the data + *input is expected to be 1'b1 for bank B but it will be overwritten to 1'b0 + *when programming the 36th cell in bank A! * * Detailed schematic of each memory bank: - * @note The numbers are just made to show a simplified example, practical cases are more complicated! + * @note The numbers are just made to show a simplified example, practical cases + *are more complicated! * - * WL_enable WL address + * WL_enable WL address * | | * v v * +-----------------------------------------------+ * | Word Line Decoder | * +-----------------------------------------------+ - * +---------+ | | | + * +---------+ | | | * BL | | | | | - * enable ---->| |-----------+---------------+---- ... |------+--> BL[0:2] - * | | | | | | | | - * | | | v | v | v - * | Bit | | +-------+ | +-------+ | +------+ - * BL | Line | +-->| SRAM | +-->| SRAM | +->| SRAM | - * address ---->| Decoder | | | [0:8] | | | [0:5] | ... | | [0:7]| - * | | | +-------+ | +-------+ | +------+ - * | | | | | - * | |-----------+--------------+--------- | -----+--> BL[0:9] - * | | | | | | | | - * | | | v | v | v - * | | | +-------+ | +-------+ | +-------+ - * | | +-->| SRAM | | | SRAM | +->| SRAM | - * | | | | [0:80]| | | [0:63]| ... | | [0:31]| - * | | | +-------+ | +-------+ | +-------+ - * | | | | - * | | | ... ... ... | ... - * | | | | | - * | |-----------+---------------+---- --- | -----+--> BL[0:3] - * | | | | | | | | - * | | | v | v | v - * | | | +-------+ | +-------+ | +-------+ - * | | +-->| SRAM | +-->| SRAM | +->| SRAM | - * | | | |[0:5] | | | [0:8] | ... | | [0:2] | - * | | | +-------+ | +-------+ | +-------+ - * BL | | v v v + * enable ---->| |-----------+---------------+---- ... |------+--> + *BL[0:2] | | | | | | | | | | | + *v | v | v | Bit | | +-------+ | + *+-------+ | +------+ BL | Line | +-->| SRAM | +-->| + *SRAM | +->| SRAM | address ---->| Decoder | | | [0:8] | | | + *[0:5] | ... | | [0:7]| | | | +-------+ | +-------+ | + *+------+ | | | | | | + *|-----------+--------------+--------- | -----+--> BL[0:9] | | | + *| | | | | | | | v | v + *| v | | | +-------+ | +-------+ | +-------+ | | + *+-->| SRAM | | | SRAM | +->| SRAM | | | | | [0:80]| + *| | [0:63]| ... | | [0:31]| | | | +-------+ | +-------+ + *| +-------+ | | | | | | + *| ... ... ... | ... | | | | | + * | |-----------+---------------+---- --- | -----+--> + *BL[0:3] | | | | | | | | | | | + *v | v | v | | | +-------+ | + *+-------+ | +-------+ | | +-->| SRAM | +-->| SRAM | +->| + *SRAM | | | | |[0:5] | | | [0:8] | ... | | [0:2] | | | | + *+-------+ | +-------+ | +-------+ BL | | v v v * data_in ---->| | WL[0:9] WL[0:7] WL[0:4] * +---------+ * **********************************************************************/ -static -void add_top_module_nets_cmos_ql_memory_bank_bl_decoder_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const TopModuleNumConfigBits& num_config_bits) { - /* Find Enable port from the top-level module */ - ModulePortId en_port = module_manager.find_module_port(top_module, std::string(DECODER_ENABLE_PORT_NAME)); +static void add_top_module_nets_cmos_ql_memory_bank_bl_decoder_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const ModuleId& top_module, const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const TopModuleNumConfigBits& num_config_bits) { + /* Find Enable port from the top-level module */ + ModulePortId en_port = module_manager.find_module_port( + top_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort en_port_info = module_manager.module_port(top_module, en_port); - /* Find data-in port from the top-level module */ - ModulePortId din_port = module_manager.find_module_port(top_module, std::string(DECODER_DATA_IN_PORT_NAME)); + /* Find data-in port from the top-level module */ + ModulePortId din_port = module_manager.find_module_port( + top_module, std::string(DECODER_DATA_IN_PORT_NAME)); BasicPort din_port_info = module_manager.module_port(top_module, din_port); /* Data in port should match the number of configuration regions */ - VTR_ASSERT(din_port_info.get_width() == module_manager.regions(top_module).size()); + VTR_ASSERT(din_port_info.get_width() == + module_manager.regions(top_module).size()); - /* Find BL and WL address port from the top-level module */ - ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); - BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port); + /* Find BL and WL address port from the top-level module */ + ModulePortId bl_addr_port = module_manager.find_module_port( + top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); + BasicPort bl_addr_port_info = + module_manager.module_port(top_module, bl_addr_port); - /* Find the top-level number of BLs and WLs required to access each memory bit */ + /* Find the top-level number of BLs and WLs required to access each memory bit + */ size_t bl_addr_size = bl_addr_port_info.get_width(); /* Each memory bank has a unified number of BL/WLs */ size_t num_bls = 0; for (const auto& curr_config_bits : num_config_bits) { - num_bls = std::max(num_bls, curr_config_bits.first); + num_bls = std::max(num_bls, curr_config_bits.first); } - /* Create separated memory bank circuitry, i.e., BL/WL decoders for each region */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - /************************************************************** - * Add the BL decoder module + /* Create separated memory bank circuitry, i.e., BL/WL decoders for each + * region */ + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + /************************************************************** + * Add the BL decoder module * Search the decoder library * If we find one, we use the module. * Otherwise, we create one and add it to the decoder library */ - DecoderId bl_decoder_id = decoder_lib.find_decoder(bl_addr_size, num_bls, - true, true, false, false); + DecoderId bl_decoder_id = + decoder_lib.find_decoder(bl_addr_size, num_bls, true, true, false, false); if (DecoderId::INVALID() == bl_decoder_id) { - bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false, false); + bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, + false, false); } VTR_ASSERT(DecoderId::INVALID() != bl_decoder_id); /* Create a module if not existed yet */ - std::string bl_decoder_module_name = generate_memory_decoder_with_data_in_subckt_name(bl_addr_size, num_bls); - ModuleId bl_decoder_module = module_manager.find_module(bl_decoder_module_name); + std::string bl_decoder_module_name = + generate_memory_decoder_with_data_in_subckt_name(bl_addr_size, num_bls); + ModuleId bl_decoder_module = + module_manager.find_module(bl_decoder_module_name); if (ModuleId::INVALID() == bl_decoder_module) { /* BL decoder has the same ports as the frame-based decoders * We reuse it here */ - bl_decoder_module = build_bl_memory_decoder_module(module_manager, - decoder_lib, - bl_decoder_id); + bl_decoder_module = build_bl_memory_decoder_module( + module_manager, decoder_lib, bl_decoder_id); } VTR_ASSERT(ModuleId::INVALID() != bl_decoder_module); - size_t curr_bl_decoder_instance_id = module_manager.num_instance(top_module, bl_decoder_module); + size_t curr_bl_decoder_instance_id = + module_manager.num_instance(top_module, bl_decoder_module); module_manager.add_child_module(top_module, bl_decoder_module, false); - /************************************************************** + /************************************************************** * Add module nets from the top module to BL decoder's inputs */ - ModulePortId bl_decoder_en_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); - BasicPort bl_decoder_en_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_en_port); + ModulePortId bl_decoder_en_port = module_manager.find_module_port( + bl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); + BasicPort bl_decoder_en_port_info = + module_manager.module_port(bl_decoder_module, bl_decoder_en_port); - ModulePortId bl_decoder_addr_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort bl_decoder_addr_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_addr_port); + ModulePortId bl_decoder_addr_port = module_manager.find_module_port( + bl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort bl_decoder_addr_port_info = + module_manager.module_port(bl_decoder_module, bl_decoder_addr_port); - ModulePortId bl_decoder_din_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_IN_PORT_NAME)); - BasicPort bl_decoder_din_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_din_port); + ModulePortId bl_decoder_din_port = module_manager.find_module_port( + bl_decoder_module, std::string(DECODER_DATA_IN_PORT_NAME)); + BasicPort bl_decoder_din_port_info = + module_manager.module_port(bl_decoder_module, bl_decoder_din_port); /* Data in port of the local BL decoder should always be 1 */ VTR_ASSERT(1 == bl_decoder_din_port_info.get_width()); /* Top module Enable port -> BL Decoder Enable port */ - add_module_bus_nets(module_manager, - top_module, - top_module, 0, en_port, - bl_decoder_module, curr_bl_decoder_instance_id, bl_decoder_en_port); + add_module_bus_nets(module_manager, top_module, top_module, 0, en_port, + bl_decoder_module, curr_bl_decoder_instance_id, + bl_decoder_en_port); /* Top module Address port -> BL Decoder Address port */ - add_module_bus_nets(module_manager, - top_module, - top_module, 0, bl_addr_port, - bl_decoder_module, curr_bl_decoder_instance_id, bl_decoder_addr_port); + add_module_bus_nets(module_manager, top_module, top_module, 0, bl_addr_port, + bl_decoder_module, curr_bl_decoder_instance_id, + bl_decoder_addr_port); /* Top module data_in port -> BL Decoder data_in port: - * Note that each region has independent data_in connection from the top-level module - * The pin index is the configuration region index + * Note that each region has independent data_in connection from the + * top-level module The pin index is the configuration region index */ - ModuleNetId din_net = create_module_source_pin_net(module_manager, top_module, - top_module, 0, - din_port, - din_port_info.pins()[size_t(config_region)]); + ModuleNetId din_net = create_module_source_pin_net( + module_manager, top_module, top_module, 0, din_port, + din_port_info.pins()[size_t(config_region)]); VTR_ASSERT(ModuleNetId::INVALID() != din_net); /* Configure the net sink */ - module_manager.add_module_net_sink(top_module, din_net, bl_decoder_module, curr_bl_decoder_instance_id, bl_decoder_din_port, bl_decoder_din_port_info.pins()[0]); + module_manager.add_module_net_sink( + top_module, din_net, bl_decoder_module, curr_bl_decoder_instance_id, + bl_decoder_din_port, bl_decoder_din_port_info.pins()[0]); - /************************************************************** + /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric - * The distribution is a matrix which contains the starting index of BL/WL for each column or row + * The distribution is a matrix which contains the starting index of BL/WL + * for each column or row */ - std::pair child_x_range = compute_memory_bank_regional_configurable_child_x_range(module_manager, top_module, config_region); - std::map num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module, - config_region, - circuit_lib, sram_model); - std::map bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile); + std::pair child_x_range = + compute_memory_bank_regional_configurable_child_x_range( + module_manager, top_module, config_region); + std::map num_bls_per_tile = + compute_memory_bank_regional_bitline_numbers_per_tile( + module_manager, top_module, config_region, circuit_lib, sram_model); + std::map bl_start_index_per_tile = + compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, + num_bls_per_tile); - /************************************************************** + /************************************************************** * Add nets from BL data out to each configurable child * BL data output pins are connected to the BL input pins of each PB/CB/SB * For all the PB/CB/SB in the same column, they share the same set of BLs * A quick example * - * BL[i .. i + sqrt(N)] + * BL[i .. i + sqrt(N)] * | * | CLB[1][H] - * | +---------+ - * | | SRAM | - * +-->| [0..N] | + * | +---------+ + * | | SRAM | + * +-->| [0..N] | * | +---------+ * | * ... * | CLB[1][1] - * | +---------+ - * | | SRAM | - * +-->| [0..N] | + * | +---------+ + * | | SRAM | + * +-->| [0..N] | * | +---------+ * | */ - ModulePortId bl_decoder_dout_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); - BasicPort bl_decoder_dout_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_dout_port); + ModulePortId bl_decoder_dout_port = module_manager.find_module_port( + bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort bl_decoder_dout_port_info = + module_manager.module_port(bl_decoder_module, bl_decoder_dout_port); - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + for (size_t child_id = 0; + child_id < + module_manager.region_configurable_children(top_module, config_region) + .size(); + ++child_id) { + ModuleId child_module = module_manager.region_configurable_children( + top_module, config_region)[child_id]; + vtr::Point coord = + module_manager.region_configurable_child_coordinates( + top_module, config_region)[child_id]; - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + size_t child_instance = + module_manager.region_configurable_child_instances( + top_module, config_region)[child_id]; /* Find the BL port */ - ModulePortId child_bl_port = module_manager.find_module_port(child_module, std::string(MEMORY_BL_PORT_NAME)); - BasicPort child_bl_port_info = module_manager.module_port(child_module, child_bl_port); + ModulePortId child_bl_port = module_manager.find_module_port( + child_module, std::string(MEMORY_BL_PORT_NAME)); + BasicPort child_bl_port_info = + module_manager.module_port(child_module, child_bl_port); size_t cur_bl_index = 0; for (const size_t& sink_bl_pin : child_bl_port_info.pins()) { size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + cur_bl_index; - /* Find the BL decoder data index: - * It should be the starting index plus an offset which is the residual when divided by the number of BLs in this tile + /* Find the BL decoder data index: + * It should be the starting index plus an offset which is the residual + * when divided by the number of BLs in this tile */ VTR_ASSERT(bl_pin_id < bl_decoder_dout_port_info.pins().size()); /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - bl_decoder_module, curr_bl_decoder_instance_id, - bl_decoder_dout_port, - bl_decoder_dout_port_info.pins()[bl_pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, bl_decoder_module, + curr_bl_decoder_instance_id, bl_decoder_dout_port, + bl_decoder_dout_port_info.pins()[bl_pin_id]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_bl_port, sink_bl_pin); + module_manager.add_module_net_sink(top_module, net, child_module, + child_instance, child_bl_port, + sink_bl_pin); cur_bl_index++; } } - /************************************************************** + /************************************************************** * Add the BL and WL decoders to the end of configurable children list - * Note: this MUST be done after adding all the module nets to other regular configurable children + * Note: this MUST be done after adding all the module nets to other regular + * configurable children */ - module_manager.add_configurable_child(top_module, bl_decoder_module, curr_bl_decoder_instance_id); - module_manager.add_configurable_child_to_region(top_module, - config_region, - bl_decoder_module, - curr_bl_decoder_instance_id, - module_manager.configurable_children(top_module).size() - 1); + module_manager.add_configurable_child(top_module, bl_decoder_module, + curr_bl_decoder_instance_id); + module_manager.add_configurable_child_to_region( + top_module, config_region, bl_decoder_module, curr_bl_decoder_instance_id, + module_manager.configurable_children(top_module).size() - 1); } } @@ -637,25 +712,27 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_decoder_config_bus(ModuleManager * - Find the number of BLs and WLs required for each region * - Create BL and WL decoders, and add them to decoder library * - Create nets to connect from top-level module inputs to inputs of decoders - * - Create nets to connect from outputs of decoders to BL/WL of configurable children + * - Create nets to connect from outputs of decoders to BL/WL of configurable + *children * * @note this function only adds the WL configuration bus for decoders * - * @note see detailed explanation on the bus connection in function add_top_module_nets_cmos_ql_memory_bank_bl_decoder_config_bus() + * @note see detailed explanation on the bus connection in function + *add_top_module_nets_cmos_ql_memory_bank_bl_decoder_config_bus() **********************************************************************/ -static -void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const TopModuleNumConfigBits& num_config_bits) { - /* Find Enable port from the top-level module */ - ModulePortId en_port = module_manager.find_module_port(top_module, std::string(DECODER_ENABLE_PORT_NAME)); +static void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const ModuleId& top_module, const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const TopModuleNumConfigBits& num_config_bits) { + /* Find Enable port from the top-level module */ + ModulePortId en_port = module_manager.find_module_port( + top_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort en_port_info = module_manager.module_port(top_module, en_port); - - /* Find readback port from the top-level module */ - ModulePortId readback_port = module_manager.find_module_port(top_module, std::string(DECODER_READBACK_PORT_NAME)); + + /* Find readback port from the top-level module */ + ModulePortId readback_port = module_manager.find_module_port( + top_module, std::string(DECODER_READBACK_PORT_NAME)); BasicPort readback_port_info; /* Readback port if available, should be a 1-bit port */ @@ -664,113 +741,146 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager VTR_ASSERT(readback_port_info.get_width() == 1); } - /* Find BL and WL address port from the top-level module */ - ModulePortId wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); - BasicPort wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port); + /* Find BL and WL address port from the top-level module */ + ModulePortId wl_addr_port = module_manager.find_module_port( + top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); + BasicPort wl_addr_port_info = + module_manager.module_port(top_module, wl_addr_port); - /* Find the top-level number of BLs and WLs required to access each memory bit */ + /* Find the top-level number of BLs and WLs required to access each memory bit + */ size_t wl_addr_size = wl_addr_port_info.get_width(); /* Each memory bank has a unified number of BL/WLs */ size_t num_wls = 0; for (const auto& curr_config_bits : num_config_bits) { - num_wls = std::max(num_wls, curr_config_bits.second); + num_wls = std::max(num_wls, curr_config_bits.second); } - /* Create separated memory bank circuitry, i.e., BL/WL decoders for each region */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - /************************************************************** - * Add the WL decoder module + /* Create separated memory bank circuitry, i.e., BL/WL decoders for each + * region */ + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + /************************************************************** + * Add the WL decoder module * Search the decoder library * If we find one, we use the module. * Otherwise, we create one and add it to the decoder library */ - DecoderId wl_decoder_id = decoder_lib.find_decoder(wl_addr_size, num_wls, - true, false, false, readback_port != ModulePortId::INVALID()); + DecoderId wl_decoder_id = + decoder_lib.find_decoder(wl_addr_size, num_wls, true, false, false, + readback_port != ModulePortId::INVALID()); if (DecoderId::INVALID() == wl_decoder_id) { - wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false, readback_port != ModulePortId::INVALID()); + wl_decoder_id = + decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false, + readback_port != ModulePortId::INVALID()); } VTR_ASSERT(DecoderId::INVALID() != wl_decoder_id); /* Create a module if not existed yet */ - std::string wl_decoder_module_name = generate_memory_decoder_subckt_name(wl_addr_size, num_wls); - ModuleId wl_decoder_module = module_manager.find_module(wl_decoder_module_name); + std::string wl_decoder_module_name = + generate_memory_decoder_subckt_name(wl_addr_size, num_wls); + ModuleId wl_decoder_module = + module_manager.find_module(wl_decoder_module_name); if (ModuleId::INVALID() == wl_decoder_module) { /* BL decoder has the same ports as the frame-based decoders * We reuse it here */ - wl_decoder_module = build_wl_memory_decoder_module(module_manager, - decoder_lib, - wl_decoder_id); + wl_decoder_module = build_wl_memory_decoder_module( + module_manager, decoder_lib, wl_decoder_id); } VTR_ASSERT(ModuleId::INVALID() != wl_decoder_module); - size_t curr_wl_decoder_instance_id = module_manager.num_instance(top_module, wl_decoder_module); + size_t curr_wl_decoder_instance_id = + module_manager.num_instance(top_module, wl_decoder_module); module_manager.add_child_module(top_module, wl_decoder_module, false); - /************************************************************** - * Add module nets from the top module to WL decoder's inputs + /************************************************************** + * Add module nets from the top module to WL decoder's inputs */ - ModulePortId wl_decoder_en_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); - BasicPort wl_decoder_en_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_en_port); + ModulePortId wl_decoder_en_port = module_manager.find_module_port( + wl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); + BasicPort wl_decoder_en_port_info = + module_manager.module_port(wl_decoder_module, wl_decoder_en_port); - ModulePortId wl_decoder_addr_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort wl_decoder_addr_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_addr_port); + ModulePortId wl_decoder_addr_port = module_manager.find_module_port( + wl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort wl_decoder_addr_port_info = + module_manager.module_port(wl_decoder_module, wl_decoder_addr_port); - ModulePortId wl_decoder_readback_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_READBACK_PORT_NAME)); + ModulePortId wl_decoder_readback_port = module_manager.find_module_port( + wl_decoder_module, std::string(DECODER_READBACK_PORT_NAME)); BasicPort wl_decoder_readback_port_info; - if (wl_decoder_readback_port) { - wl_decoder_readback_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_readback_port); + if (wl_decoder_readback_port) { + wl_decoder_readback_port_info = + module_manager.module_port(wl_decoder_module, wl_decoder_readback_port); } /* Top module Enable port -> WL Decoder Enable port */ - add_module_bus_nets(module_manager, - top_module, - top_module, 0, en_port, - wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_en_port); + add_module_bus_nets(module_manager, top_module, top_module, 0, en_port, + wl_decoder_module, curr_wl_decoder_instance_id, + wl_decoder_en_port); /* Top module Address port -> WL Decoder Address port */ - add_module_bus_nets(module_manager, - top_module, - top_module, 0, wl_addr_port, - wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_addr_port); + add_module_bus_nets(module_manager, top_module, top_module, 0, wl_addr_port, + wl_decoder_module, curr_wl_decoder_instance_id, + wl_decoder_addr_port); /* Top module readback port -> WL Decoder readback port */ - if (wl_decoder_readback_port) { - add_module_bus_nets(module_manager, - top_module, - top_module, 0, readback_port, - wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_readback_port); + if (wl_decoder_readback_port) { + add_module_bus_nets(module_manager, top_module, top_module, 0, + readback_port, wl_decoder_module, + curr_wl_decoder_instance_id, + wl_decoder_readback_port); } - /************************************************************** + /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric - * The distribution is a matrix which contains the starting index of BL/WL for each column or row + * The distribution is a matrix which contains the starting index of BL/WL + * for each column or row */ - std::pair child_y_range = compute_memory_bank_regional_configurable_child_y_range(module_manager, top_module, config_region); - std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, - config_region, - circuit_lib, sram_model); - std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); + std::pair child_y_range = + compute_memory_bank_regional_configurable_child_y_range( + module_manager, top_module, config_region); + std::map num_wls_per_tile = + compute_memory_bank_regional_wordline_numbers_per_tile( + module_manager, top_module, config_region, circuit_lib, sram_model); + std::map wl_start_index_per_tile = + compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, + num_wls_per_tile); - /************************************************************** + /************************************************************** * Add nets from WL data out to each configurable child */ - ModulePortId wl_decoder_dout_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); - BasicPort wl_decoder_dout_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_dout_port); + ModulePortId wl_decoder_dout_port = module_manager.find_module_port( + wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort wl_decoder_dout_port_info = + module_manager.module_port(wl_decoder_module, wl_decoder_dout_port); /* Note we skip the last child which is the bl decoder added */ - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + for (size_t child_id = 0; + child_id < + module_manager.region_configurable_children(top_module, config_region) + .size(); + ++child_id) { + ModuleId child_module = module_manager.region_configurable_children( + top_module, config_region)[child_id]; + vtr::Point coord = + module_manager.region_configurable_child_coordinates( + top_module, config_region)[child_id]; - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + size_t child_instance = + module_manager.region_configurable_child_instances( + top_module, config_region)[child_id]; - /* Find the WL port. If the child does not have WL port, bypass it. It is usually a decoder module */ - ModulePortId child_wl_port = module_manager.find_module_port(child_module, std::string(MEMORY_WL_PORT_NAME)); + /* Find the WL port. If the child does not have WL port, bypass it. It is + * usually a decoder module */ + ModulePortId child_wl_port = module_manager.find_module_port( + child_module, std::string(MEMORY_WL_PORT_NAME)); if (!child_wl_port) { continue; } - BasicPort child_wl_port_info = module_manager.module_port(child_module, child_wl_port); + BasicPort child_wl_port_info = + module_manager.module_port(child_module, child_wl_port); size_t cur_wl_index = 0; @@ -779,90 +889,109 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager VTR_ASSERT(wl_pin_id < wl_decoder_dout_port_info.pins().size()); /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - wl_decoder_module, curr_wl_decoder_instance_id, - wl_decoder_dout_port, - wl_decoder_dout_port_info.pins()[wl_pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, wl_decoder_module, + curr_wl_decoder_instance_id, wl_decoder_dout_port, + wl_decoder_dout_port_info.pins()[wl_pin_id]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_wl_port, sink_wl_pin); - + module_manager.add_module_net_sink(top_module, net, child_module, + child_instance, child_wl_port, + sink_wl_pin); + cur_wl_index++; } } - /************************************************************** + /************************************************************** * Optional: Add nets from WLR data out to each configurable child */ - ModulePortId wl_decoder_data_ren_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_READ_ENABLE_PORT_NAME)); + ModulePortId wl_decoder_data_ren_port = module_manager.find_module_port( + wl_decoder_module, std::string(DECODER_DATA_READ_ENABLE_PORT_NAME)); BasicPort wl_decoder_data_ren_port_info; - if (wl_decoder_data_ren_port) { - wl_decoder_data_ren_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_data_ren_port); - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; - - /* Find the WLR port. If the child does not have WLR port, bypass it. It is usually a decoder module */ - ModulePortId child_wlr_port = module_manager.find_module_port(child_module, std::string(MEMORY_WLR_PORT_NAME)); + if (wl_decoder_data_ren_port) { + wl_decoder_data_ren_port_info = + module_manager.module_port(wl_decoder_module, wl_decoder_data_ren_port); + for (size_t child_id = 0; + child_id < module_manager + .region_configurable_children(top_module, config_region) + .size(); + ++child_id) { + ModuleId child_module = module_manager.region_configurable_children( + top_module, config_region)[child_id]; + vtr::Point coord = + module_manager.region_configurable_child_coordinates( + top_module, config_region)[child_id]; + + size_t child_instance = + module_manager.region_configurable_child_instances( + top_module, config_region)[child_id]; + + /* Find the WLR port. If the child does not have WLR port, bypass it. It + * is usually a decoder module */ + ModulePortId child_wlr_port = module_manager.find_module_port( + child_module, std::string(MEMORY_WLR_PORT_NAME)); if (!child_wlr_port) { continue; } - BasicPort child_wlr_port_info = module_manager.module_port(child_module, child_wlr_port); - + BasicPort child_wlr_port_info = + module_manager.module_port(child_module, child_wlr_port); + size_t cur_wlr_index = 0; - + for (const size_t& sink_wlr_pin : child_wlr_port_info.pins()) { - size_t wlr_pin_id = wl_start_index_per_tile[coord.y()] + cur_wlr_index; + size_t wlr_pin_id = + wl_start_index_per_tile[coord.y()] + cur_wlr_index; VTR_ASSERT(wlr_pin_id < wl_decoder_data_ren_port_info.pins().size()); - + /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - wl_decoder_module, curr_wl_decoder_instance_id, - wl_decoder_data_ren_port, - wl_decoder_data_ren_port_info.pins()[wlr_pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, wl_decoder_module, + curr_wl_decoder_instance_id, wl_decoder_data_ren_port, + wl_decoder_data_ren_port_info.pins()[wlr_pin_id]); VTR_ASSERT(ModuleNetId::INVALID() != net); - + /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_wlr_port, sink_wlr_pin); - + module_manager.add_module_net_sink(top_module, net, child_module, + child_instance, child_wlr_port, + sink_wlr_pin); + cur_wlr_index++; } } } - /************************************************************** + /************************************************************** * Add the BL and WL decoders to the end of configurable children list - * Note: this MUST be done after adding all the module nets to other regular configurable children + * Note: this MUST be done after adding all the module nets to other regular + * configurable children */ - module_manager.add_configurable_child(top_module, wl_decoder_module, curr_wl_decoder_instance_id); - module_manager.add_configurable_child_to_region(top_module, - config_region, - wl_decoder_module, - curr_wl_decoder_instance_id, - module_manager.configurable_children(top_module).size() - 1); + module_manager.add_configurable_child(top_module, wl_decoder_module, + curr_wl_decoder_instance_id); + module_manager.add_configurable_child_to_region( + top_module, config_region, wl_decoder_module, curr_wl_decoder_instance_id, + module_manager.configurable_children(top_module).size() - 1); } } /********************************************************************* - * This function to add nets for quicklogic memory banks using flatten BLs and WLs - * Each configuration region has independent BL/WLs + * This function to add nets for quicklogic memory banks using flatten BLs and + *WLs Each configuration region has independent BL/WLs * - Find the number of BLs and WLs required for each region - * - Create nets to connect from top-level module inputs to BL/WL of configurable children + * - Create nets to connect from top-level module inputs to BL/WL of + *configurable children * * @note this function only adds the BL configuration bus * * Detailed schematic of each memory bank: - * @note The numbers are just made to show a simplified example, practical cases are more complicated! + * @note The numbers are just made to show a simplified example, practical cases + *are more complicated! * * BL[0:9] BL[10:17] BL[18:22] - * | | | * | | | - * WL[0:3]-->-----------+---------------+---- ... |------+--> + * | | | + * WL[0:3]-->-----------+---------------+---- ... |------+--> * | | | | | | * | v | v | v * | +-------+ | +-------+ | +------+ @@ -870,7 +999,7 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager * | | [0:8] | | | [0:5] | ... | | [0:7]| * | +-------+ | +-------+ | +------+ * | | | - * WL[4:14] -----------+--------------+--------- | -----+--> + * WL[4:14] -----------+--------------+--------- | -----+--> * | | | | | | * | v | v | v * | +-------+ | +-------+ | +-------+ @@ -880,7 +1009,7 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager * | | * | ... ... ... | ... * | | | - * WL[15:18] -----------+---------------+---- --- | -----+--> + * WL[15:18] -----------+---------------+---- --- | -----+--> * | | | | | | * | v | v | v * | +-------+ | +-------+ | +-------+ @@ -889,59 +1018,78 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager * | +-------+ | +-------+ | +-------+ * v v v * WL[0:9] WL[0:7] WL[0:4] - * + * **********************************************************************/ -static -void add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus(ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model) { - /* Create connections between BLs of top-level module and BLs of child modules for each region */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - /************************************************************** +static void add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus( + ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model) { + /* Create connections between BLs of top-level module and BLs of child modules + * for each region */ + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric - * The distribution is a matrix which contains the starting index of BL/WL for each column or row + * The distribution is a matrix which contains the starting index of BL/WL + * for each column or row */ - std::pair child_x_range = compute_memory_bank_regional_configurable_child_x_range(module_manager, top_module, config_region); - std::map num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module, - config_region, - circuit_lib, sram_model); - std::map bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile); + std::pair child_x_range = + compute_memory_bank_regional_configurable_child_x_range( + module_manager, top_module, config_region); + std::map num_bls_per_tile = + compute_memory_bank_regional_bitline_numbers_per_tile( + module_manager, top_module, config_region, circuit_lib, sram_model); + std::map bl_start_index_per_tile = + compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, + num_bls_per_tile); - /************************************************************** + /************************************************************** * Add BL nets from top module to each configurable child * BL pins of top module are connected to the BL input pins of each PB/CB/SB * For all the PB/CB/SB in the same column, they share the same set of BLs * A quick example * - * BL[i .. i + sqrt(N)] + * BL[i .. i + sqrt(N)] * | * | CLB[1][H] - * | +---------+ - * | | SRAM | - * +-->| [0..N] | + * | +---------+ + * | | SRAM | + * +-->| [0..N] | * | +---------+ * | * ... * | CLB[1][1] - * | +---------+ - * | | SRAM | - * +-->| [0..N] | + * | +---------+ + * | | SRAM | + * +-->| [0..N] | * | +---------+ * | */ - ModulePortId top_module_bl_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), config_region)); - BasicPort top_module_bl_port_info = module_manager.module_port(top_module, top_module_bl_port); + ModulePortId top_module_bl_port = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(MEMORY_BL_PORT_NAME), config_region)); + BasicPort top_module_bl_port_info = + module_manager.module_port(top_module, top_module_bl_port); - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + for (size_t child_id = 0; + child_id < + module_manager.region_configurable_children(top_module, config_region) + .size(); + ++child_id) { + ModuleId child_module = module_manager.region_configurable_children( + top_module, config_region)[child_id]; + vtr::Point coord = + module_manager.region_configurable_child_coordinates( + top_module, config_region)[child_id]; - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + size_t child_instance = + module_manager.region_configurable_child_instances( + top_module, config_region)[child_id]; /* Find the BL port */ - ModulePortId child_bl_port = module_manager.find_module_port(child_module, std::string(MEMORY_BL_PORT_NAME)); - BasicPort child_bl_port_info = module_manager.module_port(child_module, child_bl_port); + ModulePortId child_bl_port = module_manager.find_module_port( + child_module, std::string(MEMORY_BL_PORT_NAME)); + BasicPort child_bl_port_info = + module_manager.module_port(child_module, child_bl_port); size_t cur_bl_index = 0; @@ -950,15 +1098,15 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus(ModuleManager VTR_ASSERT(bl_pin_id < top_module_bl_port_info.pins().size()); /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - top_module, 0, - top_module_bl_port, - top_module_bl_port_info.pins()[bl_pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, top_module, 0, top_module_bl_port, + top_module_bl_port_info.pins()[bl_pin_id]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_bl_port, sink_bl_pin); + module_manager.add_module_net_sink(top_module, net, child_module, + child_instance, child_bl_port, + sink_bl_pin); cur_bl_index++; } @@ -967,47 +1115,68 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus(ModuleManager } /********************************************************************* - * Top-level function to add nets for quicklogic memory banks using flatten BL/WLs - * Each configuration region has independent BL/WLs + * Top-level function to add nets for quicklogic memory banks using flatten + *BL/WLs Each configuration region has independent BL/WLs * - Find the number of BLs and WLs required for each region - * - Create nets to connect from top-level module inputs to BL/WL of configurable children + * - Create nets to connect from top-level module inputs to BL/WL of + *configurable children * * @note this function only adds the WL configuration bus * - * @note see detailed explanation on the bus connection in function add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus() + * @note see detailed explanation on the bus connection in function + *add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus() **********************************************************************/ -static -void add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus(ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model) { - /* Create connections between WLs of top-level module and WLs of child modules for each region */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - /************************************************************** +static void add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus( + ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model) { + /* Create connections between WLs of top-level module and WLs of child modules + * for each region */ + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric - * The distribution is a matrix which contains the starting index of BL/WL for each column or row + * The distribution is a matrix which contains the starting index of BL/WL + * for each column or row */ - std::pair child_y_range = compute_memory_bank_regional_configurable_child_y_range(module_manager, top_module, config_region); - std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, - config_region, - circuit_lib, sram_model); - std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); + std::pair child_y_range = + compute_memory_bank_regional_configurable_child_y_range( + module_manager, top_module, config_region); + std::map num_wls_per_tile = + compute_memory_bank_regional_wordline_numbers_per_tile( + module_manager, top_module, config_region, circuit_lib, sram_model); + std::map wl_start_index_per_tile = + compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, + num_wls_per_tile); - /************************************************************** + /************************************************************** * Add WL nets from top module to each configurable child */ - ModulePortId top_module_wl_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region)); - BasicPort top_module_wl_port_info = module_manager.module_port(top_module, top_module_wl_port); + ModulePortId top_module_wl_port = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(MEMORY_WL_PORT_NAME), config_region)); + BasicPort top_module_wl_port_info = + module_manager.module_port(top_module, top_module_wl_port); - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + for (size_t child_id = 0; + child_id < + module_manager.region_configurable_children(top_module, config_region) + .size(); + ++child_id) { + ModuleId child_module = module_manager.region_configurable_children( + top_module, config_region)[child_id]; + vtr::Point coord = + module_manager.region_configurable_child_coordinates( + top_module, config_region)[child_id]; - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + size_t child_instance = + module_manager.region_configurable_child_instances( + top_module, config_region)[child_id]; /* Find the WL port */ - ModulePortId child_wl_port = module_manager.find_module_port(child_module, std::string(MEMORY_WL_PORT_NAME)); - BasicPort child_wl_port_info = module_manager.module_port(child_module, child_wl_port); + ModulePortId child_wl_port = module_manager.find_module_port( + child_module, std::string(MEMORY_WL_PORT_NAME)); + BasicPort child_wl_port_info = + module_manager.module_port(child_module, child_wl_port); size_t cur_wl_index = 0; @@ -1016,54 +1185,69 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus(ModuleManager VTR_ASSERT(wl_pin_id < top_module_wl_port_info.pins().size()); /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - top_module, 0, - top_module_wl_port, - top_module_wl_port_info.pins()[wl_pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, top_module, 0, top_module_wl_port, + top_module_wl_port_info.pins()[wl_pin_id]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_wl_port, sink_wl_pin); - + module_manager.add_module_net_sink(top_module, net, child_module, + child_instance, child_wl_port, + sink_wl_pin); + cur_wl_index++; } } - /************************************************************** + /************************************************************** * Optional: Add WLR nets from top module to each configurable child */ - ModulePortId top_module_wlr_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_WLR_PORT_NAME), config_region)); + ModulePortId top_module_wlr_port = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(MEMORY_WLR_PORT_NAME), config_region)); BasicPort top_module_wlr_port_info; - if (top_module_wlr_port) { - top_module_wlr_port_info = module_manager.module_port(top_module, top_module_wlr_port); - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; - + if (top_module_wlr_port) { + top_module_wlr_port_info = + module_manager.module_port(top_module, top_module_wlr_port); + for (size_t child_id = 0; + child_id < module_manager + .region_configurable_children(top_module, config_region) + .size(); + ++child_id) { + ModuleId child_module = module_manager.region_configurable_children( + top_module, config_region)[child_id]; + vtr::Point coord = + module_manager.region_configurable_child_coordinates( + top_module, config_region)[child_id]; + + size_t child_instance = + module_manager.region_configurable_child_instances( + top_module, config_region)[child_id]; + /* Find the WL port */ - ModulePortId child_wlr_port = module_manager.find_module_port(child_module, std::string(MEMORY_WLR_PORT_NAME)); - BasicPort child_wlr_port_info = module_manager.module_port(child_module, child_wlr_port); - + ModulePortId child_wlr_port = module_manager.find_module_port( + child_module, std::string(MEMORY_WLR_PORT_NAME)); + BasicPort child_wlr_port_info = + module_manager.module_port(child_module, child_wlr_port); + size_t cur_wlr_index = 0; - + for (const size_t& sink_wlr_pin : child_wlr_port_info.pins()) { - size_t wlr_pin_id = wl_start_index_per_tile[coord.y()] + cur_wlr_index; + size_t wlr_pin_id = + wl_start_index_per_tile[coord.y()] + cur_wlr_index; VTR_ASSERT(wlr_pin_id < top_module_wlr_port_info.pins().size()); - + /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - top_module, 0, - top_module_wlr_port, - top_module_wlr_port_info.pins()[wlr_pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, top_module, 0, top_module_wlr_port, + top_module_wlr_port_info.pins()[wlr_pin_id]); VTR_ASSERT(ModuleNetId::INVALID() != net); - + /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_wlr_port, sink_wlr_pin); - + module_manager.add_module_net_sink(top_module, net, child_module, + child_instance, child_wlr_port, + sink_wlr_pin); + cur_wlr_index++; } } @@ -1073,41 +1257,50 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus(ModuleManager /********************************************************************* * This function to add nets for QuickLogic memory bank - * We build the net connects between the head ports of BL shift register banks + * We build the net connects between the head ports of BL shift register banks * and the head ports of top-level module **********************************************************************/ -static -void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_heads(ModuleManager& module_manager, - const ModuleId& top_module, - const MemoryBankShiftRegisterBanks& sr_banks) { +static void +add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_heads( + ModuleManager& module_manager, const ModuleId& top_module, + const MemoryBankShiftRegisterBanks& sr_banks) { std::string head_port_name(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME); - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - ModulePortId sr_head_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(head_port_name, config_region)); - BasicPort sr_head_port_info = module_manager.module_port(top_module, sr_head_port); + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + ModulePortId sr_head_port = module_manager.find_module_port( + top_module, + generate_regional_blwl_port_name(head_port_name, config_region)); + BasicPort sr_head_port_info = + module_manager.module_port(top_module, sr_head_port); /* Iterate over each shift register banks */ for (const auto& bank : sr_banks.bl_banks(config_region)) { /* Get the module and instance ids */ - ModuleId sr_bank_module = sr_banks.bl_shift_register_bank_module(config_region, bank); - size_t sr_bank_instance = sr_banks.bl_shift_register_bank_instance(config_region, bank); + ModuleId sr_bank_module = + sr_banks.bl_shift_register_bank_module(config_region, bank); + size_t sr_bank_instance = + sr_banks.bl_shift_register_bank_instance(config_region, bank); VTR_ASSERT(sr_bank_module); - ModulePortId sr_module_head_port = module_manager.find_module_port(sr_bank_module, head_port_name); - BasicPort sr_module_head_port_info = module_manager.module_port(sr_bank_module, sr_module_head_port); + ModulePortId sr_module_head_port = + module_manager.find_module_port(sr_bank_module, head_port_name); + BasicPort sr_module_head_port_info = + module_manager.module_port(sr_bank_module, sr_module_head_port); VTR_ASSERT(sr_module_head_port_info.get_width() == 1); - for (size_t ipin = 0; ipin < sr_module_head_port_info.pins().size(); ++ipin) { + for (size_t ipin = 0; ipin < sr_module_head_port_info.pins().size(); + ++ipin) { /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - top_module, 0, - sr_head_port, - sr_head_port_info.pins()[size_t(bank)]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, top_module, 0, sr_head_port, + sr_head_port_info.pins()[size_t(bank)]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - sr_bank_module, sr_bank_instance, sr_module_head_port, sr_module_head_port_info.pins()[ipin]); + module_manager.add_module_net_sink( + top_module, net, sr_bank_module, sr_bank_instance, + sr_module_head_port, sr_module_head_port_info.pins()[ipin]); } } } @@ -1115,41 +1308,50 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_heads(Module /********************************************************************* * This function to add nets for QuickLogic memory bank - * We build the net connects between the head ports of BL shift register banks + * We build the net connects between the head ports of BL shift register banks * and the head ports of top-level module **********************************************************************/ -static -void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_heads(ModuleManager& module_manager, - const ModuleId& top_module, - const MemoryBankShiftRegisterBanks& sr_banks) { +static void +add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_heads( + ModuleManager& module_manager, const ModuleId& top_module, + const MemoryBankShiftRegisterBanks& sr_banks) { std::string head_port_name(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME); - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - ModulePortId sr_head_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(head_port_name, config_region)); - BasicPort sr_head_port_info = module_manager.module_port(top_module, sr_head_port); + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + ModulePortId sr_head_port = module_manager.find_module_port( + top_module, + generate_regional_blwl_port_name(head_port_name, config_region)); + BasicPort sr_head_port_info = + module_manager.module_port(top_module, sr_head_port); /* Iterate over each shift register banks */ for (const auto& bank : sr_banks.wl_banks(config_region)) { /* Get the module and instance ids */ - ModuleId sr_bank_module = sr_banks.wl_shift_register_bank_module(config_region, bank); - size_t sr_bank_instance = sr_banks.wl_shift_register_bank_instance(config_region, bank); + ModuleId sr_bank_module = + sr_banks.wl_shift_register_bank_module(config_region, bank); + size_t sr_bank_instance = + sr_banks.wl_shift_register_bank_instance(config_region, bank); VTR_ASSERT(sr_bank_module); - ModulePortId sr_module_head_port = module_manager.find_module_port(sr_bank_module, head_port_name); - BasicPort sr_module_head_port_info = module_manager.module_port(sr_bank_module, sr_module_head_port); + ModulePortId sr_module_head_port = + module_manager.find_module_port(sr_bank_module, head_port_name); + BasicPort sr_module_head_port_info = + module_manager.module_port(sr_bank_module, sr_module_head_port); VTR_ASSERT(sr_module_head_port_info.get_width() == 1); - for (size_t ipin = 0; ipin < sr_module_head_port_info.pins().size(); ++ipin) { + for (size_t ipin = 0; ipin < sr_module_head_port_info.pins().size(); + ++ipin) { /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - top_module, 0, - sr_head_port, - sr_head_port_info.pins()[size_t(bank)]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, top_module, 0, sr_head_port, + sr_head_port_info.pins()[size_t(bank)]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - sr_bank_module, sr_bank_instance, sr_module_head_port, sr_module_head_port_info.pins()[ipin]); + module_manager.add_module_net_sink( + top_module, net, sr_bank_module, sr_bank_instance, + sr_module_head_port, sr_module_head_port_info.pins()[ipin]); } } } @@ -1157,39 +1359,48 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_heads(Module /********************************************************************* * This function to add nets for QuickLogic memory bank - * We build the net connects between the tail ports of BL shift register banks + * We build the net connects between the tail ports of BL shift register banks * and the tail ports of top-level module **********************************************************************/ -static -void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_tails(ModuleManager& module_manager, - const ModuleId& top_module, - const MemoryBankShiftRegisterBanks& sr_banks) { +static void +add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_tails( + ModuleManager& module_manager, const ModuleId& top_module, + const MemoryBankShiftRegisterBanks& sr_banks) { std::string tail_port_name(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME); - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - ModulePortId sr_tail_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(tail_port_name, config_region)); - BasicPort sr_tail_port_info = module_manager.module_port(top_module, sr_tail_port); + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + ModulePortId sr_tail_port = module_manager.find_module_port( + top_module, + generate_regional_blwl_port_name(tail_port_name, config_region)); + BasicPort sr_tail_port_info = + module_manager.module_port(top_module, sr_tail_port); /* Iterate over each shift register banks */ for (const auto& bank : sr_banks.bl_banks(config_region)) { /* Get the module and instance ids */ - ModuleId sr_bank_module = sr_banks.bl_shift_register_bank_module(config_region, bank); - size_t sr_bank_instance = sr_banks.bl_shift_register_bank_instance(config_region, bank); + ModuleId sr_bank_module = + sr_banks.bl_shift_register_bank_module(config_region, bank); + size_t sr_bank_instance = + sr_banks.bl_shift_register_bank_instance(config_region, bank); VTR_ASSERT(sr_bank_module); - ModulePortId sr_module_tail_port = module_manager.find_module_port(sr_bank_module, tail_port_name); - BasicPort sr_module_tail_port_info = module_manager.module_port(sr_bank_module, sr_module_tail_port); + ModulePortId sr_module_tail_port = + module_manager.find_module_port(sr_bank_module, tail_port_name); + BasicPort sr_module_tail_port_info = + module_manager.module_port(sr_bank_module, sr_module_tail_port); VTR_ASSERT(sr_module_tail_port_info.get_width() == 1); - for (size_t ipin = 0; ipin < sr_module_tail_port_info.pins().size(); ++ipin) { + for (size_t ipin = 0; ipin < sr_module_tail_port_info.pins().size(); + ++ipin) { /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - sr_bank_module, sr_bank_instance, - sr_module_tail_port, sr_module_tail_port_info.pins()[ipin]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, sr_bank_module, sr_bank_instance, + sr_module_tail_port, sr_module_tail_port_info.pins()[ipin]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - top_module, 0, - sr_tail_port, sr_tail_port_info.pins()[size_t(bank)]); + module_manager.add_module_net_sink( + top_module, net, top_module, 0, sr_tail_port, + sr_tail_port_info.pins()[size_t(bank)]); } } } @@ -1197,191 +1408,233 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_tails(Module /********************************************************************* * This function to add nets for QuickLogic memory bank - * We build the net connects between the tail ports of WL shift register banks + * We build the net connects between the tail ports of WL shift register banks * and the tail ports of top-level module **********************************************************************/ -static -void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_tails(ModuleManager& module_manager, - const ModuleId& top_module, - const MemoryBankShiftRegisterBanks& sr_banks) { +static void +add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_tails( + ModuleManager& module_manager, const ModuleId& top_module, + const MemoryBankShiftRegisterBanks& sr_banks) { std::string tail_port_name(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME); - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - ModulePortId sr_tail_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(tail_port_name, config_region)); - BasicPort sr_tail_port_info = module_manager.module_port(top_module, sr_tail_port); + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + ModulePortId sr_tail_port = module_manager.find_module_port( + top_module, + generate_regional_blwl_port_name(tail_port_name, config_region)); + BasicPort sr_tail_port_info = + module_manager.module_port(top_module, sr_tail_port); /* Iterate over each shift register banks */ for (const auto& bank : sr_banks.wl_banks(config_region)) { /* Get the module and instance ids */ - ModuleId sr_bank_module = sr_banks.wl_shift_register_bank_module(config_region, bank); - size_t sr_bank_instance = sr_banks.wl_shift_register_bank_instance(config_region, bank); + ModuleId sr_bank_module = + sr_banks.wl_shift_register_bank_module(config_region, bank); + size_t sr_bank_instance = + sr_banks.wl_shift_register_bank_instance(config_region, bank); VTR_ASSERT(sr_bank_module); - ModulePortId sr_module_tail_port = module_manager.find_module_port(sr_bank_module, tail_port_name); - BasicPort sr_module_tail_port_info = module_manager.module_port(sr_bank_module, sr_module_tail_port); + ModulePortId sr_module_tail_port = + module_manager.find_module_port(sr_bank_module, tail_port_name); + BasicPort sr_module_tail_port_info = + module_manager.module_port(sr_bank_module, sr_module_tail_port); VTR_ASSERT(sr_module_tail_port_info.get_width() == 1); - for (size_t ipin = 0; ipin < sr_module_tail_port_info.pins().size(); ++ipin) { + for (size_t ipin = 0; ipin < sr_module_tail_port_info.pins().size(); + ++ipin) { /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - sr_bank_module, sr_bank_instance, - sr_module_tail_port, sr_module_tail_port_info.pins()[ipin]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, sr_bank_module, sr_bank_instance, + sr_module_tail_port, sr_module_tail_port_info.pins()[ipin]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - top_module, 0, - sr_tail_port, sr_tail_port_info.pins()[size_t(bank)]); + module_manager.add_module_net_sink( + top_module, net, top_module, 0, sr_tail_port, + sr_tail_port_info.pins()[size_t(bank)]); } } } } -/************************************************************** +/************************************************************** * Add BL/WL nets from shift register module to each configurable child - * BL pins of shift register module are connected to the BL input pins of each PB/CB/SB - * For all the PB/CB/SB in the same column, they share the same set of BLs - * A quick example + * BL pins of shift register module are connected to the BL input pins of each + * PB/CB/SB For all the PB/CB/SB in the same column, they share the same set of + * BLs A quick example * * +-----------------------+ * | Shift register chain | * +-----------------------+ - * BL[i .. i + sqrt(N)] + * BL[i .. i + sqrt(N)] * | * | CLB[1][H] - * | +---------+ - * | | SRAM | - * +-->| [0..N] | + * | +---------+ + * | | SRAM | + * +-->| [0..N] | * | +---------+ * | * ... * | CLB[1][1] - * | +---------+ - * | | SRAM | - * +-->| [0..N] | + * | +---------+ + * | | SRAM | + * +-->| [0..N] | * | +---------+ * | * @note optional BL/WL is applicable to WLR, which may not always exist */ -static -void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_bls(ModuleManager& module_manager, - const ModuleId& top_module, - const MemoryBankShiftRegisterBanks& sr_banks, - const std::string sr_blwl_port_name, - const std::string& child_blwl_port_name, - const bool& optional_blwl = false) { - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { +static void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_bls( + ModuleManager& module_manager, const ModuleId& top_module, + const MemoryBankShiftRegisterBanks& sr_banks, + const std::string sr_blwl_port_name, const std::string& child_blwl_port_name, + const bool& optional_blwl = false) { + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { /* Iterate over each shift register banks */ for (const auto& bank : sr_banks.bl_banks(config_region)) { /* Get the module and instance ids */ - ModuleId sr_bank_module = sr_banks.bl_shift_register_bank_module(config_region, bank); - size_t sr_bank_instance = sr_banks.bl_shift_register_bank_instance(config_region, bank); + ModuleId sr_bank_module = + sr_banks.bl_shift_register_bank_module(config_region, bank); + size_t sr_bank_instance = + sr_banks.bl_shift_register_bank_instance(config_region, bank); VTR_ASSERT(sr_bank_module); - ModulePortId sr_module_blwl_port = module_manager.find_module_port(sr_bank_module, sr_blwl_port_name); + ModulePortId sr_module_blwl_port = + module_manager.find_module_port(sr_bank_module, sr_blwl_port_name); if (!sr_module_blwl_port && optional_blwl) { continue; } VTR_ASSERT(sr_module_blwl_port); - BasicPort sr_module_blwl_port_info = module_manager.module_port(sr_bank_module, sr_module_blwl_port); + BasicPort sr_module_blwl_port_info = + module_manager.module_port(sr_bank_module, sr_module_blwl_port); - for (const BasicPort& src_port : sr_banks.bl_shift_register_bank_source_ports(config_region, bank)) { + for (const BasicPort& src_port : + sr_banks.bl_shift_register_bank_source_ports(config_region, bank)) { VTR_ASSERT(1 == src_port.get_width()); /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - sr_bank_module, sr_bank_instance, - sr_module_blwl_port, - src_port.pins()[0]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, sr_bank_module, sr_bank_instance, + sr_module_blwl_port, src_port.pins()[0]); VTR_ASSERT(ModuleNetId::INVALID() != net); - for (size_t ichild = 0; ichild < sr_banks.bl_shift_register_bank_sink_child_ids(config_region, bank, src_port).size(); ++ichild) { - size_t child_id = sr_banks.bl_shift_register_bank_sink_child_ids(config_region, bank, src_port)[ichild]; - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + for (size_t ichild = 0; + ichild < sr_banks + .bl_shift_register_bank_sink_child_ids(config_region, + bank, src_port) + .size(); + ++ichild) { + size_t child_id = sr_banks.bl_shift_register_bank_sink_child_ids( + config_region, bank, src_port)[ichild]; + ModuleId child_module = module_manager.region_configurable_children( + top_module, config_region)[child_id]; + size_t child_instance = + module_manager.region_configurable_child_instances( + top_module, config_region)[child_id]; /* Find the BL port */ - ModulePortId child_blwl_port = module_manager.find_module_port(child_module, child_blwl_port_name); - BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port); + ModulePortId child_blwl_port = + module_manager.find_module_port(child_module, child_blwl_port_name); + BasicPort child_blwl_port_info = + module_manager.module_port(child_module, child_blwl_port); /* Add net sink */ - size_t sink_child_pin_id = sr_banks.bl_shift_register_bank_sink_child_pin_ids(config_region, bank, src_port)[ichild]; - module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_blwl_port, sink_child_pin_id); + size_t sink_child_pin_id = + sr_banks.bl_shift_register_bank_sink_child_pin_ids( + config_region, bank, src_port)[ichild]; + module_manager.add_module_net_sink(top_module, net, child_module, + child_instance, child_blwl_port, + sink_child_pin_id); } } } } } - -/************************************************************** +/************************************************************** * Add BL/WL nets from shift register module to each configurable child - * BL pins of shift register module are connected to the BL input pins of each PB/CB/SB - * For all the PB/CB/SB in the same column, they share the same set of BLs - * A quick example + * BL pins of shift register module are connected to the BL input pins of each + * PB/CB/SB For all the PB/CB/SB in the same column, they share the same set of + * BLs A quick example * * +-----------------------+ * | Shift register chain | * +-----------------------+ - * BL[i .. i + sqrt(N)] + * BL[i .. i + sqrt(N)] * | * | CLB[1][H] - * | +---------+ - * | | SRAM | - * +-->| [0..N] | + * | +---------+ + * | | SRAM | + * +-->| [0..N] | * | +---------+ * | * ... * | CLB[1][1] - * | +---------+ - * | | SRAM | - * +-->| [0..N] | + * | +---------+ + * | | SRAM | + * +-->| [0..N] | * | +---------+ * | * @note optional BL/WL is applicable to WLR, which may not always exist */ -static -void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls(ModuleManager& module_manager, - const ModuleId& top_module, - const MemoryBankShiftRegisterBanks& sr_banks, - const std::string sr_blwl_port_name, - const std::string& child_blwl_port_name, - const bool& optional_blwl = false) { - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { +static void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls( + ModuleManager& module_manager, const ModuleId& top_module, + const MemoryBankShiftRegisterBanks& sr_banks, + const std::string sr_blwl_port_name, const std::string& child_blwl_port_name, + const bool& optional_blwl = false) { + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { /* Iterate over each shift register banks */ for (const auto& bank : sr_banks.wl_banks(config_region)) { /* Get the module and instance ids */ - ModuleId sr_bank_module = sr_banks.wl_shift_register_bank_module(config_region, bank); - size_t sr_bank_instance = sr_banks.wl_shift_register_bank_instance(config_region, bank); + ModuleId sr_bank_module = + sr_banks.wl_shift_register_bank_module(config_region, bank); + size_t sr_bank_instance = + sr_banks.wl_shift_register_bank_instance(config_region, bank); VTR_ASSERT(sr_bank_module); - ModulePortId sr_module_blwl_port = module_manager.find_module_port(sr_bank_module, sr_blwl_port_name); + ModulePortId sr_module_blwl_port = + module_manager.find_module_port(sr_bank_module, sr_blwl_port_name); if (!sr_module_blwl_port && optional_blwl) { continue; } VTR_ASSERT(sr_module_blwl_port); - BasicPort sr_module_blwl_port_info = module_manager.module_port(sr_bank_module, sr_module_blwl_port); + BasicPort sr_module_blwl_port_info = + module_manager.module_port(sr_bank_module, sr_module_blwl_port); - for (const BasicPort& src_port : sr_banks.wl_shift_register_bank_source_ports(config_region, bank)) { + for (const BasicPort& src_port : + sr_banks.wl_shift_register_bank_source_ports(config_region, bank)) { VTR_ASSERT(1 == src_port.get_width()); /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - sr_bank_module, sr_bank_instance, - sr_module_blwl_port, - src_port.pins()[0]); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, sr_bank_module, sr_bank_instance, + sr_module_blwl_port, src_port.pins()[0]); VTR_ASSERT(ModuleNetId::INVALID() != net); - for (size_t ichild = 0; ichild < sr_banks.wl_shift_register_bank_sink_child_ids(config_region, bank, src_port).size(); ++ichild) { - size_t child_id = sr_banks.wl_shift_register_bank_sink_child_ids(config_region, bank, src_port)[ichild]; - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + for (size_t ichild = 0; + ichild < sr_banks + .wl_shift_register_bank_sink_child_ids(config_region, + bank, src_port) + .size(); + ++ichild) { + size_t child_id = sr_banks.wl_shift_register_bank_sink_child_ids( + config_region, bank, src_port)[ichild]; + ModuleId child_module = module_manager.region_configurable_children( + top_module, config_region)[child_id]; + size_t child_instance = + module_manager.region_configurable_child_instances( + top_module, config_region)[child_id]; /* Find the BL port */ - ModulePortId child_blwl_port = module_manager.find_module_port(child_module, child_blwl_port_name); - BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port); + ModulePortId child_blwl_port = + module_manager.find_module_port(child_module, child_blwl_port_name); + BasicPort child_blwl_port_info = + module_manager.module_port(child_module, child_blwl_port); /* Add net sink */ - size_t sink_child_pin_id = sr_banks.wl_shift_register_bank_sink_child_pin_ids(config_region, bank, src_port)[ichild]; - module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_blwl_port, sink_child_pin_id); + size_t sink_child_pin_id = + sr_banks.wl_shift_register_bank_sink_child_pin_ids( + config_region, bank, src_port)[ichild]; + module_manager.add_module_net_sink(top_module, net, child_module, + child_instance, child_blwl_port, + sink_child_pin_id); } } } @@ -1389,30 +1642,34 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls(ModuleMa } /********************************************************************* - * This function to add nets for quicklogic memory banks using shift registers to manipulate BL/WLs - * Each configuration region has independent BL/WL shift register banks + * This function to add nets for quicklogic memory banks using shift registers + *to manipulate BL/WLs Each configuration region has independent BL/WL shift + *register banks * - Find the number of BLs and WLs required for each region * - Find the number of BL and WL shift register chains required for each region - * - Create the module of shift register chain for each unique size - * - Create nets to connect from top-level module inputs to BL/WL shift register chains - * - Create nets to connect from BL/WL shift register chains to BL/WL of configurable children + * - Create the module of shift register chain for each unique size + * - Create nets to connect from top-level module inputs to BL/WL shift register + *chains + * - Create nets to connect from BL/WL shift register chains to BL/WL of + *configurable children * * @note this function only adds the BL protocol * * Detailed schematic of each memory bank: - * @note The numbers are just made to show a simplified example, practical cases are more complicated! + * @note The numbers are just made to show a simplified example, practical cases + *are more complicated! * * sr_clk sr_head sr_tail * | | ^ * v v | - * +-------------------------------------------------+ + * +-------------------------------------------------+ * | Bit Line shift register chains | - * +-------------------------------------------------+ - * | | | + * +-------------------------------------------------+ + * | | | * +---------+ BL[0:9] BL[10:17] BL[18:22] - * | | | | | * | | | | | - * | Word |--WL[0:3]-->-----------+---------------+---- ... |------+--> + * | | | | | + * | Word |--WL[0:3]-->-----------+---------------+---- ... |------+--> * | | | | | | | | * | Line | | v | v | v * | | | +-------+ | +-------+ | +------+ @@ -1420,247 +1677,309 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls(ModuleMa * | | | | [0:8] | | | [0:5] | ... | | [0:7]| * | register| | +-------+ | +-------+ | +------+ * | | | | | - * | chains |--WL[4:14] -----------+--------------+--------- | -----+--> + * | chains |--WL[4:14] -----------+--------------+--------- | -----+--> * | | | | | | | | * | | | v | v | v - * | | | +-------+ | +-------+ | +-------+ - * | | +-->| SRAM | | | SRAM | +->| SRAM | - * | | | | [0:80]| | | [0:63]| ... | | [0:31]| - * | | | +-------+ | +-------+ | +-------+ - * | | | | - * | | | ... ... ... | ... - * | | | | | - * | |--WL[15:18] -----------+---------------+---- --- | -----+--> + * | | | +-------+ | +-------+ | +-------+ + * | | +-->| SRAM | | | SRAM | +->| SRAM | + * | | | | [0:80]| | | [0:63]| ... | | + *[0:31]| | | | +-------+ | +-------+ | + *+-------+ | | | | | + *| | ... ... ... | ... | | | | + *| | |--WL[15:18] -----------+---------------+---- --- | -----+--> * | | | | | | | | * | | | v | v | v - * +---------+ | +-------+ | +-------+ | +-------+ - * +-->| SRAM | +-->| SRAM | +->| SRAM | - * | |[0:5] | | | [0:8] | ... | | [0:2] | - * | +-------+ | +-------+ | +-------+ - * v v v - * WL[0:9] WL[0:7] WL[0:4] - * + * +---------+ | +-------+ | +-------+ | +-------+ + * +-->| SRAM | +-->| SRAM | +->| SRAM | + * | |[0:5] | | | [0:8] | ... | | [0:2] + *| | +-------+ | +-------+ | +-------+ v v v WL[0:9] + *WL[0:7] WL[0:4] + * **********************************************************************/ -static -void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(ModuleManager& module_manager, - MemoryBankShiftRegisterBanks& sr_banks, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol) { +static void +add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus( + ModuleManager& module_manager, MemoryBankShiftRegisterBanks& sr_banks, + const ModuleId& top_module, const CircuitLibrary& circuit_lib, + const ConfigProtocol& config_protocol) { CircuitModelId sram_model = config_protocol.memory_model(); CircuitModelId bl_memory_model = config_protocol.bl_memory_model(); /* Find out the unique shift register chain sizes */ std::vector unique_sr_sizes = sr_banks.bl_bank_unique_sizes(); - /* Build submodules for shift register chains */ + /* Build submodules for shift register chains */ for (const size_t& sr_size : unique_sr_sizes) { - std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(bl_memory_model), sr_size); - build_bl_shift_register_chain_module(module_manager, - circuit_lib, - sr_module_name, - bl_memory_model, - sr_size); + std::string sr_module_name = generate_bl_shift_register_module_name( + circuit_lib.model_name(bl_memory_model), sr_size); + build_bl_shift_register_chain_module( + module_manager, circuit_lib, sr_module_name, bl_memory_model, sr_size); } - /* Instanciate the shift register chains in the top-level module */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - for (const FabricBitLineBankId& sr_bank : sr_banks.bl_banks(config_region)) { + /* Instanciate the shift register chains in the top-level module */ + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + for (const FabricBitLineBankId& sr_bank : + sr_banks.bl_banks(config_region)) { size_t bl_bank_size = sr_banks.bl_bank_size(config_region, sr_bank); - std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(bl_memory_model), bl_bank_size); + std::string sr_module_name = generate_bl_shift_register_module_name( + circuit_lib.model_name(bl_memory_model), bl_bank_size); ModuleId sr_bank_module = module_manager.find_module(sr_module_name); VTR_ASSERT(sr_bank_module); size_t cur_inst = module_manager.num_instance(top_module, sr_bank_module); module_manager.add_child_module(top_module, sr_bank_module, false); - sr_banks.link_bl_shift_register_bank_to_module(config_region, sr_bank, sr_bank_module); - sr_banks.link_bl_shift_register_bank_to_instance(config_region, sr_bank, cur_inst); + sr_banks.link_bl_shift_register_bank_to_module(config_region, sr_bank, + sr_bank_module); + sr_banks.link_bl_shift_register_bank_to_instance(config_region, sr_bank, + cur_inst); } } - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - /************************************************************** + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric - * The distribution is a matrix which contains the starting index of BL/WL for each column or row + * The distribution is a matrix which contains the starting index of BL/WL + * for each column or row */ - std::pair child_x_range = compute_memory_bank_regional_configurable_child_x_range(module_manager, top_module, config_region); - std::map num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module, - config_region, - circuit_lib, sram_model); - std::map bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile); + std::pair child_x_range = + compute_memory_bank_regional_configurable_child_x_range( + module_manager, top_module, config_region); + std::map num_bls_per_tile = + compute_memory_bank_regional_bitline_numbers_per_tile( + module_manager, top_module, config_region, circuit_lib, sram_model); + std::map bl_start_index_per_tile = + compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, + num_bls_per_tile); - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + for (size_t child_id = 0; + child_id < + module_manager.region_configurable_children(top_module, config_region) + .size(); + ++child_id) { + ModuleId child_module = module_manager.region_configurable_children( + top_module, config_region)[child_id]; + vtr::Point coord = + module_manager.region_configurable_child_coordinates( + top_module, config_region)[child_id]; /* Find the BL port */ - ModulePortId child_bl_port = module_manager.find_module_port(child_module, std::string(MEMORY_BL_PORT_NAME)); - BasicPort child_bl_port_info = module_manager.module_port(child_module, child_bl_port); + ModulePortId child_bl_port = module_manager.find_module_port( + child_module, std::string(MEMORY_BL_PORT_NAME)); + BasicPort child_bl_port_info = + module_manager.module_port(child_module, child_bl_port); size_t cur_bl_index = 0; for (const size_t& sink_bl_pin : child_bl_port_info.pins()) { /* Find the shift register bank id for the driving BL port */ size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + cur_bl_index; - BasicPort src_bl_port(std::string(MEMORY_BL_PORT_NAME), bl_pin_id, bl_pin_id); - FabricBitLineBankId sr_bank = sr_banks.find_bl_shift_register_bank_id(config_region, src_bl_port); - BasicPort sr_bank_port = sr_banks.find_bl_shift_register_bank_data_port(config_region, src_bl_port); + BasicPort src_bl_port(std::string(MEMORY_BL_PORT_NAME), bl_pin_id, + bl_pin_id); + FabricBitLineBankId sr_bank = + sr_banks.find_bl_shift_register_bank_id(config_region, src_bl_port); + BasicPort sr_bank_port = sr_banks.find_bl_shift_register_bank_data_port( + config_region, src_bl_port); VTR_ASSERT(sr_bank_port.is_valid()); - sr_banks.add_bl_shift_register_bank_sink_node(config_region, sr_bank, sr_bank_port, child_id, sink_bl_pin); + sr_banks.add_bl_shift_register_bank_sink_node( + config_region, sr_bank, sr_bank_port, child_id, sink_bl_pin); cur_bl_index++; } } } - /* Create connections between top-level module and the BL shift register banks + /* Create connections between top-level module and the BL shift register banks * - Connect the head port from top-level module to each shift register bank * - Connect the tail port from each shift register bank to top-level module */ - add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_heads(module_manager, top_module, sr_banks); + add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_heads( + module_manager, top_module, sr_banks); - add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_tails(module_manager, top_module, sr_banks); + add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_tails( + module_manager, top_module, sr_banks); - /* Create connections between BLs of top-level module and BLs of child modules for each region */ - add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_bls(module_manager, top_module, sr_banks, - std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME), - std::string(MEMORY_BL_PORT_NAME)); + /* Create connections between BLs of top-level module and BLs of child modules + * for each region */ + add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_bls( + module_manager, top_module, sr_banks, + std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME), + std::string(MEMORY_BL_PORT_NAME)); } /********************************************************************* - * Top-level function to add nets for quicklogic memory banks using shift registers to control BL/WLs + * Top-level function to add nets for quicklogic memory banks using shift + *registers to control BL/WLs * * @note this function only adds the WL configuration bus * - * @note see detailed explanation on the bus connection in function add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus() + * @note see detailed explanation on the bus connection in function + *add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus() **********************************************************************/ -static -void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(ModuleManager& module_manager, - MemoryBankShiftRegisterBanks& sr_banks, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol) { +static void +add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus( + ModuleManager& module_manager, MemoryBankShiftRegisterBanks& sr_banks, + const ModuleId& top_module, const CircuitLibrary& circuit_lib, + const ConfigProtocol& config_protocol) { CircuitModelId sram_model = config_protocol.memory_model(); CircuitModelId wl_memory_model = config_protocol.wl_memory_model(); /* Find out the unique shift register chain sizes */ std::vector unique_sr_sizes = sr_banks.wl_bank_unique_sizes(); - /* Build submodules for shift register chains */ + /* Build submodules for shift register chains */ for (const size_t& sr_size : unique_sr_sizes) { - std::string sr_module_name = generate_wl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), sr_size); - build_wl_shift_register_chain_module(module_manager, - circuit_lib, - sr_module_name, - wl_memory_model, - sr_size); + std::string sr_module_name = generate_wl_shift_register_module_name( + circuit_lib.model_name(wl_memory_model), sr_size); + build_wl_shift_register_chain_module( + module_manager, circuit_lib, sr_module_name, wl_memory_model, sr_size); } - /* Instanciate the shift register chains in the top-level module */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - for (const FabricWordLineBankId& sr_bank : sr_banks.wl_banks(config_region)) { + /* Instanciate the shift register chains in the top-level module */ + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + for (const FabricWordLineBankId& sr_bank : + sr_banks.wl_banks(config_region)) { size_t wl_bank_size = sr_banks.wl_bank_size(config_region, sr_bank); - std::string sr_module_name = generate_wl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), wl_bank_size); + std::string sr_module_name = generate_wl_shift_register_module_name( + circuit_lib.model_name(wl_memory_model), wl_bank_size); ModuleId sr_bank_module = module_manager.find_module(sr_module_name); VTR_ASSERT(sr_bank_module); size_t cur_inst = module_manager.num_instance(top_module, sr_bank_module); module_manager.add_child_module(top_module, sr_bank_module, false); - sr_banks.link_wl_shift_register_bank_to_module(config_region, sr_bank, sr_bank_module); - sr_banks.link_wl_shift_register_bank_to_instance(config_region, sr_bank, cur_inst); + sr_banks.link_wl_shift_register_bank_to_module(config_region, sr_bank, + sr_bank_module); + sr_banks.link_wl_shift_register_bank_to_instance(config_region, sr_bank, + cur_inst); } } - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - /************************************************************** + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric - * The distribution is a matrix which contains the starting index of BL/WL for each column or row + * The distribution is a matrix which contains the starting index of BL/WL + * for each column or row */ - std::pair child_y_range = compute_memory_bank_regional_configurable_child_y_range(module_manager, top_module, config_region); - std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, - config_region, - circuit_lib, sram_model); - std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); + std::pair child_y_range = + compute_memory_bank_regional_configurable_child_y_range( + module_manager, top_module, config_region); + std::map num_wls_per_tile = + compute_memory_bank_regional_wordline_numbers_per_tile( + module_manager, top_module, config_region, circuit_lib, sram_model); + std::map wl_start_index_per_tile = + compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, + num_wls_per_tile); - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + for (size_t child_id = 0; + child_id < + module_manager.region_configurable_children(top_module, config_region) + .size(); + ++child_id) { + ModuleId child_module = module_manager.region_configurable_children( + top_module, config_region)[child_id]; + vtr::Point coord = + module_manager.region_configurable_child_coordinates( + top_module, config_region)[child_id]; size_t cur_wl_index = 0; /* Find the WL port */ - ModulePortId child_wl_port = module_manager.find_module_port(child_module, std::string(MEMORY_WL_PORT_NAME)); - BasicPort child_wl_port_info = module_manager.module_port(child_module, child_wl_port); + ModulePortId child_wl_port = module_manager.find_module_port( + child_module, std::string(MEMORY_WL_PORT_NAME)); + BasicPort child_wl_port_info = + module_manager.module_port(child_module, child_wl_port); for (const size_t& sink_wl_pin : child_wl_port_info.pins()) { size_t wl_pin_id = wl_start_index_per_tile[coord.y()] + cur_wl_index; - BasicPort src_wl_port(std::string(MEMORY_WL_PORT_NAME), wl_pin_id, wl_pin_id); + BasicPort src_wl_port(std::string(MEMORY_WL_PORT_NAME), wl_pin_id, + wl_pin_id); - FabricWordLineBankId sr_bank = sr_banks.find_wl_shift_register_bank_id(config_region, src_wl_port); - BasicPort sr_bank_port = sr_banks.find_wl_shift_register_bank_data_port(config_region, src_wl_port); + FabricWordLineBankId sr_bank = + sr_banks.find_wl_shift_register_bank_id(config_region, src_wl_port); + BasicPort sr_bank_port = sr_banks.find_wl_shift_register_bank_data_port( + config_region, src_wl_port); VTR_ASSERT(sr_bank_port.is_valid()); - sr_banks.add_wl_shift_register_bank_sink_node(config_region, sr_bank, sr_bank_port, child_id, sink_wl_pin); + sr_banks.add_wl_shift_register_bank_sink_node( + config_region, sr_bank, sr_bank_port, child_id, sink_wl_pin); cur_wl_index++; } } } - /* Create connections between top-level module and the BL shift register banks + /* Create connections between top-level module and the BL shift register banks * - Connect the head port from top-level module to each shift register bank * - Connect the tail port from each shift register bank to top-level module */ - add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_heads(module_manager, top_module, sr_banks); + add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_heads( + module_manager, top_module, sr_banks); - add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_tails(module_manager, top_module, sr_banks); + add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_tails( + module_manager, top_module, sr_banks); - /* Create connections between BLs of top-level module and BLs of child modules for each region */ - add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls(module_manager, top_module, sr_banks, - std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME), - std::string(MEMORY_WL_PORT_NAME)); - add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls(module_manager, top_module, sr_banks, - std::string(WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME), - std::string(MEMORY_WLR_PORT_NAME), - true); + /* Create connections between BLs of top-level module and BLs of child modules + * for each region */ + add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls( + module_manager, top_module, sr_banks, + std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME), + std::string(MEMORY_WL_PORT_NAME)); + add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls( + module_manager, top_module, sr_banks, + std::string(WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME), + std::string(MEMORY_WLR_PORT_NAME), true); } /********************************************************************* * Top-level function to add nets for quicklogic memory banks * - Each configuration region has independent memory bank circuitry - * - BL and WL may have different circuitry and wire connection, e.g., decoder, flatten or shift-registers + * - BL and WL may have different circuitry and wire connection, e.g., decoder, + *flatten or shift-registers * - BL control circuitry - * - Decoder: Add a BL decoder; Connect enable, address and data-in (din) between top-level and decoders; Connect data ports between between the decoder and configurable child modules - * - Flatten: Connect BLs between the top-level port and configurable child modules - * - TODO: Shift registers: add blocks of shift register chain (could be multi-head); Connect shift register outputs to configurable child modules + * - Decoder: Add a BL decoder; Connect enable, address and data-in (din) + *between top-level and decoders; Connect data ports between between the decoder + *and configurable child modules + * - Flatten: Connect BLs between the top-level port and configurable child + *modules + * - TODO: Shift registers: add blocks of shift register chain (could be + *multi-head); Connect shift register outputs to configurable child modules * * - WL control circuitry - * - Decoder: Add a WL decoder; Connect address ports between top-level and decoders; Connect data ports between the decoder and configurable child modules - * - Flatten: Connect BLs between the top-level port and configurable child modules - * - TODO: Shift registers: add blocks of shift register chain (could be multi-head); Connect shift register outputs to configurable child modules + * - Decoder: Add a WL decoder; Connect address ports between top-level and + *decoders; Connect data ports between the decoder and configurable child + *modules + * - Flatten: Connect BLs between the top-level port and configurable child + *modules + * - TODO: Shift registers: add blocks of shift register chain (could be + *multi-head); Connect shift register outputs to configurable child modules ********************************************************************/ -void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - MemoryBankShiftRegisterBanks& blwl_sr_banks, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const TopModuleNumConfigBits& num_config_bits) { +void add_top_module_nets_cmos_ql_memory_bank_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const TopModuleNumConfigBits& num_config_bits) { VTR_ASSERT_SAFE(CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()); CircuitModelId sram_model = config_protocol.memory_model(); switch (config_protocol.bl_protocol_type()) { case BLWL_PROTOCOL_DECODER: { - add_top_module_nets_cmos_ql_memory_bank_bl_decoder_config_bus(module_manager, decoder_lib, top_module, circuit_lib, sram_model, num_config_bits); + add_top_module_nets_cmos_ql_memory_bank_bl_decoder_config_bus( + module_manager, decoder_lib, top_module, circuit_lib, sram_model, + num_config_bits); break; } case BLWL_PROTOCOL_FLATTEN: { - add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus(module_manager, top_module, circuit_lib, sram_model); + add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus( + module_manager, top_module, circuit_lib, sram_model); break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { - add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(module_manager, blwl_sr_banks, top_module, circuit_lib, config_protocol); + add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus( + module_manager, blwl_sr_banks, top_module, circuit_lib, + config_protocol); break; } default: { @@ -1671,15 +1990,20 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma switch (config_protocol.wl_protocol_type()) { case BLWL_PROTOCOL_DECODER: { - add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(module_manager, decoder_lib, top_module, circuit_lib, sram_model, num_config_bits); + add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus( + module_manager, decoder_lib, top_module, circuit_lib, sram_model, + num_config_bits); break; } case BLWL_PROTOCOL_FLATTEN: { - add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus(module_manager, top_module, circuit_lib, sram_model); + add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus( + module_manager, top_module, circuit_lib, sram_model); break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { - add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(module_manager, blwl_sr_banks, top_module, circuit_lib, config_protocol); + add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus( + module_manager, blwl_sr_banks, top_module, circuit_lib, + config_protocol); break; } default: { @@ -1690,7 +2014,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma } /******************************************************************** - * Add a list of ports that are used for SRAM configuration to the FPGA + * Add a list of ports that are used for SRAM configuration to the FPGA * top-level module * - Add ports for BL control circuitry: * - Decoder @@ -1715,14 +2039,14 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma * - Tail of shift register chain for WLs * - a Readback port (Optional, only needed when WLR is required) * - * @note In this memory decoders, the address size will be computed in a different way than the regular one + * @note In this memory decoders, the address size will be computed in a + *different way than the regular one ********************************************************************/ -void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const TopModuleNumConfigBits& num_config_bits) { +void add_top_module_ql_memory_bank_sram_ports( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const TopModuleNumConfigBits& num_config_bits) { VTR_ASSERT_SAFE(CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()); CircuitModelId sram_model = config_protocol.memory_model(); @@ -1730,38 +2054,59 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, case BLWL_PROTOCOL_DECODER: { /* Add enable signals */ BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); - module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(module_id, en_port, + ModuleManager::MODULE_INPUT_PORT); /* BL address size is the largest among all the regions */ size_t bl_addr_size = 0; - for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - bl_addr_size = std::max(bl_addr_size, find_mux_local_decoder_addr_size(num_config_bits[config_region].first)); + for (const ConfigRegionId& config_region : + module_manager.regions(module_id)) { + bl_addr_size = + std::max(bl_addr_size, find_mux_local_decoder_addr_size( + num_config_bits[config_region].first)); } - BasicPort bl_addr_port(std::string(DECODER_BL_ADDRESS_PORT_NAME), bl_addr_size); - module_manager.add_port(module_id, bl_addr_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort bl_addr_port(std::string(DECODER_BL_ADDRESS_PORT_NAME), + bl_addr_size); + module_manager.add_port(module_id, bl_addr_port, + ModuleManager::MODULE_INPUT_PORT); /* Data input should be dependent on the number of configuration regions*/ - BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), config_protocol.num_regions()); - module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), + config_protocol.num_regions()); + module_manager.add_port(module_id, din_port, + ModuleManager::MODULE_INPUT_PORT); break; } case BLWL_PROTOCOL_FLATTEN: { /* Each region will have independent BLs */ - for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { + for (const ConfigRegionId& config_region : + module_manager.regions(module_id)) { size_t bl_size = num_config_bits[config_region].first; - BasicPort bl_port(generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), config_region), bl_size); - module_manager.add_port(module_id, bl_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort bl_port(generate_regional_blwl_port_name( + std::string(MEMORY_BL_PORT_NAME), config_region), + bl_size); + module_manager.add_port(module_id, bl_port, + ModuleManager::MODULE_INPUT_PORT); } break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { /* Each region will have independent shift register banks */ - for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { + for (const ConfigRegionId& config_region : + module_manager.regions(module_id)) { size_t num_heads = blwl_sr_banks.bl_banks(config_region).size(); - BasicPort blsr_head_port(generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region), num_heads); - module_manager.add_port(module_id, blsr_head_port, ModuleManager::MODULE_INPUT_PORT); - BasicPort blsr_tail_port(generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region), num_heads); - module_manager.add_port(module_id, blsr_tail_port, ModuleManager::MODULE_OUTPUT_PORT); + BasicPort blsr_head_port( + generate_regional_blwl_port_name( + std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region), + num_heads); + module_manager.add_port(module_id, blsr_head_port, + ModuleManager::MODULE_INPUT_PORT); + BasicPort blsr_tail_port( + generate_regional_blwl_port_name( + std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region), + num_heads); + module_manager.add_port(module_id, blsr_tail_port, + ModuleManager::MODULE_OUTPUT_PORT); } break; } @@ -1775,42 +2120,68 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, case BLWL_PROTOCOL_DECODER: { /* WL address size is the largest among all the regions */ size_t wl_addr_size = 0; - for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - wl_addr_size = std::max(wl_addr_size, find_mux_local_decoder_addr_size(num_config_bits[config_region].second)); + for (const ConfigRegionId& config_region : + module_manager.regions(module_id)) { + wl_addr_size = + std::max(wl_addr_size, find_mux_local_decoder_addr_size( + num_config_bits[config_region].second)); } - BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size); - module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), + wl_addr_size); + module_manager.add_port(module_id, wl_addr_port, + ModuleManager::MODULE_INPUT_PORT); /* Optional: If we have WLR port, we should add a read-back port */ - if (!circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR).empty()) { - BasicPort readback_port(std::string(DECODER_READBACK_PORT_NAME), config_protocol.num_regions()); - module_manager.add_port(module_id, readback_port, ModuleManager::MODULE_INPUT_PORT); + if (!circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR) + .empty()) { + BasicPort readback_port(std::string(DECODER_READBACK_PORT_NAME), + config_protocol.num_regions()); + module_manager.add_port(module_id, readback_port, + ModuleManager::MODULE_INPUT_PORT); } break; } case BLWL_PROTOCOL_FLATTEN: { /* Each region will have independent WLs */ - for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { + for (const ConfigRegionId& config_region : + module_manager.regions(module_id)) { size_t wl_size = num_config_bits[config_region].second; - BasicPort wl_port(generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region), wl_size); - module_manager.add_port(module_id, wl_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort wl_port(generate_regional_blwl_port_name( + std::string(MEMORY_WL_PORT_NAME), config_region), + wl_size); + module_manager.add_port(module_id, wl_port, + ModuleManager::MODULE_INPUT_PORT); /* Optional: If we have WLR port, we should add a read-back port */ - if (!circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR).empty()) { - BasicPort wlr_port(generate_regional_blwl_port_name(std::string(MEMORY_WLR_PORT_NAME), config_region), wl_size); - module_manager.add_port(module_id, wlr_port, ModuleManager::MODULE_INPUT_PORT); + if (!circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR) + .empty()) { + BasicPort wlr_port( + generate_regional_blwl_port_name(std::string(MEMORY_WLR_PORT_NAME), + config_region), + wl_size); + module_manager.add_port(module_id, wlr_port, + ModuleManager::MODULE_INPUT_PORT); } } break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { /* Each region will have independent shift register banks */ - for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { + for (const ConfigRegionId& config_region : + module_manager.regions(module_id)) { size_t num_heads = blwl_sr_banks.wl_banks(config_region).size(); - BasicPort wlsr_head_port(generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region), num_heads); - module_manager.add_port(module_id, wlsr_head_port, ModuleManager::MODULE_INPUT_PORT); - BasicPort wlsr_tail_port(generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region), num_heads); - module_manager.add_port(module_id, wlsr_tail_port, ModuleManager::MODULE_OUTPUT_PORT); + BasicPort wlsr_head_port( + generate_regional_blwl_port_name( + std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region), + num_heads); + module_manager.add_port(module_id, wlsr_head_port, + ModuleManager::MODULE_INPUT_PORT); + BasicPort wlsr_tail_port( + generate_regional_blwl_port_name( + std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region), + num_heads); + module_manager.add_port(module_id, wlsr_tail_port, + ModuleManager::MODULE_OUTPUT_PORT); } break; } @@ -1822,31 +2193,39 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, } /******************************************************************** - * Load the shift register bank -related data from fabric key to - * the dedicated and unified data structure + * Load the shift register bank -related data from fabric key to + * the dedicated and unified data structure ********************************************************************/ -int load_top_module_shift_register_banks_from_fabric_key(const FabricKey& fabric_key, - MemoryBankShiftRegisterBanks& blwl_sr_banks) { +int load_top_module_shift_register_banks_from_fabric_key( + const FabricKey& fabric_key, MemoryBankShiftRegisterBanks& blwl_sr_banks) { blwl_sr_banks.resize_regions(fabric_key.regions().size()); /* Load Bit-Line shift register banks */ for (const auto& region : fabric_key.regions()) { - blwl_sr_banks.reserve_bl_shift_register_banks(region, fabric_key.bl_banks(region).size()); + blwl_sr_banks.reserve_bl_shift_register_banks( + region, fabric_key.bl_banks(region).size()); for (const auto& bank : fabric_key.bl_banks(region)) { - FabricBitLineBankId sr_bank = blwl_sr_banks.create_bl_shift_register_bank(region); - for (const auto& data_port : fabric_key.bl_bank_data_ports(region, bank)) { - blwl_sr_banks.add_data_port_to_bl_shift_register_bank(region, sr_bank, data_port); + FabricBitLineBankId sr_bank = + blwl_sr_banks.create_bl_shift_register_bank(region); + for (const auto& data_port : + fabric_key.bl_bank_data_ports(region, bank)) { + blwl_sr_banks.add_data_port_to_bl_shift_register_bank(region, sr_bank, + data_port); } } } /* Load Bit-Line shift register banks */ for (const auto& region : fabric_key.regions()) { - blwl_sr_banks.reserve_wl_shift_register_banks(region, fabric_key.wl_banks(region).size()); + blwl_sr_banks.reserve_wl_shift_register_banks( + region, fabric_key.wl_banks(region).size()); for (const auto& bank : fabric_key.wl_banks(region)) { - FabricWordLineBankId sr_bank = blwl_sr_banks.create_wl_shift_register_bank(region); - for (const auto& data_port : fabric_key.wl_bank_data_ports(region, bank)) { - blwl_sr_banks.add_data_port_to_wl_shift_register_bank(region, sr_bank, data_port); + FabricWordLineBankId sr_bank = + blwl_sr_banks.create_wl_shift_register_bank(region); + for (const auto& data_port : + fabric_key.wl_bank_data_ports(region, bank)) { + blwl_sr_banks.add_data_port_to_wl_shift_register_bank(region, sr_bank, + data_port); } } } @@ -1855,37 +2234,41 @@ int load_top_module_shift_register_banks_from_fabric_key(const FabricKey& fabric } /******************************************************************** - * @brief This functions synchronize the settings in configuration protocol (from architecture description) - * and the existing information (loaded from fabric key files) - * @note This function should be called AFTER load_top_module_shift_register_banks_from_fabric_key() + * @brief This functions synchronize the settings in configuration protocol + *(from architecture description) and the existing information (loaded from + *fabric key files) + * @note This function should be called AFTER + *load_top_module_shift_register_banks_from_fabric_key() ********************************************************************/ -void sync_memory_bank_shift_register_banks_with_config_protocol_settings(ModuleManager& module_manager, - MemoryBankShiftRegisterBanks& blwl_sr_banks, - const ConfigProtocol& config_protocol, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib) { - /* ONLY synchronize when the configuration protocol is memory bank using shift registers */ - if ( CONFIG_MEM_QL_MEMORY_BANK != config_protocol.type() - || BLWL_PROTOCOL_SHIFT_REGISTER != config_protocol.bl_protocol_type() - || BLWL_PROTOCOL_SHIFT_REGISTER != config_protocol.wl_protocol_type() ) { +void sync_memory_bank_shift_register_banks_with_config_protocol_settings( + ModuleManager& module_manager, MemoryBankShiftRegisterBanks& blwl_sr_banks, + const ConfigProtocol& config_protocol, const ModuleId& top_module, + const CircuitLibrary& circuit_lib) { + /* ONLY synchronize when the configuration protocol is memory bank using shift + * registers */ + if (CONFIG_MEM_QL_MEMORY_BANK != config_protocol.type() || + BLWL_PROTOCOL_SHIFT_REGISTER != config_protocol.bl_protocol_type() || + BLWL_PROTOCOL_SHIFT_REGISTER != config_protocol.wl_protocol_type()) { return; } - /* Fabric key has a higher priority in defining the shift register bank organization */ + /* Fabric key has a higher priority in defining the shift register bank + * organization */ if (!blwl_sr_banks.empty()) { return; } CircuitModelId sram_model = config_protocol.memory_model(); - /* Reach here, if means we do not have any definition from fabric key files, use the settings from the configuration protocol */ + /* Reach here, if means we do not have any definition from fabric key files, + * use the settings from the configuration protocol */ blwl_sr_banks.resize_regions(module_manager.regions(top_module).size()); - /* Based on the number of shift register banks, evenly distribute the BLs in each region for each shift register bank */ + /* Based on the number of shift register banks, evenly distribute the BLs in + * each region for each shift register bank */ for (const auto& config_region : module_manager.regions(top_module)) { - size_t num_bls = compute_memory_bank_regional_num_bls(module_manager, top_module, - config_region, - circuit_lib, sram_model); + size_t num_bls = compute_memory_bank_regional_num_bls( + module_manager, top_module, config_region, circuit_lib, sram_model); size_t num_bl_banks = config_protocol.bl_num_banks(); blwl_sr_banks.reserve_bl_shift_register_banks(config_region, num_bl_banks); @@ -1895,13 +2278,16 @@ void sync_memory_bank_shift_register_banks_with_config_protocol_settings(ModuleM /* For last bank, use all the residual sizes */ size_t cur_sr_bank_size = regular_sr_bank_size; if (ibank == num_bl_banks - 1) { - cur_sr_bank_size = num_bls - ibank * regular_sr_bank_size; + cur_sr_bank_size = num_bls - ibank * regular_sr_bank_size; } /* Create a bank and assign data ports */ - FabricBitLineBankId bank = blwl_sr_banks.create_bl_shift_register_bank(config_region); - BasicPort data_ports(std::string(MEMORY_BL_PORT_NAME), cur_bl_index, cur_bl_index + cur_sr_bank_size - 1); - blwl_sr_banks.add_data_port_to_bl_shift_register_bank(config_region, bank, data_ports); - + FabricBitLineBankId bank = + blwl_sr_banks.create_bl_shift_register_bank(config_region); + BasicPort data_ports(std::string(MEMORY_BL_PORT_NAME), cur_bl_index, + cur_bl_index + cur_sr_bank_size - 1); + blwl_sr_banks.add_data_port_to_bl_shift_register_bank(config_region, bank, + data_ports); + /* Increment the bl index */ cur_bl_index += cur_sr_bank_size; } @@ -1909,11 +2295,11 @@ void sync_memory_bank_shift_register_banks_with_config_protocol_settings(ModuleM VTR_ASSERT(cur_bl_index == num_bls); } - /* Based on the number of shift register banks, evenly distribute the WLs in each region for each shift register bank */ + /* Based on the number of shift register banks, evenly distribute the WLs in + * each region for each shift register bank */ for (const auto& config_region : module_manager.regions(top_module)) { - size_t num_wls = compute_memory_bank_regional_num_wls(module_manager, top_module, - config_region, - circuit_lib, sram_model); + size_t num_wls = compute_memory_bank_regional_num_wls( + module_manager, top_module, config_region, circuit_lib, sram_model); size_t num_wl_banks = config_protocol.wl_num_banks(); blwl_sr_banks.reserve_wl_shift_register_banks(config_region, num_wl_banks); @@ -1923,13 +2309,16 @@ void sync_memory_bank_shift_register_banks_with_config_protocol_settings(ModuleM /* For last bank, use all the residual sizes */ size_t cur_sr_bank_size = regular_sr_bank_size; if (ibank == num_wl_banks - 1) { - cur_sr_bank_size = num_wls - ibank * regular_sr_bank_size; + cur_sr_bank_size = num_wls - ibank * regular_sr_bank_size; } /* Create a bank and assign data ports */ - FabricWordLineBankId bank = blwl_sr_banks.create_wl_shift_register_bank(config_region); - BasicPort data_ports(std::string(MEMORY_WL_PORT_NAME), cur_wl_index, cur_wl_index + cur_sr_bank_size - 1); - blwl_sr_banks.add_data_port_to_wl_shift_register_bank(config_region, bank, data_ports); - + FabricWordLineBankId bank = + blwl_sr_banks.create_wl_shift_register_bank(config_region); + BasicPort data_ports(std::string(MEMORY_WL_PORT_NAME), cur_wl_index, + cur_wl_index + cur_sr_bank_size - 1); + blwl_sr_banks.add_data_port_to_wl_shift_register_bank(config_region, bank, + data_ports); + /* Increment the bl index */ cur_wl_index += cur_sr_bank_size; } diff --git a/openfpga/src/fabric/build_top_module_memory_bank.h b/openfpga/src/fabric/build_top_module_memory_bank.h index 3d76ec3f4..ba94448e1 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.h +++ b/openfpga/src/fabric/build_top_module_memory_bank.h @@ -5,17 +5,18 @@ * Include header files that are required by function declaration *******************************************************************/ -#include -#include #include -#include "vtr_vector.h" -#include "vtr_ndmatrix.h" -#include "module_manager.h" -#include "config_protocol.h" +#include +#include + +#include "build_top_module_memory_utils.h" #include "circuit_library.h" +#include "config_protocol.h" #include "decoder_library.h" #include "memory_bank_shift_register_banks.h" -#include "build_top_module_memory_utils.h" +#include "module_manager.h" +#include "vtr_ndmatrix.h" +#include "vtr_vector.h" /******************************************************************** * Function declaration @@ -24,29 +25,25 @@ /* begin namespace openfpga */ namespace openfpga { -void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - MemoryBankShiftRegisterBanks& blwl_sr_banks, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const TopModuleNumConfigBits& num_config_bits); +void add_top_module_nets_cmos_ql_memory_bank_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const TopModuleNumConfigBits& num_config_bits); -void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const TopModuleNumConfigBits& num_config_bits); +void add_top_module_ql_memory_bank_sram_ports( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const TopModuleNumConfigBits& num_config_bits); -int load_top_module_shift_register_banks_from_fabric_key(const FabricKey& fabric_key, - MemoryBankShiftRegisterBanks& blwl_sr_banks); +int load_top_module_shift_register_banks_from_fabric_key( + const FabricKey& fabric_key, MemoryBankShiftRegisterBanks& blwl_sr_banks); -void sync_memory_bank_shift_register_banks_with_config_protocol_settings(ModuleManager& module_manager, - MemoryBankShiftRegisterBanks& blwl_sr_banks, - const ConfigProtocol& config_protocol, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib); +void sync_memory_bank_shift_register_banks_with_config_protocol_settings( + ModuleManager& module_manager, MemoryBankShiftRegisterBanks& blwl_sr_banks, + const ConfigProtocol& config_protocol, const ModuleId& top_module, + const CircuitLibrary& circuit_lib); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_memory_utils.h b/openfpga/src/fabric/build_top_module_memory_utils.h index 235f54055..d4a9adcf4 100644 --- a/openfpga/src/fabric/build_top_module_memory_utils.h +++ b/openfpga/src/fabric/build_top_module_memory_utils.h @@ -5,8 +5,9 @@ * Include header files that are required by function declaration *******************************************************************/ -#include #include +#include + #include "vtr_vector.h" /******************************************************************** @@ -16,12 +17,13 @@ /* begin namespace openfpga */ namespace openfpga { -/* A data structure to store the number of configuration bits for each configurable region - * of the top-level module. - * For different configuration protocol, the std::pair represents different data - * See details in each function about how the data is organized +/* A data structure to store the number of configuration bits for each + * configurable region of the top-level module. For different configuration + * protocol, the std::pair represents different data See details + * in each function about how the data is organized */ -typedef vtr::vector> TopModuleNumConfigBits; +typedef vtr::vector> + TopModuleNumConfigBits; } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_utils.cpp b/openfpga/src/fabric/build_top_module_utils.cpp index 141d2dd54..c4405623a 100644 --- a/openfpga/src/fabric/build_top_module_utils.cpp +++ b/openfpga/src/fabric/build_top_module_utils.cpp @@ -1,14 +1,13 @@ /******************************************************************** - * This file include most utilized functions for building the module + * This file include most utilized functions for building the module * graph for FPGA fabric *******************************************************************/ /* Headers from vtrutil library */ #include "vtr_assert.h" /* Headers from vpr library */ -#include "vpr_utils.h" - #include "openfpga_naming.h" +#include "vpr_utils.h" /* Module builder headers */ #include "build_top_module_utils.h" @@ -20,24 +19,23 @@ namespace openfpga { * Generate the name for a grid block, by considering * 1. if it locates on the border with given device size * 2. its type - * + * * This function is mainly used in the top-level module generation *******************************************************************/ -std::string generate_grid_block_module_name_in_top_module(const std::string& prefix, - const DeviceGrid& grids, - const vtr::Point& grid_coord) { +std::string generate_grid_block_module_name_in_top_module( + const std::string& prefix, const DeviceGrid& grids, + const vtr::Point& grid_coord) { /* Determine if the grid locates at the border */ vtr::Point device_size(grids.width(), grids.height()); e_side border_side = find_grid_border_side(device_size, grid_coord); - return generate_grid_block_module_name(prefix, - std::string(grids[grid_coord.x()][grid_coord.y()].type->name), - is_io_type(grids[grid_coord.x()][grid_coord.y()].type), - border_side); + return generate_grid_block_module_name( + prefix, std::string(grids[grid_coord.x()][grid_coord.y()].type->name), + is_io_type(grids[grid_coord.x()][grid_coord.y()].type), border_side); } /******************************************************************** - * Find the cb_type of a GSB in the top-level module + * Find the cb_type of a GSB in the top-level module * depending on the side of SB * TOP/BOTTOM side: CHANY * RIGHT/LEFT side: CHANX @@ -54,34 +52,34 @@ t_rr_type find_top_module_cb_type_by_sb_side(const e_side& sb_side) { } /******************************************************************** - * Find the GSB coordinate for a CB in the top-level module + * Find the GSB coordinate for a CB in the top-level module * depending on the side of a SB * TODO: use vtr::Point to replace DeviceCoordinator *******************************************************************/ -vtr::Point find_top_module_gsb_coordinate_by_sb_side(const RRGSB& rr_gsb, - const e_side& sb_side) { +vtr::Point find_top_module_gsb_coordinate_by_sb_side( + const RRGSB& rr_gsb, const e_side& sb_side) { VTR_ASSERT(NUM_SIDES != sb_side); vtr::Point gsb_coordinate; if ((TOP == sb_side) || (LEFT == sb_side)) { - gsb_coordinate.set_x(rr_gsb.get_x()); - gsb_coordinate.set_y(rr_gsb.get_y()); + gsb_coordinate.set_x(rr_gsb.get_x()); + gsb_coordinate.set_y(rr_gsb.get_y()); return gsb_coordinate; } - + VTR_ASSERT((RIGHT == sb_side) || (BOTTOM == sb_side)); /* RIGHT side: x + 1 */ if (RIGHT == sb_side) { - gsb_coordinate.set_x(rr_gsb.get_x() + 1); - gsb_coordinate.set_y(rr_gsb.get_y()); + gsb_coordinate.set_x(rr_gsb.get_x() + 1); + gsb_coordinate.set_y(rr_gsb.get_y()); } /* BOTTOM side: y - 1 */ if (BOTTOM == sb_side) { - gsb_coordinate.set_x(rr_gsb.get_x()); - gsb_coordinate.set_y(rr_gsb.get_y() - 1); + gsb_coordinate.set_x(rr_gsb.get_x()); + gsb_coordinate.set_y(rr_gsb.get_y() - 1); } return gsb_coordinate; diff --git a/openfpga/src/fabric/build_top_module_utils.h b/openfpga/src/fabric/build_top_module_utils.h index c0bcbcee5..394a3408a 100644 --- a/openfpga/src/fabric/build_top_module_utils.h +++ b/openfpga/src/fabric/build_top_module_utils.h @@ -4,11 +4,12 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include #include -#include "vtr_geometry.h" +#include + #include "device_grid.h" #include "rr_gsb.h" +#include "vtr_geometry.h" /******************************************************************** * Function declaration @@ -17,14 +18,14 @@ /* begin namespace openfpga */ namespace openfpga { -std::string generate_grid_block_module_name_in_top_module(const std::string& prefix, - const DeviceGrid& grids, - const vtr::Point& grid_coord); +std::string generate_grid_block_module_name_in_top_module( + const std::string& prefix, const DeviceGrid& grids, + const vtr::Point& grid_coord); t_rr_type find_top_module_cb_type_by_sb_side(const e_side& sb_side); -vtr::Point find_top_module_gsb_coordinate_by_sb_side(const RRGSB& rr_gsb, - const e_side& sb_side); +vtr::Point find_top_module_gsb_coordinate_by_sb_side( + const RRGSB& rr_gsb, const e_side& sb_side); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_wire_modules.cpp b/openfpga/src/fabric/build_wire_modules.cpp index d505f93e6..9e7ec1fe7 100644 --- a/openfpga/src/fabric/build_wire_modules.cpp +++ b/openfpga/src/fabric/build_wire_modules.cpp @@ -2,22 +2,20 @@ * This file includes functions to generate * Verilog submodules for wires. **********************************************/ -#include #include +#include /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Device-level header files */ +#include "build_wire_modules.h" #include "module_manager.h" #include "module_manager_utils.h" - #include "openfpga_naming.h" -#include "build_wire_modules.h" - /* begin namespace openfpga */ namespace openfpga { @@ -30,29 +28,33 @@ namespace openfpga { * +------+ * *******************************************************************/ -static -void build_wire_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const CircuitModelId& wire_model) { +static void build_wire_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const CircuitModelId& wire_model) { /* Find the input port, output port*/ - std::vector input_ports = circuit_lib.model_ports_by_type(wire_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(wire_model, CIRCUIT_MODEL_PORT_OUTPUT, true); - std::vector global_ports = circuit_lib.model_global_ports_by_type(wire_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector input_ports = + circuit_lib.model_ports_by_type(wire_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + wire_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector global_ports = + circuit_lib.model_global_ports_by_type(wire_model, CIRCUIT_MODEL_PORT_INPUT, + true, true); /* Makre sure the port size is what we want */ - VTR_ASSERT (1 == input_ports.size()); - VTR_ASSERT (1 == output_ports.size()); - VTR_ASSERT (1 == circuit_lib.port_size(input_ports[0])); - VTR_ASSERT (1 == circuit_lib.port_size(output_ports[0])); + VTR_ASSERT(1 == input_ports.size()); + VTR_ASSERT(1 == output_ports.size()); + VTR_ASSERT(1 == circuit_lib.port_size(input_ports[0])); + VTR_ASSERT(1 == circuit_lib.port_size(output_ports[0])); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - add_circuit_model_to_module_manager(module_manager, circuit_lib, wire_model); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + add_circuit_model_to_module_manager(module_manager, circuit_lib, wire_model); } /******************************************************************** - * This function will only create wire modules with a number of + * This function will only create wire modules with a number of * ports that are defined by users. - * It will NOT insert any internal logic, which should be handled + * It will NOT insert any internal logic, which should be handled * by Verilog/SPICE writers *******************************************************************/ void build_wire_modules(ModuleManager& module_manager, @@ -60,10 +62,11 @@ void build_wire_modules(ModuleManager& module_manager, vtr::ScopedStartFinishTimer timer("Build wire modules"); /* Print Verilog models for regular wires*/ - for (const auto& wire_model : circuit_lib.models_by_type(CIRCUIT_MODEL_WIRE)) { + for (const auto& wire_model : + circuit_lib.models_by_type(CIRCUIT_MODEL_WIRE)) { /* Bypass user-defined circuit models */ - if ( (!circuit_lib.model_spice_netlist(wire_model).empty()) - && (!circuit_lib.model_verilog_netlist(wire_model).empty()) ) { + if ((!circuit_lib.model_spice_netlist(wire_model).empty()) && + (!circuit_lib.model_verilog_netlist(wire_model).empty())) { continue; } build_wire_module(module_manager, circuit_lib, wire_model); diff --git a/openfpga/src/fabric/fabric_global_port_info.cpp b/openfpga/src/fabric/fabric_global_port_info.cpp index 18108597d..eb8a299bb 100644 --- a/openfpga/src/fabric/fabric_global_port_info.cpp +++ b/openfpga/src/fabric/fabric_global_port_info.cpp @@ -1,81 +1,91 @@ /************************************************************************ * Member functions for class FabricGlobalPortInfo ***********************************************************************/ -#include "vtr_assert.h" - #include "fabric_global_port_info.h" +#include "vtr_assert.h" + /* namespace openfpga begins */ namespace openfpga { /************************************************************************ * Constructors ***********************************************************************/ -FabricGlobalPortInfo::FabricGlobalPortInfo() { - return; -} +FabricGlobalPortInfo::FabricGlobalPortInfo() { return; } /************************************************************************ * Public Accessors : aggregates ***********************************************************************/ -FabricGlobalPortInfo::global_port_range FabricGlobalPortInfo::global_ports() const { +FabricGlobalPortInfo::global_port_range FabricGlobalPortInfo::global_ports() + const { return vtr::make_range(global_port_ids_.begin(), global_port_ids_.end()); } /************************************************************************ * Public Accessors ***********************************************************************/ -ModulePortId FabricGlobalPortInfo::global_module_port(const FabricGlobalPortId& global_port_id) const { +ModulePortId FabricGlobalPortInfo::global_module_port( + const FabricGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_module_ports_[global_port_id]; } -bool FabricGlobalPortInfo::global_port_is_clock(const FabricGlobalPortId& global_port_id) const { +bool FabricGlobalPortInfo::global_port_is_clock( + const FabricGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_is_clock_[global_port_id]; } -bool FabricGlobalPortInfo::global_port_is_set(const FabricGlobalPortId& global_port_id) const { +bool FabricGlobalPortInfo::global_port_is_set( + const FabricGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_is_set_[global_port_id]; } -bool FabricGlobalPortInfo::global_port_is_reset(const FabricGlobalPortId& global_port_id) const { +bool FabricGlobalPortInfo::global_port_is_reset( + const FabricGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_is_reset_[global_port_id]; } -bool FabricGlobalPortInfo::global_port_is_prog(const FabricGlobalPortId& global_port_id) const { +bool FabricGlobalPortInfo::global_port_is_prog( + const FabricGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_is_prog_[global_port_id]; } -bool FabricGlobalPortInfo::global_port_is_shift_register(const FabricGlobalPortId& global_port_id) const { +bool FabricGlobalPortInfo::global_port_is_shift_register( + const FabricGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_is_shift_register_[global_port_id]; } -bool FabricGlobalPortInfo::global_port_is_bl(const FabricGlobalPortId& global_port_id) const { +bool FabricGlobalPortInfo::global_port_is_bl( + const FabricGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_is_bl_[global_port_id]; } -bool FabricGlobalPortInfo::global_port_is_wl(const FabricGlobalPortId& global_port_id) const { +bool FabricGlobalPortInfo::global_port_is_wl( + const FabricGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_is_wl_[global_port_id]; } -bool FabricGlobalPortInfo::global_port_is_config_enable(const FabricGlobalPortId& global_port_id) const { +bool FabricGlobalPortInfo::global_port_is_config_enable( + const FabricGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_is_config_enable_[global_port_id]; } -bool FabricGlobalPortInfo::global_port_is_io(const FabricGlobalPortId& global_port_id) const { +bool FabricGlobalPortInfo::global_port_is_io( + const FabricGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_is_io_[global_port_id]; } -size_t FabricGlobalPortInfo::global_port_default_value(const FabricGlobalPortId& global_port_id) const { +size_t FabricGlobalPortInfo::global_port_default_value( + const FabricGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_default_values_[global_port_id]; } @@ -83,7 +93,8 @@ size_t FabricGlobalPortInfo::global_port_default_value(const FabricGlobalPortId& /************************************************************************ * Public Mutators ***********************************************************************/ -FabricGlobalPortId FabricGlobalPortInfo::create_global_port(const ModulePortId& module_port) { +FabricGlobalPortId FabricGlobalPortInfo::create_global_port( + const ModulePortId& module_port) { /* This is a legal name. we can create a new id */ FabricGlobalPortId port_id = FabricGlobalPortId(global_port_ids_.size()); global_port_ids_.push_back(port_id); @@ -102,72 +113,74 @@ FabricGlobalPortId FabricGlobalPortInfo::create_global_port(const ModulePortId& return port_id; } -void FabricGlobalPortInfo::set_global_port_is_clock(const FabricGlobalPortId& global_port_id, - const bool& is_clock) { +void FabricGlobalPortInfo::set_global_port_is_clock( + const FabricGlobalPortId& global_port_id, const bool& is_clock) { VTR_ASSERT(valid_global_port_id(global_port_id)); global_port_is_clock_[global_port_id] = is_clock; } -void FabricGlobalPortInfo::set_global_port_is_set(const FabricGlobalPortId& global_port_id, - const bool& is_set) { +void FabricGlobalPortInfo::set_global_port_is_set( + const FabricGlobalPortId& global_port_id, const bool& is_set) { VTR_ASSERT(valid_global_port_id(global_port_id)); global_port_is_set_[global_port_id] = is_set; } -void FabricGlobalPortInfo::set_global_port_is_reset(const FabricGlobalPortId& global_port_id, - const bool& is_reset) { +void FabricGlobalPortInfo::set_global_port_is_reset( + const FabricGlobalPortId& global_port_id, const bool& is_reset) { VTR_ASSERT(valid_global_port_id(global_port_id)); global_port_is_reset_[global_port_id] = is_reset; } -void FabricGlobalPortInfo::set_global_port_is_prog(const FabricGlobalPortId& global_port_id, - const bool& is_prog) { +void FabricGlobalPortInfo::set_global_port_is_prog( + const FabricGlobalPortId& global_port_id, const bool& is_prog) { VTR_ASSERT(valid_global_port_id(global_port_id)); global_port_is_prog_[global_port_id] = is_prog; } -void FabricGlobalPortInfo::set_global_port_is_shift_register(const FabricGlobalPortId& global_port_id, - const bool& is_shift_register) { +void FabricGlobalPortInfo::set_global_port_is_shift_register( + const FabricGlobalPortId& global_port_id, const bool& is_shift_register) { VTR_ASSERT(valid_global_port_id(global_port_id)); global_port_is_shift_register_[global_port_id] = is_shift_register; } -void FabricGlobalPortInfo::set_global_port_is_bl(const FabricGlobalPortId& global_port_id, - const bool& is_bl) { +void FabricGlobalPortInfo::set_global_port_is_bl( + const FabricGlobalPortId& global_port_id, const bool& is_bl) { VTR_ASSERT(valid_global_port_id(global_port_id)); global_port_is_bl_[global_port_id] = is_bl; } -void FabricGlobalPortInfo::set_global_port_is_wl(const FabricGlobalPortId& global_port_id, - const bool& is_wl) { +void FabricGlobalPortInfo::set_global_port_is_wl( + const FabricGlobalPortId& global_port_id, const bool& is_wl) { VTR_ASSERT(valid_global_port_id(global_port_id)); global_port_is_wl_[global_port_id] = is_wl; } -void FabricGlobalPortInfo::set_global_port_is_config_enable(const FabricGlobalPortId& global_port_id, - const bool& is_config_enable) { +void FabricGlobalPortInfo::set_global_port_is_config_enable( + const FabricGlobalPortId& global_port_id, const bool& is_config_enable) { VTR_ASSERT(valid_global_port_id(global_port_id)); global_port_is_config_enable_[global_port_id] = is_config_enable; } -void FabricGlobalPortInfo::set_global_port_is_io(const FabricGlobalPortId& global_port_id, - const bool& is_io) { +void FabricGlobalPortInfo::set_global_port_is_io( + const FabricGlobalPortId& global_port_id, const bool& is_io) { VTR_ASSERT(valid_global_port_id(global_port_id)); global_port_is_io_[global_port_id] = is_io; } -void FabricGlobalPortInfo::set_global_port_default_value(const FabricGlobalPortId& global_port_id, - const size_t& default_value) { +void FabricGlobalPortInfo::set_global_port_default_value( + const FabricGlobalPortId& global_port_id, const size_t& default_value) { VTR_ASSERT(valid_global_port_id(global_port_id)); global_port_default_values_[global_port_id] = default_value; } /************************************************************************ - * Internal invalidators/validators + * Internal invalidators/validators ***********************************************************************/ /* Validators */ -bool FabricGlobalPortInfo::valid_global_port_id(const FabricGlobalPortId& global_port_id) const { - return ( size_t(global_port_id) < global_port_ids_.size() ) && ( global_port_id == global_port_ids_[global_port_id] ); +bool FabricGlobalPortInfo::valid_global_port_id( + const FabricGlobalPortId& global_port_id) const { + return (size_t(global_port_id) < global_port_ids_.size()) && + (global_port_id == global_port_ids_[global_port_id]); } -} /* namespace openfpga ends */ +} // namespace openfpga diff --git a/openfpga/src/fabric/fabric_global_port_info.h b/openfpga/src/fabric/fabric_global_port_info.h index 45f8f41cc..80d8abc3d 100644 --- a/openfpga/src/fabric/fabric_global_port_info.h +++ b/openfpga/src/fabric/fabric_global_port_info.h @@ -4,13 +4,12 @@ /******************************************************************** * Include header files required by the data structure definition *******************************************************************/ -#include #include - -#include "vtr_vector.h" -#include "module_manager_fwd.h" +#include #include "fabric_global_port_info_fwd.h" +#include "module_manager_fwd.h" +#include "vtr_vector.h" /* namespace openfpga begins */ namespace openfpga { @@ -22,70 +21,80 @@ namespace openfpga { * Currently the global port information is mainly used for testbench generation *******************************************************************/ class FabricGlobalPortInfo { - public: /* Types */ - typedef vtr::vector::const_iterator global_port_iterator; - /* Create range */ - typedef vtr::Range global_port_range; - public: /* Constructor */ - FabricGlobalPortInfo(); - public: /* Public accessors: aggregators */ - global_port_range global_ports() const; - public: /* Public accessors */ - ModulePortId global_module_port(const FabricGlobalPortId& global_port_id) const; - bool global_port_is_clock(const FabricGlobalPortId& global_port_id) const; - bool global_port_is_set(const FabricGlobalPortId& global_port_id) const; - bool global_port_is_reset(const FabricGlobalPortId& global_port_id) const; - bool global_port_is_prog(const FabricGlobalPortId& global_port_id) const; - bool global_port_is_bl(const FabricGlobalPortId& global_port_id) const; - bool global_port_is_wl(const FabricGlobalPortId& global_port_id) const; - bool global_port_is_shift_register(const FabricGlobalPortId& global_port_id) const; - bool global_port_is_config_enable(const FabricGlobalPortId& global_port_id) const; - bool global_port_is_io(const FabricGlobalPortId& global_port_id) const; - size_t global_port_default_value(const FabricGlobalPortId& global_port_id) const; - public: /* Public mutators */ - /* By default, we do not set it as a clock. - * Users should set it through the set_global_port_is_clock() function - */ - FabricGlobalPortId create_global_port(const ModulePortId& module_port); - void set_global_port_is_clock(const FabricGlobalPortId& global_port_id, - const bool& is_clock); - void set_global_port_is_set(const FabricGlobalPortId& global_port_id, - const bool& is_set); - void set_global_port_is_reset(const FabricGlobalPortId& global_port_id, - const bool& is_reset); - void set_global_port_is_prog(const FabricGlobalPortId& global_port_id, - const bool& is_prog); - void set_global_port_is_shift_register(const FabricGlobalPortId& global_port_id, - const bool& is_shift_register); - void set_global_port_is_bl(const FabricGlobalPortId& global_port_id, - const bool& is_bl); - void set_global_port_is_wl(const FabricGlobalPortId& global_port_id, - const bool& is_wl); - void set_global_port_is_config_enable(const FabricGlobalPortId& global_port_id, - const bool& is_config_enable); - void set_global_port_is_io(const FabricGlobalPortId& global_port_id, - const bool& is_io); - void set_global_port_default_value(const FabricGlobalPortId& global_port_id, - const size_t& default_value); - public: /* Public validator */ - bool valid_global_port_id(const FabricGlobalPortId& global_port_id) const; - private: /* Internal data */ - /* Global port information for tiles */ - vtr::vector global_port_ids_; - vtr::vector global_module_ports_; - vtr::vector global_port_is_clock_; - vtr::vector global_port_is_reset_; - vtr::vector global_port_is_set_; - vtr::vector global_port_is_prog_; - vtr::vector global_port_is_shift_register_; - vtr::vector global_port_is_bl_; - vtr::vector global_port_is_wl_; - vtr::vector global_port_is_config_enable_; - vtr::vector global_port_is_io_; - vtr::vector global_port_default_values_; + public: /* Types */ + typedef vtr::vector::const_iterator + global_port_iterator; + /* Create range */ + typedef vtr::Range global_port_range; + + public: /* Constructor */ + FabricGlobalPortInfo(); + + public: /* Public accessors: aggregators */ + global_port_range global_ports() const; + + public: /* Public accessors */ + ModulePortId global_module_port( + const FabricGlobalPortId& global_port_id) const; + bool global_port_is_clock(const FabricGlobalPortId& global_port_id) const; + bool global_port_is_set(const FabricGlobalPortId& global_port_id) const; + bool global_port_is_reset(const FabricGlobalPortId& global_port_id) const; + bool global_port_is_prog(const FabricGlobalPortId& global_port_id) const; + bool global_port_is_bl(const FabricGlobalPortId& global_port_id) const; + bool global_port_is_wl(const FabricGlobalPortId& global_port_id) const; + bool global_port_is_shift_register( + const FabricGlobalPortId& global_port_id) const; + bool global_port_is_config_enable( + const FabricGlobalPortId& global_port_id) const; + bool global_port_is_io(const FabricGlobalPortId& global_port_id) const; + size_t global_port_default_value( + const FabricGlobalPortId& global_port_id) const; + + public: /* Public mutators */ + /* By default, we do not set it as a clock. + * Users should set it through the set_global_port_is_clock() function + */ + FabricGlobalPortId create_global_port(const ModulePortId& module_port); + void set_global_port_is_clock(const FabricGlobalPortId& global_port_id, + const bool& is_clock); + void set_global_port_is_set(const FabricGlobalPortId& global_port_id, + const bool& is_set); + void set_global_port_is_reset(const FabricGlobalPortId& global_port_id, + const bool& is_reset); + void set_global_port_is_prog(const FabricGlobalPortId& global_port_id, + const bool& is_prog); + void set_global_port_is_shift_register( + const FabricGlobalPortId& global_port_id, const bool& is_shift_register); + void set_global_port_is_bl(const FabricGlobalPortId& global_port_id, + const bool& is_bl); + void set_global_port_is_wl(const FabricGlobalPortId& global_port_id, + const bool& is_wl); + void set_global_port_is_config_enable( + const FabricGlobalPortId& global_port_id, const bool& is_config_enable); + void set_global_port_is_io(const FabricGlobalPortId& global_port_id, + const bool& is_io); + void set_global_port_default_value(const FabricGlobalPortId& global_port_id, + const size_t& default_value); + + public: /* Public validator */ + bool valid_global_port_id(const FabricGlobalPortId& global_port_id) const; + + private: /* Internal data */ + /* Global port information for tiles */ + vtr::vector global_port_ids_; + vtr::vector global_module_ports_; + vtr::vector global_port_is_clock_; + vtr::vector global_port_is_reset_; + vtr::vector global_port_is_set_; + vtr::vector global_port_is_prog_; + vtr::vector global_port_is_shift_register_; + vtr::vector global_port_is_bl_; + vtr::vector global_port_is_wl_; + vtr::vector global_port_is_config_enable_; + vtr::vector global_port_is_io_; + vtr::vector global_port_default_values_; }; -} /* namespace openfpga ends */ +} // namespace openfpga #endif - diff --git a/openfpga/src/fabric/fabric_global_port_info_fwd.h b/openfpga/src/fabric/fabric_global_port_info_fwd.h index 35a7dcd04..c4b6e13d8 100644 --- a/openfpga/src/fabric/fabric_global_port_info_fwd.h +++ b/openfpga/src/fabric/fabric_global_port_info_fwd.h @@ -1,11 +1,11 @@ /************************************************************************ - * A header file for FabricGlobalPortList class, including critical data declaration - * Please include this file only for using any FabricGlobalPortList data structure - * Refer to fabric_global_port_list.h for more details + * A header file for FabricGlobalPortList class, including critical data + *declaration Please include this file only for using any FabricGlobalPortList + *data structure Refer to fabric_global_port_list.h for more details ***********************************************************************/ /************************************************************************ - * Create strong id for fabric global ports to avoid illegal type casting + * Create strong id for fabric global ports to avoid illegal type casting ***********************************************************************/ #ifndef FABRIC_GLOBAL_PORT_INFO_FWD_H #define FABRIC_GLOBAL_PORT_INFO_FWD_H diff --git a/openfpga/src/fabric/fabric_hierarchy_writer.cpp b/openfpga/src/fabric/fabric_hierarchy_writer.cpp index a40bfee39..546f0ebc1 100644 --- a/openfpga/src/fabric/fabric_hierarchy_writer.cpp +++ b/openfpga/src/fabric/fabric_hierarchy_writer.cpp @@ -2,33 +2,28 @@ * Output internal structure of Module Graph hierarchy to file formats ***************************************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - -#include "openfpga_naming.h" - #include "fabric_hierarchy_writer.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" /* begin namespace openfpga */ namespace openfpga { /*************************************************************************************** * Recursively output child module of the parent_module to a text file - * We use Depth-First Search (DFS) here so that we can output a tree down to leaf first - * Add space (indent) based on the depth in hierarchy - * e.g. depth = 1 means a space as indent + * We use Depth-First Search (DFS) here so that we can output a tree down to + *leaf first Add space (indent) based on the depth in hierarchy e.g. depth = 1 + *means a space as indent ***************************************************************************************/ -static -int rec_output_module_hierarchy_to_text_file(std::fstream& fp, - const size_t& hie_depth_to_stop, - const size_t& current_hie_depth, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const bool& verbose) { +static int rec_output_module_hierarchy_to_text_file( + std::fstream& fp, const size_t& hie_depth_to_stop, + const size_t& current_hie_depth, const ModuleManager& module_manager, + const ModuleId& parent_module, const bool& verbose) { /* Stop if hierarchy depth is beyond the stop line */ if (hie_depth_to_stop < current_hie_depth) { return 0; @@ -39,14 +34,14 @@ int rec_output_module_hierarchy_to_text_file(std::fstream& fp, } /* Iterate over all the child module */ - for (const ModuleId& child_module : module_manager.child_modules(parent_module)) { + for (const ModuleId& child_module : + module_manager.child_modules(parent_module)) { if (false == write_space_to_file(fp, current_hie_depth * 2)) { return 2; } if (true != module_manager.valid_module_id(child_module)) { - VTR_LOGV_ERROR(verbose, - "Unable to find the child module '%u'!\n", + VTR_LOGV_ERROR(verbose, "Unable to find the child module '%u'!\n", size_t(child_module)); return 1; } @@ -54,22 +49,20 @@ int rec_output_module_hierarchy_to_text_file(std::fstream& fp, fp << "- "; fp << module_manager.module_name(child_module); - /* If this is the leaf node, we leave a new line - * Otherwise, we will leave a ':' to be compatible to YAML file format + /* If this is the leaf node, we leave a new line + * Otherwise, we will leave a ':' to be compatible to YAML file format */ - if ( (0 != module_manager.child_modules(child_module).size()) - && (hie_depth_to_stop >= current_hie_depth + 1) ) { + if ((0 != module_manager.child_modules(child_module).size()) && + (hie_depth_to_stop >= current_hie_depth + 1)) { fp << ":"; } fp << "\n"; /* Go to next level */ - int status = rec_output_module_hierarchy_to_text_file(fp, - hie_depth_to_stop, - current_hie_depth + 1, /* Increment the depth for the next level */ - module_manager, - child_module, - verbose); + int status = rec_output_module_hierarchy_to_text_file( + fp, hie_depth_to_stop, + current_hie_depth + 1, /* Increment the depth for the next level */ + module_manager, child_module, verbose); if (0 != status) { return status; } @@ -84,17 +77,19 @@ int rec_output_module_hierarchy_to_text_file(std::fstream& fp, * * * ... - * This file is mainly used by hierarchical P&R flow + * This file is mainly used by hierarchical P&R flow * * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture + * Return 1 if there are more serious bugs in the architecture * Return 2 if fail when creating files ***************************************************************************************/ int write_fabric_hierarchy_to_text_file(const ModuleManager& module_manager, const std::string& fname, const size_t& hie_depth_to_stop, const bool& verbose) { - std::string timer_message = std::string("Write fabric hierarchy to plain-text file '") + fname + std::string("'"); + std::string timer_message = + std::string("Write fabric hierarchy to plain-text file '") + fname + + std::string("'"); std::string dir_path = format_dir_path(find_path_dir_name(fname)); @@ -119,12 +114,11 @@ int write_fabric_hierarchy_to_text_file(const ModuleManager& module_manager, std::string top_module_name = generate_fpga_top_module_name(); ModuleId top_module = module_manager.find_module(top_module_name); if (true != module_manager.valid_module_id(top_module)) { - VTR_LOGV_ERROR(verbose, - "Unable to find the top-level module '%s'!\n", + VTR_LOGV_ERROR(verbose, "Unable to find the top-level module '%s'!\n", top_module_name.c_str()); return 1; } - + /* Record current depth of module: top module is the root with 0 depth */ size_t hie_depth = 0; @@ -132,15 +126,13 @@ int write_fabric_hierarchy_to_text_file(const ModuleManager& module_manager, return 0; } - fp << top_module_name << ":" << "\n"; + fp << top_module_name << ":" + << "\n"; /* Visit child module recursively and output the hierarchy */ - int err_code = rec_output_module_hierarchy_to_text_file(fp, - hie_depth_to_stop, - hie_depth + 1, /* Start with level 1 */ - module_manager, - top_module, - verbose); + int err_code = rec_output_module_hierarchy_to_text_file( + fp, hie_depth_to_stop, hie_depth + 1, /* Start with level 1 */ + module_manager, top_module, verbose); /* close a file */ fp.close(); diff --git a/openfpga/src/fabric/fabric_hierarchy_writer.h b/openfpga/src/fabric/fabric_hierarchy_writer.h index 86ed3a263..ccba3f99d 100644 --- a/openfpga/src/fabric/fabric_hierarchy_writer.h +++ b/openfpga/src/fabric/fabric_hierarchy_writer.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" #include "openfpga_context.h" +#include "vpr_context.h" /******************************************************************** * Function declaration diff --git a/openfpga/src/fabric/fabric_key_writer.cpp b/openfpga/src/fabric/fabric_key_writer.cpp index 7ac8f90ea..d5e7ef978 100644 --- a/openfpga/src/fabric/fabric_key_writer.cpp +++ b/openfpga/src/fabric/fabric_key_writer.cpp @@ -2,21 +2,18 @@ * Output fabric key of Module Graph to file formats ***************************************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgautil library */ #include "openfpga_digest.h" /* Headers from archopenfpga library */ -#include "write_xml_fabric_key.h" - -#include "openfpga_naming.h" - -#include "memory_utils.h" - #include "fabric_key_writer.h" +#include "memory_utils.h" +#include "openfpga_naming.h" +#include "write_xml_fabric_key.h" /* begin namespace openfpga */ namespace openfpga { @@ -26,15 +23,15 @@ namespace openfpga { * We will use the writer API in libfabrickey * * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture + * Return 1 if there are more serious bugs in the architecture * Return 2 if fail when creating files ***************************************************************************************/ -int write_fabric_key_to_xml_file(const ModuleManager& module_manager, - const std::string& fname, - const ConfigProtocol& config_protocol, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const bool& verbose) { - std::string timer_message = std::string("Write fabric key to XML file '") + fname + std::string("'"); +int write_fabric_key_to_xml_file( + const ModuleManager& module_manager, const std::string& fname, + const ConfigProtocol& config_protocol, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& verbose) { + std::string timer_message = + std::string("Write fabric key to XML file '") + fname + std::string("'"); std::string dir_path = format_dir_path(find_path_dir_name(fname)); @@ -51,15 +48,14 @@ int write_fabric_key_to_xml_file(const ModuleManager& module_manager, std::string top_module_name = generate_fpga_top_module_name(); ModuleId top_module = module_manager.find_module(top_module_name); if (true != module_manager.valid_module_id(top_module)) { - VTR_LOGV_ERROR(verbose, - "Unable to find the top-level module '%s'!\n", + VTR_LOGV_ERROR(verbose, "Unable to find the top-level module '%s'!\n", top_module_name.c_str()); return 1; } - + /* Build a fabric key database by visiting all the configurable children */ FabricKey fabric_key; - size_t num_keys = module_manager.configurable_children(top_module).size(); + size_t num_keys = module_manager.configurable_children(top_module).size(); fabric_key.reserve_keys(num_keys); @@ -68,41 +64,57 @@ int write_fabric_key_to_xml_file(const ModuleManager& module_manager, /* Create regions and build a id map */ std::map region_id_map; - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { FabricRegionId fabric_region = fabric_key.create_region(); region_id_map[config_region] = fabric_region; - } - + } + /* Create regions for the keys and load keys by region */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { /* Must have a valid one-to-one region mapping */ auto result = region_id_map.find(config_region); VTR_ASSERT_SAFE(result != region_id_map.end()); - FabricRegionId fabric_region = result->second; + FabricRegionId fabric_region = result->second; - /* Each configuration protocol has some child which should not be in the list. They are typically decoders */ - size_t curr_region_num_config_child = module_manager.region_configurable_children(top_module, config_region).size(); - size_t num_child_to_skip = estimate_num_configurable_children_to_skip_by_config_protocol(config_protocol, curr_region_num_config_child); + /* Each configuration protocol has some child which should not be in the + * list. They are typically decoders */ + size_t curr_region_num_config_child = + module_manager.region_configurable_children(top_module, config_region) + .size(); + size_t num_child_to_skip = + estimate_num_configurable_children_to_skip_by_config_protocol( + config_protocol, curr_region_num_config_child); curr_region_num_config_child -= num_child_to_skip; fabric_key.reserve_region_keys(fabric_region, curr_region_num_config_child); for (size_t ichild = 0; ichild < curr_region_num_config_child; ++ichild) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[ichild]; - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[ichild]; - vtr::Point child_coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[ichild]; + ModuleId child_module = module_manager.region_configurable_children( + top_module, config_region)[ichild]; + size_t child_instance = + module_manager.region_configurable_child_instances( + top_module, config_region)[ichild]; + vtr::Point child_coord = + module_manager.region_configurable_child_coordinates( + top_module, config_region)[ichild]; FabricKeyId key = fabric_key.create_key(); fabric_key.set_key_name(key, module_manager.module_name(child_module)); fabric_key.set_key_value(key, child_instance); - if (false == module_manager.instance_name(top_module, child_module, child_instance).empty()) { - fabric_key.set_key_alias(key, module_manager.instance_name(top_module, child_module, child_instance)); + if (false == + module_manager.instance_name(top_module, child_module, child_instance) + .empty()) { + fabric_key.set_key_alias( + key, module_manager.instance_name(top_module, child_module, + child_instance)); } /* Add key coordinate */ fabric_key.set_key_coordinate(key, child_coord); - + /* Add keys to the region */ fabric_key.add_key_to_region(fabric_region, key); } @@ -111,37 +123,46 @@ int write_fabric_key_to_xml_file(const ModuleManager& module_manager, /* Skip invalid region, some architecture may not have BL/WL banks */ if (0 < blwl_sr_banks.regions().size()) { /* Add BL shift register bank information, if there is any */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { auto result = region_id_map.find(config_region); /* Must have a valid one-to-one region mapping */ VTR_ASSERT_SAFE(result != region_id_map.end()); - FabricRegionId fabric_region = result->second; - for (const FabricBitLineBankId& bank : blwl_sr_banks.bl_banks(config_region)) { - FabricBitLineBankId fabric_bank = fabric_key.create_bl_shift_register_bank(fabric_region); - for (const BasicPort& data_port : blwl_sr_banks.bl_bank_data_ports(config_region, bank)) { - fabric_key.add_data_port_to_bl_shift_register_bank(fabric_region, fabric_bank, data_port); + FabricRegionId fabric_region = result->second; + for (const FabricBitLineBankId& bank : + blwl_sr_banks.bl_banks(config_region)) { + FabricBitLineBankId fabric_bank = + fabric_key.create_bl_shift_register_bank(fabric_region); + for (const BasicPort& data_port : + blwl_sr_banks.bl_bank_data_ports(config_region, bank)) { + fabric_key.add_data_port_to_bl_shift_register_bank( + fabric_region, fabric_bank, data_port); } } } /* Add WL shift register bank information, if there is any */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { auto result = region_id_map.find(config_region); /* Must have a valid one-to-one region mapping */ VTR_ASSERT_SAFE(result != region_id_map.end()); - FabricRegionId fabric_region = result->second; + FabricRegionId fabric_region = result->second; - for (const FabricWordLineBankId& bank : blwl_sr_banks.wl_banks(config_region)) { - FabricWordLineBankId fabric_bank = fabric_key.create_wl_shift_register_bank(fabric_region); - for (const BasicPort& data_port : blwl_sr_banks.wl_bank_data_ports(config_region, bank)) { - fabric_key.add_data_port_to_wl_shift_register_bank(fabric_region, fabric_bank, data_port); + for (const FabricWordLineBankId& bank : + blwl_sr_banks.wl_banks(config_region)) { + FabricWordLineBankId fabric_bank = + fabric_key.create_wl_shift_register_bank(fabric_region); + for (const BasicPort& data_port : + blwl_sr_banks.wl_bank_data_ports(config_region, bank)) { + fabric_key.add_data_port_to_wl_shift_register_bank( + fabric_region, fabric_bank, data_port); } } } } - VTR_LOGV(verbose, - "Created %lu regions and %lu keys for the top module %s.\n", + VTR_LOGV(verbose, "Created %lu regions and %lu keys for the top module %s.\n", num_regions, num_keys, top_module_name.c_str()); /* Call the XML writer for fabric key */ diff --git a/openfpga/src/fabric/fabric_key_writer.h b/openfpga/src/fabric/fabric_key_writer.h index d80a7180f..34327d307 100644 --- a/openfpga/src/fabric/fabric_key_writer.h +++ b/openfpga/src/fabric/fabric_key_writer.h @@ -5,9 +5,10 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "module_manager.h" + #include "config_protocol.h" #include "memory_bank_shift_register_banks.h" +#include "module_manager.h" /******************************************************************** * Function declaration @@ -16,11 +17,10 @@ /* begin namespace openfpga */ namespace openfpga { -int write_fabric_key_to_xml_file(const ModuleManager& module_manager, - const std::string& fname, - const ConfigProtocol& config_protocol, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const bool& verbose); +int write_fabric_key_to_xml_file( + const ModuleManager& module_manager, const std::string& fname, + const ConfigProtocol& config_protocol, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp index 39eaa8ad3..2bc2dc596 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp @@ -1,7 +1,9 @@ +#include "memory_bank_shift_register_banks.h" + #include -#include "vtr_assert.h" + #include "openfpga_reserved_words.h" -#include "memory_bank_shift_register_banks.h" +#include "vtr_assert.h" /* begin namespace openfpga */ namespace openfpga { @@ -14,10 +16,13 @@ std::vector MemoryBankShiftRegisterBanks::bl_bank_unique_sizes() const { std::vector unique_sizes; for (const auto& region : bl_bank_data_ports_) { for (const auto& bank : region) { - ConfigRegionId region_id = ConfigRegionId(®ion - &bl_bank_data_ports_[ConfigRegionId(0)]); - FabricBitLineBankId bank_id = FabricBitLineBankId(&bank - ®ion[FabricBitLineBankId(0)]); + ConfigRegionId region_id = + ConfigRegionId(®ion - &bl_bank_data_ports_[ConfigRegionId(0)]); + FabricBitLineBankId bank_id = + FabricBitLineBankId(&bank - ®ion[FabricBitLineBankId(0)]); size_t cur_bank_size = bl_bank_size(region_id, bank_id); - if (unique_sizes.end() == std::find(unique_sizes.begin(), unique_sizes.end(), cur_bank_size)) { + if (unique_sizes.end() == + std::find(unique_sizes.begin(), unique_sizes.end(), cur_bank_size)) { unique_sizes.push_back(cur_bank_size); } } @@ -25,11 +30,13 @@ std::vector MemoryBankShiftRegisterBanks::bl_bank_unique_sizes() const { return unique_sizes; } -std::vector MemoryBankShiftRegisterBanks::bl_bank_unique_modules() const { +std::vector MemoryBankShiftRegisterBanks::bl_bank_unique_modules() + const { std::vector unique_modules; for (const auto& region : bl_bank_modules_) { for (const auto& bank : region) { - if (unique_modules.end() == std::find(unique_modules.begin(), unique_modules.end(), bank)) { + if (unique_modules.end() == + std::find(unique_modules.begin(), unique_modules.end(), bank)) { unique_modules.push_back(bank); } } @@ -37,27 +44,33 @@ std::vector MemoryBankShiftRegisterBanks::bl_bank_unique_modules() con return unique_modules; } -size_t MemoryBankShiftRegisterBanks::bl_bank_size(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { +size_t MemoryBankShiftRegisterBanks::bl_bank_size( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { size_t cur_bank_size = 0; for (const auto& data_port : bl_bank_data_ports(region_id, bank_id)) { - cur_bank_size += data_port.get_width(); + cur_bank_size += data_port.get_width(); } return cur_bank_size; } -FabricKey::fabric_bit_line_bank_range MemoryBankShiftRegisterBanks::bl_banks(const ConfigRegionId& region_id) const { +FabricKey::fabric_bit_line_bank_range MemoryBankShiftRegisterBanks::bl_banks( + const ConfigRegionId& region_id) const { VTR_ASSERT(valid_region_id(region_id)); - return vtr::make_range(bl_bank_ids_[region_id].begin(), bl_bank_ids_[region_id].end()); + return vtr::make_range(bl_bank_ids_[region_id].begin(), + bl_bank_ids_[region_id].end()); } std::vector MemoryBankShiftRegisterBanks::wl_bank_unique_sizes() const { std::vector unique_sizes; for (const auto& region : wl_bank_data_ports_) { for (const auto& bank : region) { - ConfigRegionId region_id = ConfigRegionId(®ion - &wl_bank_data_ports_[ConfigRegionId(0)]); - FabricWordLineBankId bank_id = FabricWordLineBankId(&bank - ®ion[FabricWordLineBankId(0)]); + ConfigRegionId region_id = + ConfigRegionId(®ion - &wl_bank_data_ports_[ConfigRegionId(0)]); + FabricWordLineBankId bank_id = + FabricWordLineBankId(&bank - ®ion[FabricWordLineBankId(0)]); size_t cur_bank_size = wl_bank_size(region_id, bank_id); - if (unique_sizes.end() == std::find(unique_sizes.begin(), unique_sizes.end(), cur_bank_size)) { + if (unique_sizes.end() == + std::find(unique_sizes.begin(), unique_sizes.end(), cur_bank_size)) { unique_sizes.push_back(cur_bank_size); } } @@ -65,11 +78,13 @@ std::vector MemoryBankShiftRegisterBanks::wl_bank_unique_sizes() const { return unique_sizes; } -std::vector MemoryBankShiftRegisterBanks::wl_bank_unique_modules() const { +std::vector MemoryBankShiftRegisterBanks::wl_bank_unique_modules() + const { std::vector unique_modules; for (const auto& region : wl_bank_modules_) { for (const auto& bank : region) { - if (unique_modules.end() == std::find(unique_modules.begin(), unique_modules.end(), bank)) { + if (unique_modules.end() == + std::find(unique_modules.begin(), unique_modules.end(), bank)) { unique_modules.push_back(bank); } } @@ -77,35 +92,41 @@ std::vector MemoryBankShiftRegisterBanks::wl_bank_unique_modules() con return unique_modules; } -size_t MemoryBankShiftRegisterBanks::wl_bank_size(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const { +size_t MemoryBankShiftRegisterBanks::wl_bank_size( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const { size_t cur_bank_size = 0; for (const auto& data_port : wl_bank_data_ports(region_id, bank_id)) { - cur_bank_size += data_port.get_width(); + cur_bank_size += data_port.get_width(); } return cur_bank_size; } -FabricKey::fabric_word_line_bank_range MemoryBankShiftRegisterBanks::wl_banks(const ConfigRegionId& region_id) const { +FabricKey::fabric_word_line_bank_range MemoryBankShiftRegisterBanks::wl_banks( + const ConfigRegionId& region_id) const { VTR_ASSERT(valid_region_id(region_id)); - return vtr::make_range(wl_bank_ids_[region_id].begin(), wl_bank_ids_[region_id].end()); + return vtr::make_range(wl_bank_ids_[region_id].begin(), + wl_bank_ids_[region_id].end()); } -std::vector MemoryBankShiftRegisterBanks::bl_bank_data_ports(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { +std::vector MemoryBankShiftRegisterBanks::bl_bank_data_ports( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); return bl_bank_data_ports_[region_id][bank_id]; } -std::vector MemoryBankShiftRegisterBanks::wl_bank_data_ports(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const { +std::vector MemoryBankShiftRegisterBanks::wl_bank_data_ports( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); return wl_bank_data_ports_[region_id][bank_id]; } -FabricBitLineBankId MemoryBankShiftRegisterBanks::find_bl_shift_register_bank_id(const ConfigRegionId& region, - const BasicPort& bl_port) const { +FabricBitLineBankId +MemoryBankShiftRegisterBanks::find_bl_shift_register_bank_id( + const ConfigRegionId& region, const BasicPort& bl_port) const { if (is_bl_bank_dirty_) { - build_bl_port_fast_lookup(); + build_bl_port_fast_lookup(); } - + VTR_ASSERT(valid_region_id(region)); const auto& result = bl_ports_to_sr_bank_ids_[region].find(bl_port); if (result == bl_ports_to_sr_bank_ids_[region].end()) { @@ -114,12 +135,12 @@ FabricBitLineBankId MemoryBankShiftRegisterBanks::find_bl_shift_register_bank_id return result->second; } -BasicPort MemoryBankShiftRegisterBanks::find_bl_shift_register_bank_data_port(const ConfigRegionId& region, - const BasicPort& bl_port) const { +BasicPort MemoryBankShiftRegisterBanks::find_bl_shift_register_bank_data_port( + const ConfigRegionId& region, const BasicPort& bl_port) const { if (is_bl_bank_dirty_) { - build_bl_port_fast_lookup(); + build_bl_port_fast_lookup(); } - + VTR_ASSERT(valid_region_id(region)); const auto& result = bl_ports_to_sr_bank_ports_[region].find(bl_port); if (result == bl_ports_to_sr_bank_ports_[region].end()) { @@ -128,9 +149,10 @@ BasicPort MemoryBankShiftRegisterBanks::find_bl_shift_register_bank_data_port(co return result->second; } -std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_child_ids(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const BasicPort& src_port) const { +std::vector +MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_child_ids( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id, + const BasicPort& src_port) const { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); auto result = bl_bank_sink_child_ids_[region_id][bank_id].find(src_port); if (result == bl_bank_sink_child_ids_[region_id][bank_id].end()) { @@ -139,9 +161,10 @@ std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_ch return result->second; } -std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_child_pin_ids(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const BasicPort& src_port) const { +std::vector +MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_child_pin_ids( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id, + const BasicPort& src_port) const { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); auto result = bl_bank_sink_child_pin_ids_[region_id][bank_id].find(src_port); if (result == bl_bank_sink_child_pin_ids_[region_id][bank_id].end()) { @@ -150,15 +173,17 @@ std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_ch return result->second; } -std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_source_ports(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id) const { +std::vector +MemoryBankShiftRegisterBanks::bl_shift_register_bank_source_ports( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); std::vector src_ports; - size_t cur_pin =0; + size_t cur_pin = 0; for (const BasicPort& wide_port : bl_bank_data_ports(region_id, bank_id)) { for (size_t ipin = 0; ipin < wide_port.pins().size(); ++ipin) { - src_ports.push_back(BasicPort(std::string(MEMORY_BL_PORT_NAME), cur_pin, cur_pin)); + src_ports.push_back( + BasicPort(std::string(MEMORY_BL_PORT_NAME), cur_pin, cur_pin)); cur_pin++; } } @@ -166,24 +191,25 @@ std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_sour return src_ports; } -ModuleId MemoryBankShiftRegisterBanks::bl_shift_register_bank_module(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id) const { +ModuleId MemoryBankShiftRegisterBanks::bl_shift_register_bank_module( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); return bl_bank_modules_[region_id][bank_id]; } -size_t MemoryBankShiftRegisterBanks::bl_shift_register_bank_instance(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id) const { +size_t MemoryBankShiftRegisterBanks::bl_shift_register_bank_instance( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); return bl_bank_instances_[region_id][bank_id]; } -FabricWordLineBankId MemoryBankShiftRegisterBanks::find_wl_shift_register_bank_id(const ConfigRegionId& region, - const BasicPort& wl_port) const { +FabricWordLineBankId +MemoryBankShiftRegisterBanks::find_wl_shift_register_bank_id( + const ConfigRegionId& region, const BasicPort& wl_port) const { if (is_wl_bank_dirty_) { - build_wl_port_fast_lookup(); + build_wl_port_fast_lookup(); } - + VTR_ASSERT(valid_region_id(region)); const auto& result = wl_ports_to_sr_bank_ids_[region].find(wl_port); if (result == wl_ports_to_sr_bank_ids_[region].end()) { @@ -192,12 +218,12 @@ FabricWordLineBankId MemoryBankShiftRegisterBanks::find_wl_shift_register_bank_i return result->second; } -BasicPort MemoryBankShiftRegisterBanks::find_wl_shift_register_bank_data_port(const ConfigRegionId& region, - const BasicPort& wl_port) const { +BasicPort MemoryBankShiftRegisterBanks::find_wl_shift_register_bank_data_port( + const ConfigRegionId& region, const BasicPort& wl_port) const { if (is_wl_bank_dirty_) { - build_wl_port_fast_lookup(); + build_wl_port_fast_lookup(); } - + VTR_ASSERT(valid_region_id(region)); const auto& result = wl_ports_to_sr_bank_ports_[region].find(wl_port); if (result == wl_ports_to_sr_bank_ports_[region].end()) { @@ -226,55 +252,56 @@ void MemoryBankShiftRegisterBanks::resize_regions(const size_t& num_regions) { wl_bank_sink_child_pin_ids_.resize(num_regions); } -void MemoryBankShiftRegisterBanks::link_bl_shift_register_bank_to_module(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const ModuleId& module_id) { +void MemoryBankShiftRegisterBanks::link_bl_shift_register_bank_to_module( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id, + const ModuleId& module_id) { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); - bl_bank_modules_[region_id][bank_id] = module_id; + bl_bank_modules_[region_id][bank_id] = module_id; } -void MemoryBankShiftRegisterBanks::link_bl_shift_register_bank_to_instance(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const size_t& instance_id) { +void MemoryBankShiftRegisterBanks::link_bl_shift_register_bank_to_instance( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id, + const size_t& instance_id) { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); - bl_bank_instances_[region_id][bank_id] = instance_id; + bl_bank_instances_[region_id][bank_id] = instance_id; } -void MemoryBankShiftRegisterBanks::link_wl_shift_register_bank_to_module(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id, - const ModuleId& module_id) { +void MemoryBankShiftRegisterBanks::link_wl_shift_register_bank_to_module( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id, + const ModuleId& module_id) { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); - wl_bank_modules_[region_id][bank_id] = module_id; + wl_bank_modules_[region_id][bank_id] = module_id; } -void MemoryBankShiftRegisterBanks::link_wl_shift_register_bank_to_instance(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id, - const size_t& instance_id) { +void MemoryBankShiftRegisterBanks::link_wl_shift_register_bank_to_instance( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id, + const size_t& instance_id) { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); - wl_bank_instances_[region_id][bank_id] = instance_id; + wl_bank_instances_[region_id][bank_id] = instance_id; } -void MemoryBankShiftRegisterBanks::add_bl_shift_register_bank_sink_node(const ConfigRegionId& region, - const FabricBitLineBankId& bank, - const BasicPort& src_port, - const size_t& sink_child_id, - const size_t& sink_child_pin_id) { +void MemoryBankShiftRegisterBanks::add_bl_shift_register_bank_sink_node( + const ConfigRegionId& region, const FabricBitLineBankId& bank, + const BasicPort& src_port, const size_t& sink_child_id, + const size_t& sink_child_pin_id) { VTR_ASSERT(valid_bl_bank_id(region, bank)); bl_bank_sink_child_ids_[region][bank][src_port].push_back(sink_child_id); - bl_bank_sink_child_pin_ids_[region][bank][src_port].push_back(sink_child_pin_id); + bl_bank_sink_child_pin_ids_[region][bank][src_port].push_back( + sink_child_pin_id); } -void MemoryBankShiftRegisterBanks::add_wl_shift_register_bank_sink_node(const ConfigRegionId& region, - const FabricWordLineBankId& bank, - const BasicPort& src_port, - const size_t& sink_child_id, - const size_t& sink_child_pin_id) { +void MemoryBankShiftRegisterBanks::add_wl_shift_register_bank_sink_node( + const ConfigRegionId& region, const FabricWordLineBankId& bank, + const BasicPort& src_port, const size_t& sink_child_id, + const size_t& sink_child_pin_id) { VTR_ASSERT(valid_wl_bank_id(region, bank)); wl_bank_sink_child_ids_[region][bank][src_port].push_back(sink_child_id); - wl_bank_sink_child_pin_ids_[region][bank][src_port].push_back(sink_child_pin_id); + wl_bank_sink_child_pin_ids_[region][bank][src_port].push_back( + sink_child_pin_id); } -void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks) { +void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks( + const ConfigRegionId& region_id, const size_t& num_banks) { VTR_ASSERT(valid_region_id(region_id)); bl_bank_ids_[region_id].reserve(num_banks); bl_bank_data_ports_[region_id].reserve(num_banks); @@ -284,12 +311,14 @@ void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks(const ConfigR bl_bank_sink_child_pin_ids_[region_id].reserve(num_banks); } -void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) { +void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks( + const FabricRegionId& region_id, const size_t& num_banks) { ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); reserve_bl_shift_register_banks(config_region_id, num_banks); } -void MemoryBankShiftRegisterBanks::reserve_wl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks) { +void MemoryBankShiftRegisterBanks::reserve_wl_shift_register_banks( + const ConfigRegionId& region_id, const size_t& num_banks) { VTR_ASSERT(valid_region_id(region_id)); wl_bank_ids_[region_id].reserve(num_banks); wl_bank_data_ports_[region_id].reserve(num_banks); @@ -299,16 +328,19 @@ void MemoryBankShiftRegisterBanks::reserve_wl_shift_register_banks(const ConfigR wl_bank_sink_child_pin_ids_[region_id].reserve(num_banks); } -void MemoryBankShiftRegisterBanks::reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) { +void MemoryBankShiftRegisterBanks::reserve_wl_shift_register_banks( + const FabricRegionId& region_id, const size_t& num_banks) { ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); reserve_wl_shift_register_banks(config_region_id, num_banks); } -FabricBitLineBankId MemoryBankShiftRegisterBanks::create_bl_shift_register_bank(const ConfigRegionId& region_id) { +FabricBitLineBankId MemoryBankShiftRegisterBanks::create_bl_shift_register_bank( + const ConfigRegionId& region_id) { VTR_ASSERT(valid_region_id(region_id)); - + /* Create a new id */ - FabricBitLineBankId bank = FabricBitLineBankId(bl_bank_ids_[region_id].size()); + FabricBitLineBankId bank = + FabricBitLineBankId(bl_bank_ids_[region_id].size()); bl_bank_ids_[region_id].push_back(bank); bl_bank_data_ports_[region_id].emplace_back(); bl_bank_modules_[region_id].push_back(ModuleId::INVALID()); @@ -319,36 +351,42 @@ FabricBitLineBankId MemoryBankShiftRegisterBanks::create_bl_shift_register_bank( return bank; } -FabricBitLineBankId MemoryBankShiftRegisterBanks::create_bl_shift_register_bank(const FabricRegionId& region_id) { +FabricBitLineBankId MemoryBankShiftRegisterBanks::create_bl_shift_register_bank( + const FabricRegionId& region_id) { ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); return create_bl_shift_register_bank(config_region_id); } -void MemoryBankShiftRegisterBanks::add_data_port_to_bl_shift_register_bank(const FabricRegionId& region_id, - const FabricBitLineBankId& bank_id, - const openfpga::BasicPort& data_port) { +void MemoryBankShiftRegisterBanks::add_data_port_to_bl_shift_register_bank( + const FabricRegionId& region_id, const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port) { ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); add_data_port_to_bl_shift_register_bank(config_region_id, bank_id, data_port); } -void MemoryBankShiftRegisterBanks::add_data_port_to_bl_shift_register_bank(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const openfpga::BasicPort& data_port) { +void MemoryBankShiftRegisterBanks::add_data_port_to_bl_shift_register_bank( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port) { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); bl_bank_data_ports_[region_id][bank_id].push_back(data_port); is_bl_bank_dirty_ = true; } -FabricWordLineBankId MemoryBankShiftRegisterBanks::create_wl_shift_register_bank(const FabricRegionId& region_id) { +FabricWordLineBankId +MemoryBankShiftRegisterBanks::create_wl_shift_register_bank( + const FabricRegionId& region_id) { ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); return create_wl_shift_register_bank(config_region_id); } -FabricWordLineBankId MemoryBankShiftRegisterBanks::create_wl_shift_register_bank(const ConfigRegionId& region_id) { +FabricWordLineBankId +MemoryBankShiftRegisterBanks::create_wl_shift_register_bank( + const ConfigRegionId& region_id) { VTR_ASSERT(valid_region_id(region_id)); - + /* Create a new id */ - FabricWordLineBankId bank = FabricWordLineBankId(wl_bank_ids_[region_id].size()); + FabricWordLineBankId bank = + FabricWordLineBankId(wl_bank_ids_[region_id].size()); wl_bank_ids_[region_id].push_back(bank); wl_bank_data_ports_[region_id].emplace_back(); wl_bank_modules_[region_id].push_back(ModuleId::INVALID()); @@ -359,24 +397,25 @@ FabricWordLineBankId MemoryBankShiftRegisterBanks::create_wl_shift_register_bank return bank; } -void MemoryBankShiftRegisterBanks::add_data_port_to_wl_shift_register_bank(const FabricRegionId& region_id, - const FabricWordLineBankId& bank_id, - const openfpga::BasicPort& data_port) { +void MemoryBankShiftRegisterBanks::add_data_port_to_wl_shift_register_bank( + const FabricRegionId& region_id, const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port) { ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); add_data_port_to_wl_shift_register_bank(config_region_id, bank_id, data_port); } -void MemoryBankShiftRegisterBanks::add_data_port_to_wl_shift_register_bank(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id, - const openfpga::BasicPort& data_port) { +void MemoryBankShiftRegisterBanks::add_data_port_to_wl_shift_register_bank( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port) { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); wl_bank_data_ports_[region_id][bank_id].push_back(data_port); is_wl_bank_dirty_ = true; } -std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_child_ids(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id, - const BasicPort& src_port) const { +std::vector +MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_child_ids( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id, + const BasicPort& src_port) const { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); auto result = wl_bank_sink_child_ids_[region_id][bank_id].find(src_port); if (result == wl_bank_sink_child_ids_[region_id][bank_id].end()) { @@ -385,21 +424,22 @@ std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_ch return result->second; } -ModuleId MemoryBankShiftRegisterBanks::wl_shift_register_bank_module(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id) const { +ModuleId MemoryBankShiftRegisterBanks::wl_shift_register_bank_module( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); return wl_bank_modules_[region_id][bank_id]; } -size_t MemoryBankShiftRegisterBanks::wl_shift_register_bank_instance(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id) const { +size_t MemoryBankShiftRegisterBanks::wl_shift_register_bank_instance( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); return wl_bank_instances_[region_id][bank_id]; } -std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_child_pin_ids(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id, - const BasicPort& src_port) const { +std::vector +MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_child_pin_ids( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id, + const BasicPort& src_port) const { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); auto result = wl_bank_sink_child_pin_ids_[region_id][bank_id].find(src_port); if (result == wl_bank_sink_child_pin_ids_[region_id][bank_id].end()) { @@ -408,15 +448,17 @@ std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_ch return result->second; } -std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_source_ports(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id) const { +std::vector +MemoryBankShiftRegisterBanks::wl_shift_register_bank_source_ports( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); std::vector src_ports; size_t cur_pin = 0; for (const BasicPort& wide_port : wl_bank_data_ports(region_id, bank_id)) { for (size_t ipin = 0; ipin < wide_port.pins().size(); ++ipin) { - src_ports.push_back(BasicPort(std::string(MEMORY_WL_PORT_NAME), cur_pin, cur_pin)); + src_ports.push_back( + BasicPort(std::string(MEMORY_WL_PORT_NAME), cur_pin, cur_pin)); cur_pin++; } } @@ -424,42 +466,51 @@ std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_sour return src_ports; } -bool MemoryBankShiftRegisterBanks::valid_region_id(const ConfigRegionId& region) const { +bool MemoryBankShiftRegisterBanks::valid_region_id( + const ConfigRegionId& region) const { return size_t(region) < bl_bank_ids_.size(); } -bool MemoryBankShiftRegisterBanks::valid_bl_bank_id(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { +bool MemoryBankShiftRegisterBanks::valid_bl_bank_id( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { if (!valid_region_id(region_id)) { return false; } - return ( size_t(bank_id) < bl_bank_ids_[region_id].size() ) && ( bank_id == bl_bank_ids_[region_id][bank_id] ); + return (size_t(bank_id) < bl_bank_ids_[region_id].size()) && + (bank_id == bl_bank_ids_[region_id][bank_id]); } -bool MemoryBankShiftRegisterBanks::valid_wl_bank_id(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const { +bool MemoryBankShiftRegisterBanks::valid_wl_bank_id( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const { if (!valid_region_id(region_id)) { return false; } - return ( size_t(bank_id) < wl_bank_ids_[region_id].size() ) && ( bank_id == wl_bank_ids_[region_id][bank_id] ); + return (size_t(bank_id) < wl_bank_ids_[region_id].size()) && + (bank_id == wl_bank_ids_[region_id][bank_id]); } bool MemoryBankShiftRegisterBanks::empty() const { - return bl_bank_ids_.empty() && wl_bank_ids_.empty(); + return bl_bank_ids_.empty() && wl_bank_ids_.empty(); } void MemoryBankShiftRegisterBanks::build_bl_port_fast_lookup() const { bl_ports_to_sr_bank_ids_.resize(bl_bank_data_ports_.size()); bl_ports_to_sr_bank_ports_.resize(bl_bank_data_ports_.size()); for (const auto& region : bl_bank_data_ports_) { - for (const auto& bank : region) { + for (const auto& bank : region) { size_t cur_pin = 0; for (const auto& port : bank) { for (const size_t& bl_index : port.pins()) { - BasicPort bl_port(std::string(MEMORY_BL_PORT_NAME), bl_index, bl_index); - BasicPort sr_bl_port(std::string(MEMORY_BL_PORT_NAME), cur_pin, cur_pin); - ConfigRegionId region_id = ConfigRegionId(®ion - &bl_bank_data_ports_[ConfigRegionId(0)]); - FabricBitLineBankId bank_id = FabricBitLineBankId(&bank - ®ion[FabricBitLineBankId(0)]); - bl_ports_to_sr_bank_ids_[region_id][bl_port] = bank_id; - bl_ports_to_sr_bank_ports_[region_id][bl_port] = sr_bl_port; + BasicPort bl_port(std::string(MEMORY_BL_PORT_NAME), bl_index, + bl_index); + BasicPort sr_bl_port(std::string(MEMORY_BL_PORT_NAME), cur_pin, + cur_pin); + ConfigRegionId region_id = + ConfigRegionId(®ion - &bl_bank_data_ports_[ConfigRegionId(0)]); + FabricBitLineBankId bank_id = + FabricBitLineBankId(&bank - ®ion[FabricBitLineBankId(0)]); + bl_ports_to_sr_bank_ids_[region_id][bl_port] = bank_id; + bl_ports_to_sr_bank_ports_[region_id][bl_port] = sr_bl_port; cur_pin++; } } @@ -473,16 +524,20 @@ void MemoryBankShiftRegisterBanks::build_wl_port_fast_lookup() const { wl_ports_to_sr_bank_ids_.resize(wl_bank_data_ports_.size()); wl_ports_to_sr_bank_ports_.resize(wl_bank_data_ports_.size()); for (const auto& region : wl_bank_data_ports_) { - for (const auto& bank : region) { + for (const auto& bank : region) { size_t cur_pin = 0; for (const auto& port : bank) { for (const size_t& wl_index : port.pins()) { - BasicPort wl_port(std::string(MEMORY_WL_PORT_NAME), wl_index, wl_index); - BasicPort sr_wl_port(std::string(MEMORY_WL_PORT_NAME), cur_pin, cur_pin); - ConfigRegionId region_id = ConfigRegionId(®ion - &wl_bank_data_ports_[ConfigRegionId(0)]); - FabricWordLineBankId bank_id = FabricWordLineBankId(&bank - ®ion[FabricWordLineBankId(0)]); - wl_ports_to_sr_bank_ids_[region_id][wl_port] = bank_id; - wl_ports_to_sr_bank_ports_[region_id][wl_port] = sr_wl_port; + BasicPort wl_port(std::string(MEMORY_WL_PORT_NAME), wl_index, + wl_index); + BasicPort sr_wl_port(std::string(MEMORY_WL_PORT_NAME), cur_pin, + cur_pin); + ConfigRegionId region_id = + ConfigRegionId(®ion - &wl_bank_data_ports_[ConfigRegionId(0)]); + FabricWordLineBankId bank_id = + FabricWordLineBankId(&bank - ®ion[FabricWordLineBankId(0)]); + wl_ports_to_sr_bank_ids_[region_id][wl_port] = bank_id; + wl_ports_to_sr_bank_ports_[region_id][wl_port] = sr_wl_port; cur_pin++; } } diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.h b/openfpga/src/fabric/memory_bank_shift_register_banks.h index d6ae9e8ca..60691508f 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.h +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.h @@ -3,235 +3,311 @@ #include #include -#include "vtr_vector.h" + #include "fabric_key.h" -#include "openfpga_port.h" #include "module_manager.h" +#include "openfpga_port.h" +#include "vtr_vector.h" /* begin namespace openfpga */ namespace openfpga { /****************************************************************************** - * This files includes data structures that stores detailed information about - * shift register banks for each configuration region in the top-level module, including + * This files includes data structures that stores detailed information about + * shift register banks for each configuration region in the top-level module, + including * - Module id of each shift register bank - * - Instance id of each shift register bank - * - The connectivity of of each shift register bank to reconfigurable child under a configuration region - * - The ids of each child to be connected + * - Instance id of each shift register bank + * - The connectivity of of each shift register bank to reconfigurable child + under a configuration region + * - The ids of each child to be connected * - The Bit Line (BL) or Word Line (WL) pin id of each child - * @note This data structure is mainly used as a database for adding connections around shift register banks in top-level module + * @note This data structure is mainly used as a database for adding connections + around shift register banks in top-level module ******************************************************************************/ class MemoryBankShiftRegisterBanks { - public: /* Accessors: aggregates */ - ModuleManager::region_range regions() const; - FabricKey::fabric_bit_line_bank_range bl_banks(const ConfigRegionId& region_id) const; - FabricKey::fabric_word_line_bank_range wl_banks(const ConfigRegionId& region_id) const; - public: /* Accessors */ - /* @brief Return a list of unique sizes of shift register banks for BL protocol */ - std::vector bl_bank_unique_sizes() const; + public: /* Accessors: aggregates */ + ModuleManager::region_range regions() const; + FabricKey::fabric_bit_line_bank_range bl_banks( + const ConfigRegionId& region_id) const; + FabricKey::fabric_word_line_bank_range wl_banks( + const ConfigRegionId& region_id) const; - /* @brief Return a list of unique modules of shift register banks for BL protocol */ - std::vector bl_bank_unique_modules() const; + public: /* Accessors */ + /* @brief Return a list of unique sizes of shift register banks for BL + * protocol */ + std::vector bl_bank_unique_sizes() const; - /* @brief Return the size of a BL shift register bank */ - size_t bl_bank_size(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; + /* @brief Return a list of unique modules of shift register banks for BL + * protocol */ + std::vector bl_bank_unique_modules() const; - /* @brief Return a list of data ports which will be driven by a BL shift register bank */ - std::vector bl_bank_data_ports(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; + /* @brief Return the size of a BL shift register bank */ + size_t bl_bank_size(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id) const; - /** @brief find the BL shift register bank id to which a BL port is connected to */ - FabricBitLineBankId find_bl_shift_register_bank_id(const ConfigRegionId& region, const BasicPort& bl_port) const; + /* @brief Return a list of data ports which will be driven by a BL shift + * register bank */ + std::vector bl_bank_data_ports( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; - /** @brief find the data port of a BL shift register bank id to which a BL port is connected to */ - BasicPort find_bl_shift_register_bank_data_port(const ConfigRegionId& region, const BasicPort& bl_port) const; + /** @brief find the BL shift register bank id to which a BL port is connected + * to */ + FabricBitLineBankId find_bl_shift_register_bank_id( + const ConfigRegionId& region, const BasicPort& bl_port) const; - /** @brief Return the module id of a BL shift register bank */ - ModuleId bl_shift_register_bank_module(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id) const; + /** @brief find the data port of a BL shift register bank id to which a BL + * port is connected to */ + BasicPort find_bl_shift_register_bank_data_port( + const ConfigRegionId& region, const BasicPort& bl_port) const; - /** @brief Return the instance id of a BL shift register bank */ - size_t bl_shift_register_bank_instance(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id) const; + /** @brief Return the module id of a BL shift register bank */ + ModuleId bl_shift_register_bank_module( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; - /** @brief return the child ids at top-level module to which a data port (1-bit) of a BL shift register bank is connected to - * @note a BL may drive multiple children (children on the same column share the same BLs) - */ - std::vector bl_shift_register_bank_sink_child_ids(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const BasicPort& src_port) const; + /** @brief Return the instance id of a BL shift register bank */ + size_t bl_shift_register_bank_instance( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; - /** @brief return the child pin id of the child module at top-level module - * to which a data port (1-bit) of a BL shift register bank is connected to - * @note a BL may drive multiple children (children on the same column share the same BLs) - */ - std::vector bl_shift_register_bank_sink_child_pin_ids(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const BasicPort& src_port) const; + /** @brief return the child ids at top-level module to which a data port + * (1-bit) of a BL shift register bank is connected to + * @note a BL may drive multiple children (children on the same column share + * the same BLs) + */ + std::vector bl_shift_register_bank_sink_child_ids( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id, + const BasicPort& src_port) const; - /** @brief Return a list of single-bit ports which are the data ports of a BL shift register bank */ - std::vector bl_shift_register_bank_source_ports(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id) const; + /** @brief return the child pin id of the child module at top-level module + * to which a data port (1-bit) of a BL shift register bank is connected to + * @note a BL may drive multiple children (children on the same column share + * the same BLs) + */ + std::vector bl_shift_register_bank_sink_child_pin_ids( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id, + const BasicPort& src_port) const; - /* @brief Return a list of unique sizes of shift register banks for WL protocol */ - std::vector wl_bank_unique_sizes() const; + /** @brief Return a list of single-bit ports which are the data ports of a BL + * shift register bank */ + std::vector bl_shift_register_bank_source_ports( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; - /* @brief Return a list of unique modules of shift register banks for WL protocol */ - std::vector wl_bank_unique_modules() const; + /* @brief Return a list of unique sizes of shift register banks for WL + * protocol */ + std::vector wl_bank_unique_sizes() const; - /* @brief Return the size of a WL shift register bank */ - size_t wl_bank_size(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; + /* @brief Return a list of unique modules of shift register banks for WL + * protocol */ + std::vector wl_bank_unique_modules() const; - /* @brief Return a list of data ports which will be driven by a WL shift register bank */ - std::vector wl_bank_data_ports(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; + /* @brief Return the size of a WL shift register bank */ + size_t wl_bank_size(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id) const; - /** @brief find the WL shift register bank id to which a BL port is connected to */ - FabricWordLineBankId find_wl_shift_register_bank_id(const ConfigRegionId& region, const BasicPort& wl_port) const; + /* @brief Return a list of data ports which will be driven by a WL shift + * register bank */ + std::vector wl_bank_data_ports( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; - /** @brief find the data port of a WL shift register bank id to which a BL port is connected to */ - BasicPort find_wl_shift_register_bank_data_port(const ConfigRegionId& region, const BasicPort& wl_port) const; + /** @brief find the WL shift register bank id to which a BL port is connected + * to */ + FabricWordLineBankId find_wl_shift_register_bank_id( + const ConfigRegionId& region, const BasicPort& wl_port) const; - /** @brief Return the module id of a WL shift register bank */ - ModuleId wl_shift_register_bank_module(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id) const; + /** @brief find the data port of a WL shift register bank id to which a BL + * port is connected to */ + BasicPort find_wl_shift_register_bank_data_port( + const ConfigRegionId& region, const BasicPort& wl_port) const; - /** @brief Return the instance id of a WL shift register bank */ - size_t wl_shift_register_bank_instance(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id) const; + /** @brief Return the module id of a WL shift register bank */ + ModuleId wl_shift_register_bank_module( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; - /** @brief return the child id at top-level module to which a data port (1-bit) of a WL shift register bank is connected to - * @note a WL may drive multiple children (children on the same row share the same WLs) - */ - std::vector wl_shift_register_bank_sink_child_ids(const ConfigRegionId& region, - const FabricWordLineBankId& bank_id, - const BasicPort& src_port) const; + /** @brief Return the instance id of a WL shift register bank */ + size_t wl_shift_register_bank_instance( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; - /** @brief return the child pin id of the child module at top-level module - * to which a data port (1-bit) of a WL shift register bank is connected to - * @note a WL may drive multiple children (children on the same row share the same WLs) - */ - std::vector wl_shift_register_bank_sink_child_pin_ids(const ConfigRegionId& region, - const FabricWordLineBankId& bank_id, - const BasicPort& src_port) const; + /** @brief return the child id at top-level module to which a data port + * (1-bit) of a WL shift register bank is connected to + * @note a WL may drive multiple children (children on the same row share the + * same WLs) + */ + std::vector wl_shift_register_bank_sink_child_ids( + const ConfigRegionId& region, const FabricWordLineBankId& bank_id, + const BasicPort& src_port) const; - /** @brief Return a list of single-bit ports which are the data ports of a WL shift register bank */ - std::vector wl_shift_register_bank_source_ports(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id) const; + /** @brief return the child pin id of the child module at top-level module + * to which a data port (1-bit) of a WL shift register bank is connected to + * @note a WL may drive multiple children (children on the same row share the + * same WLs) + */ + std::vector wl_shift_register_bank_sink_child_pin_ids( + const ConfigRegionId& region, const FabricWordLineBankId& bank_id, + const BasicPort& src_port) const; - public: /* Mutators */ - void resize_regions(const size_t& num_regions); + /** @brief Return a list of single-bit ports which are the data ports of a WL + * shift register bank */ + std::vector wl_shift_register_bank_source_ports( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; - /* Reserve a number of banks to be memory efficent */ - void reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks); - void reserve_bl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks); + public: /* Mutators */ + void resize_regions(const size_t& num_regions); - /* Create a new shift register bank for BLs and return an id */ - FabricBitLineBankId create_bl_shift_register_bank(const FabricRegionId& region_id); - FabricBitLineBankId create_bl_shift_register_bank(const ConfigRegionId& region_id); + /* Reserve a number of banks to be memory efficent */ + void reserve_bl_shift_register_banks(const FabricRegionId& region_id, + const size_t& num_banks); + void reserve_bl_shift_register_banks(const ConfigRegionId& region_id, + const size_t& num_banks); - /* Add a data port to a given BL shift register bank */ - void add_data_port_to_bl_shift_register_bank(const FabricRegionId& region_id, - const FabricBitLineBankId& bank_id, - const openfpga::BasicPort& data_port); - void add_data_port_to_bl_shift_register_bank(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const openfpga::BasicPort& data_port); + /* Create a new shift register bank for BLs and return an id */ + FabricBitLineBankId create_bl_shift_register_bank( + const FabricRegionId& region_id); + FabricBitLineBankId create_bl_shift_register_bank( + const ConfigRegionId& region_id); - /* Link a BL shift register bank to a module id */ - void link_bl_shift_register_bank_to_module(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const ModuleId& module_id); + /* Add a data port to a given BL shift register bank */ + void add_data_port_to_bl_shift_register_bank( + const FabricRegionId& region_id, const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port); + void add_data_port_to_bl_shift_register_bank( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port); - /* Link a BL shift register bank to a instance id */ - void link_bl_shift_register_bank_to_instance(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const size_t& instance_id); + /* Link a BL shift register bank to a module id */ + void link_bl_shift_register_bank_to_module(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id, + const ModuleId& module_id); - /* @brief Add the child id and pin id of BL to which a shift register is connected to under a specific configuration region of top-level module */ - void add_bl_shift_register_bank_sink_node(const ConfigRegionId& region, - const FabricBitLineBankId& bank, - const BasicPort& src_port, - const size_t& sink_child_id, - const size_t& sink_child_pin_id); + /* Link a BL shift register bank to a instance id */ + void link_bl_shift_register_bank_to_instance( + const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id, + const size_t& instance_id); - /* Reserve a number of banks to be memory efficent */ - void reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks); - void reserve_wl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks); + /* @brief Add the child id and pin id of BL to which a shift register is + * connected to under a specific configuration region of top-level module */ + void add_bl_shift_register_bank_sink_node(const ConfigRegionId& region, + const FabricBitLineBankId& bank, + const BasicPort& src_port, + const size_t& sink_child_id, + const size_t& sink_child_pin_id); - /* Create a new shift register bank for WLs and return an id */ - FabricWordLineBankId create_wl_shift_register_bank(const FabricRegionId& region_id); - FabricWordLineBankId create_wl_shift_register_bank(const ConfigRegionId& region_id); + /* Reserve a number of banks to be memory efficent */ + void reserve_wl_shift_register_banks(const FabricRegionId& region_id, + const size_t& num_banks); + void reserve_wl_shift_register_banks(const ConfigRegionId& region_id, + const size_t& num_banks); - /* Add a data port to a given WL shift register bank */ - void add_data_port_to_wl_shift_register_bank(const FabricRegionId& region_id, - const FabricWordLineBankId& bank_id, - const openfpga::BasicPort& data_port); - void add_data_port_to_wl_shift_register_bank(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id, - const openfpga::BasicPort& data_port); + /* Create a new shift register bank for WLs and return an id */ + FabricWordLineBankId create_wl_shift_register_bank( + const FabricRegionId& region_id); + FabricWordLineBankId create_wl_shift_register_bank( + const ConfigRegionId& region_id); - /* Link a WL shift register bank to a module id */ - void link_wl_shift_register_bank_to_module(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id, - const ModuleId& module_id); + /* Add a data port to a given WL shift register bank */ + void add_data_port_to_wl_shift_register_bank( + const FabricRegionId& region_id, const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port); + void add_data_port_to_wl_shift_register_bank( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port); - /* Link a WL shift register bank to a instance id */ - void link_wl_shift_register_bank_to_instance(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id, - const size_t& instance_id); + /* Link a WL shift register bank to a module id */ + void link_wl_shift_register_bank_to_module( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id, + const ModuleId& module_id); - /* @brief Add the child id and pin id of WL to which a shift register is connected to under a specific configuration region of top-level module */ - void add_wl_shift_register_bank_sink_node(const ConfigRegionId& region, - const FabricWordLineBankId& bank, - const BasicPort& src_port, - const size_t& sink_child_id, - const size_t& sink_child_pin_id); + /* Link a WL shift register bank to a instance id */ + void link_wl_shift_register_bank_to_instance( + const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id, + const size_t& instance_id); - public: /* Validators */ - bool valid_region_id(const ConfigRegionId& region) const; - bool valid_bl_bank_id(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; - bool valid_wl_bank_id(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; - bool empty() const; + /* @brief Add the child id and pin id of WL to which a shift register is + * connected to under a specific configuration region of top-level module */ + void add_wl_shift_register_bank_sink_node(const ConfigRegionId& region, + const FabricWordLineBankId& bank, + const BasicPort& src_port, + const size_t& sink_child_id, + const size_t& sink_child_pin_id); - private: /* Internal Mutators */ - /** @brief Build the mapping from a BL/WL port to shift register bank and assoicated pins - * @note we use const here because the caller functions, e.g., find_bl_shift_register_bank_id(), is const - * even though it does modify internal data - */ - void build_bl_port_fast_lookup() const; - void build_wl_port_fast_lookup() const; + public: /* Validators */ + bool valid_region_id(const ConfigRegionId& region) const; + bool valid_bl_bank_id(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id) const; + bool valid_wl_bank_id(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id) const; + bool empty() const; - private: /* Internal data */ - vtr::vector config_region_ids_; + private: /* Internal Mutators */ + /** @brief Build the mapping from a BL/WL port to shift register bank and + * assoicated pins + * @note we use const here because the caller functions, e.g., + * find_bl_shift_register_bank_id(), is const even though it does modify + * internal data + */ + void build_bl_port_fast_lookup() const; + void build_wl_port_fast_lookup() const; - /* General information about the BL shift register bank */ - vtr::vector> bl_bank_ids_; - vtr::vector>> bl_bank_data_ports_; - vtr::vector> bl_bank_modules_; - vtr::vector> bl_bank_instances_; - vtr::vector>>> bl_bank_sink_child_ids_; - vtr::vector>>> bl_bank_sink_child_pin_ids_; + private: /* Internal data */ + vtr::vector config_region_ids_; - /* General information about the WL shift register bank */ - vtr::vector> wl_bank_ids_; - vtr::vector>> wl_bank_data_ports_; - vtr::vector> wl_bank_modules_; - vtr::vector> wl_bank_instances_; - vtr::vector>>> wl_bank_sink_child_ids_; - vtr::vector>>> wl_bank_sink_child_pin_ids_; + /* General information about the BL shift register bank */ + vtr::vector> + bl_bank_ids_; + vtr::vector>> + bl_bank_data_ports_; + vtr::vector> + bl_bank_modules_; + vtr::vector> + bl_bank_instances_; + vtr::vector< + ConfigRegionId, + vtr::vector>>> + bl_bank_sink_child_ids_; + vtr::vector< + ConfigRegionId, + vtr::vector>>> + bl_bank_sink_child_pin_ids_; - /* Fast look-up: given a BL/Wl port, e.g., bl[i], find out - * - the shift register bank id - * - the output pin id of the shift register bank - */ - mutable vtr::vector> bl_ports_to_sr_bank_ids_; - mutable vtr::vector> bl_ports_to_sr_bank_ports_; - mutable vtr::vector> wl_ports_to_sr_bank_ids_; - mutable vtr::vector> wl_ports_to_sr_bank_ports_; + /* General information about the WL shift register bank */ + vtr::vector> + wl_bank_ids_; + vtr::vector>> + wl_bank_data_ports_; + vtr::vector> + wl_bank_modules_; + vtr::vector> + wl_bank_instances_; + vtr::vector< + ConfigRegionId, + vtr::vector>>> + wl_bank_sink_child_ids_; + vtr::vector< + ConfigRegionId, + vtr::vector>>> + wl_bank_sink_child_pin_ids_; - /* A flag to indicate that the general information of the shift register banks have been modified, fast look-up has to be updated */ - mutable bool is_bl_bank_dirty_ = false; - mutable bool is_wl_bank_dirty_ = false; + /* Fast look-up: given a BL/Wl port, e.g., bl[i], find out + * - the shift register bank id + * - the output pin id of the shift register bank + */ + mutable vtr::vector> + bl_ports_to_sr_bank_ids_; + mutable vtr::vector> + bl_ports_to_sr_bank_ports_; + mutable vtr::vector> + wl_ports_to_sr_bank_ids_; + mutable vtr::vector> + wl_ports_to_sr_bank_ports_; + + /* A flag to indicate that the general information of the shift register banks + * have been modified, fast look-up has to be updated */ + mutable bool is_bl_bank_dirty_ = false; + mutable bool is_wl_bank_dirty_ = false; }; } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/module_manager.cpp b/openfpga/src/fabric/module_manager.cpp index e597d7c1f..b1474835a 100644 --- a/openfpga/src/fabric/module_manager.cpp +++ b/openfpga/src/fabric/module_manager.cpp @@ -1,14 +1,15 @@ /****************************************************************************** * Memember functions for data structure ModuleManager ******************************************************************************/ -#include -#include +#include "module_manager.h" + #include -#include "vtr_assert.h" -#include "vtr_log.h" +#include +#include #include "circuit_library.h" -#include "module_manager.h" +#include "vtr_assert.h" +#include "vtr_log.h" /* begin namespace openfpga */ namespace openfpga { @@ -26,29 +27,35 @@ ModuleManager::module_range ModuleManager::modules() const { } /* Find all the ports belonging to a module */ -ModuleManager::module_port_range ModuleManager::module_ports(const ModuleId& module) const { +ModuleManager::module_port_range ModuleManager::module_ports( + const ModuleId& module) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(module)); return vtr::make_range(port_ids_[module].begin(), port_ids_[module].end()); } /* Find all the nets belonging to a module */ -ModuleManager::module_net_range ModuleManager::module_nets(const ModuleId& module) const { +ModuleManager::module_net_range ModuleManager::module_nets( + const ModuleId& module) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(module)); - return vtr::make_range(module_net_iterator(ModuleNetId(0), invalid_net_ids_[module]), - module_net_iterator(ModuleNetId(num_nets_[module]), invalid_net_ids_[module])); + return vtr::make_range( + module_net_iterator(ModuleNetId(0), invalid_net_ids_[module]), + module_net_iterator(ModuleNetId(num_nets_[module]), + invalid_net_ids_[module])); } /* Find all the child modules under a parent module */ -std::vector ModuleManager::child_modules(const ModuleId& parent_module) const { +std::vector ModuleManager::child_modules( + const ModuleId& parent_module) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); return children_[parent_module]; } /* Find all the instances under a parent module */ -std::vector ModuleManager::child_module_instances(const ModuleId& parent_module, const ModuleId& child_module) const { +std::vector ModuleManager::child_module_instances( + const ModuleId& parent_module, const ModuleId& child_module) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); /* Ensure that the child module is in the child list of parent module */ @@ -57,19 +64,21 @@ std::vector ModuleManager::child_module_instances(const ModuleId& parent if (child_module == children_[parent_module][i]) { child_index = i; break; - } + } } VTR_ASSERT(child_index != children_[parent_module].size()); - + /* Create a vector, with sequentially increasing numbers */ - std::vector instance_range(num_child_instances_[parent_module][child_index], 0); + std::vector instance_range( + num_child_instances_[parent_module][child_index], 0); std::iota(instance_range.begin(), instance_range.end(), 0); return instance_range; } /* Find all the configurable child modules under a parent module */ -std::vector ModuleManager::configurable_children(const ModuleId& parent_module) const { +std::vector ModuleManager::configurable_children( + const ModuleId& parent_module) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); @@ -77,14 +86,16 @@ std::vector ModuleManager::configurable_children(const ModuleId& paren } /* Find all the instances of configurable child modules under a parent module */ -std::vector ModuleManager::configurable_child_instances(const ModuleId& parent_module) const { +std::vector ModuleManager::configurable_child_instances( + const ModuleId& parent_module) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); return configurable_child_instances_[parent_module]; } -std::vector> ModuleManager::configurable_child_coordinates(const ModuleId& parent_module) const { +std::vector> ModuleManager::configurable_child_coordinates( + const ModuleId& parent_module) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); @@ -92,7 +103,8 @@ std::vector> ModuleManager::configurable_child_coordinates(const } /* Find all the configurable child modules under a parent module */ -std::vector ModuleManager::io_children(const ModuleId& parent_module) const { +std::vector ModuleManager::io_children( + const ModuleId& parent_module) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); @@ -100,14 +112,16 @@ std::vector ModuleManager::io_children(const ModuleId& parent_module) } /* Find all the instances of configurable child modules under a parent module */ -std::vector ModuleManager::io_child_instances(const ModuleId& parent_module) const { +std::vector ModuleManager::io_child_instances( + const ModuleId& parent_module) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); return io_child_instances_[parent_module]; } -std::vector> ModuleManager::io_child_coordinates(const ModuleId& parent_module) const { +std::vector> ModuleManager::io_child_coordinates( + const ModuleId& parent_module) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); @@ -115,68 +129,84 @@ std::vector> ModuleManager::io_child_coordinates(const ModuleId& } /* Find the source ids of modules */ -ModuleManager::module_net_src_range ModuleManager::module_net_sources(const ModuleId& module, const ModuleNetId& net) const { +ModuleManager::module_net_src_range ModuleManager::module_net_sources( + const ModuleId& module, const ModuleNetId& net) const { /* Validate the module_id */ VTR_ASSERT(valid_module_net_id(module, net)); - return vtr::make_range(net_src_ids_[module][net].begin(), net_src_ids_[module][net].end()); + return vtr::make_range(net_src_ids_[module][net].begin(), + net_src_ids_[module][net].end()); } /* Find the sink ids of modules */ -ModuleManager::module_net_sink_range ModuleManager::module_net_sinks(const ModuleId& module, const ModuleNetId& net) const { +ModuleManager::module_net_sink_range ModuleManager::module_net_sinks( + const ModuleId& module, const ModuleNetId& net) const { /* Validate the module_id */ VTR_ASSERT(valid_module_net_id(module, net)); - return vtr::make_range(net_sink_ids_[module][net].begin(), net_sink_ids_[module][net].end()); + return vtr::make_range(net_sink_ids_[module][net].begin(), + net_sink_ids_[module][net].end()); } -ModuleManager::region_range ModuleManager::regions(const ModuleId& module) const { +ModuleManager::region_range ModuleManager::regions( + const ModuleId& module) const { VTR_ASSERT(valid_module_id(module)); - return vtr::make_range(config_region_ids_[module].begin(), config_region_ids_[module].end()); + return vtr::make_range(config_region_ids_[module].begin(), + config_region_ids_[module].end()); } -std::vector ModuleManager::region_configurable_children(const ModuleId& parent_module, - const ConfigRegionId& region) const { +std::vector ModuleManager::region_configurable_children( + const ModuleId& parent_module, const ConfigRegionId& region) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); VTR_ASSERT(valid_region_id(parent_module, region)); std::vector region_config_children; - region_config_children.reserve(config_region_children_[parent_module][region].size()); + region_config_children.reserve( + config_region_children_[parent_module][region].size()); - for (const size_t& child_id : config_region_children_[parent_module][region]) { - region_config_children.push_back(configurable_children_[parent_module][child_id]); - } + for (const size_t& child_id : + config_region_children_[parent_module][region]) { + region_config_children.push_back( + configurable_children_[parent_module][child_id]); + } return region_config_children; } -std::vector ModuleManager::region_configurable_child_instances(const ModuleId& parent_module, - const ConfigRegionId& region) const { +std::vector ModuleManager::region_configurable_child_instances( + const ModuleId& parent_module, const ConfigRegionId& region) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); VTR_ASSERT(valid_region_id(parent_module, region)); std::vector region_config_child_instances; - region_config_child_instances.reserve(config_region_children_[parent_module][region].size()); + region_config_child_instances.reserve( + config_region_children_[parent_module][region].size()); - for (const size_t& child_id : config_region_children_[parent_module][region]) { - region_config_child_instances.push_back(configurable_child_instances_[parent_module][child_id]); - } + for (const size_t& child_id : + config_region_children_[parent_module][region]) { + region_config_child_instances.push_back( + configurable_child_instances_[parent_module][child_id]); + } return region_config_child_instances; } -std::vector> ModuleManager::region_configurable_child_coordinates(const ModuleId& parent_module, - const ConfigRegionId& region) const { +std::vector> +ModuleManager::region_configurable_child_coordinates( + const ModuleId& parent_module, const ConfigRegionId& region) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); VTR_ASSERT(valid_region_id(parent_module, region)); std::vector> region_config_child_coordinates; - region_config_child_coordinates.reserve(config_region_children_[parent_module][region].size()); + region_config_child_coordinates.reserve( + config_region_children_[parent_module][region].size()); - for (const size_t& child_id : config_region_children_[parent_module][region]) { - region_config_child_coordinates.push_back(configurable_child_coordinates_[parent_module][child_id]); - } + for (const size_t& child_id : + config_region_children_[parent_module][region]) { + region_config_child_coordinates.push_back( + configurable_child_coordinates_[parent_module][child_id]); + } return region_config_child_coordinates; } @@ -185,9 +215,7 @@ std::vector> ModuleManager::region_configurable_child_coordinate * Public Accessors ******************************************************************************/ /* Return number of modules */ -size_t ModuleManager::num_modules() const { - return ids_.size(); -} +size_t ModuleManager::num_modules() const { return ids_.size(); } /* Return number of net of a module */ size_t ModuleManager::num_nets(const ModuleId& module) const { @@ -203,20 +231,25 @@ std::string ModuleManager::module_name(const ModuleId& module_id) const { return names_[module_id]; } -ModuleManager::e_module_usage_type ModuleManager::module_usage(const ModuleId& module_id) const { +ModuleManager::e_module_usage_type ModuleManager::module_usage( + const ModuleId& module_id) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(module_id)); return usages_[module_id]; } /* Get the string of a module port type */ -std::string ModuleManager::module_port_type_str(const enum e_module_port_type& port_type) const { - std::array MODULE_PORT_TYPE_STRING = {{"GLOBAL PORTS", "GPIN PORTS", "GPOUT PORTS", "GPIO PORTS", "INOUT PORTS", "INPUT PORTS", "OUTPUT PORTS", "CLOCK PORTS"}}; +std::string ModuleManager::module_port_type_str( + const enum e_module_port_type& port_type) const { + std::array MODULE_PORT_TYPE_STRING = { + {"GLOBAL PORTS", "GPIN PORTS", "GPOUT PORTS", "GPIO PORTS", "INOUT PORTS", + "INPUT PORTS", "OUTPUT PORTS", "CLOCK PORTS"}}; return MODULE_PORT_TYPE_STRING[port_type]; } /* Find a list of ports of a module by a given types */ -std::vector ModuleManager::module_ports_by_type(const ModuleId& module_id, const enum e_module_port_type& port_type) const { +std::vector ModuleManager::module_ports_by_type( + const ModuleId& module_id, const enum e_module_port_type& port_type) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(module_id)); @@ -233,7 +266,8 @@ std::vector ModuleManager::module_ports_by_type(const ModuleId& modul } /* Find a list of port ids of a module by a given types */ -std::vector ModuleManager::module_port_ids_by_type(const ModuleId& module_id, const enum e_module_port_type& port_type) const { +std::vector ModuleManager::module_port_ids_by_type( + const ModuleId& module_id, const enum e_module_port_type& port_type) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(module_id)); @@ -249,9 +283,9 @@ std::vector ModuleManager::module_port_ids_by_type(const ModuleId& return port_ids; } - /* Find a port of a module by a given name */ -ModulePortId ModuleManager::find_module_port(const ModuleId& module_id, const std::string& port_name) const { +ModulePortId ModuleManager::find_module_port( + const ModuleId& module_id, const std::string& port_name) const { /* Validate the module id */ VTR_ASSERT(valid_module_id(module_id)); @@ -259,7 +293,7 @@ ModulePortId ModuleManager::find_module_port(const ModuleId& module_id, const st for (const auto& port : port_ids_[module_id]) { if (0 == port_name.compare(ports_[module_id][port].get_name())) { /* Find it, return the id */ - return port; + return port; } } /* Not found, return an invalid id */ @@ -267,112 +301,128 @@ ModulePortId ModuleManager::find_module_port(const ModuleId& module_id, const st } /* Find the Port information with a given port id */ -BasicPort ModuleManager::module_port(const ModuleId& module_id, const ModulePortId& port_id) const { +BasicPort ModuleManager::module_port(const ModuleId& module_id, + const ModulePortId& port_id) const { /* Validate the module and port id */ VTR_ASSERT(valid_module_port_id(module_id, port_id)); - return ports_[module_id][port_id]; + return ports_[module_id][port_id]; } /* Find the module id by a given name, return invalid if not found */ ModuleId ModuleManager::find_module(const std::string& name) const { if (name_id_map_.find(name) != name_id_map_.end()) { /* Find it, return the id */ - return name_id_map_.at(name); + return name_id_map_.at(name); } /* Not found, return an invalid id */ return ModuleId::INVALID(); } /* Find the number of instances of a child module in the parent module */ -size_t ModuleManager::num_instance(const ModuleId& parent_module, const ModuleId& child_module) const { - size_t child_index = find_child_module_index_in_parent_module(parent_module, child_module); +size_t ModuleManager::num_instance(const ModuleId& parent_module, + const ModuleId& child_module) const { + size_t child_index = + find_child_module_index_in_parent_module(parent_module, child_module); if (size_t(-1) == child_index) { /* Not found, return a zero */ return 0; } - return num_child_instances_[parent_module][child_index]; + return num_child_instances_[parent_module][child_index]; } /* Find the instance name of a child module */ -std::string ModuleManager::instance_name(const ModuleId& parent_module, const ModuleId& child_module, +std::string ModuleManager::instance_name(const ModuleId& parent_module, + const ModuleId& child_module, const size_t& instance_id) const { /* Validate the id of both parent and child modules */ - VTR_ASSERT ( valid_module_id(parent_module) ); - VTR_ASSERT ( valid_module_id(child_module) ); + VTR_ASSERT(valid_module_id(parent_module)); + VTR_ASSERT(valid_module_id(child_module)); /* Find the index of child module in the child list of parent module */ - size_t child_index = find_child_module_index_in_parent_module(parent_module, child_module); - VTR_ASSERT (child_index < children_[parent_module].size()); + size_t child_index = + find_child_module_index_in_parent_module(parent_module, child_module); + VTR_ASSERT(child_index < children_[parent_module].size()); /* Ensure that instance id is valid */ - VTR_ASSERT (instance_id < num_instance(parent_module, child_module)); + VTR_ASSERT(instance_id < num_instance(parent_module, child_module)); return child_instance_names_[parent_module][child_index][instance_id]; } /* Find the instance id of a given instance name */ -size_t ModuleManager::instance_id(const ModuleId& parent_module, const ModuleId& child_module, +size_t ModuleManager::instance_id(const ModuleId& parent_module, + const ModuleId& child_module, const std::string& instance_name) const { /* Validate the id of both parent and child modules */ - VTR_ASSERT ( valid_module_id(parent_module) ); - VTR_ASSERT ( valid_module_id(child_module) ); + VTR_ASSERT(valid_module_id(parent_module)); + VTR_ASSERT(valid_module_id(child_module)); /* Find the index of child module in the child list of parent module */ - size_t child_index = find_child_module_index_in_parent_module(parent_module, child_module); - VTR_ASSERT (child_index < children_[parent_module].size()); + size_t child_index = + find_child_module_index_in_parent_module(parent_module, child_module); + VTR_ASSERT(child_index < children_[parent_module].size()); /* Search the instance name list and try to find a match */ - for (size_t name_id = 0; name_id < child_instance_names_[parent_module][child_index].size(); ++name_id) { - const std::string& name = child_instance_names_[parent_module][child_index][name_id]; + for (size_t name_id = 0; + name_id < child_instance_names_[parent_module][child_index].size(); + ++name_id) { + const std::string& name = + child_instance_names_[parent_module][child_index][name_id]; if (0 == name.compare(instance_name)) { return name_id; } } - + /* Not found, return an invalid name */ return size_t(-1); } -ModuleManager::e_module_port_type ModuleManager::port_type(const ModuleId& module, const ModulePortId& port) const { +ModuleManager::e_module_port_type ModuleManager::port_type( + const ModuleId& module, const ModulePortId& port) const { /* validate both module id and port id*/ VTR_ASSERT(valid_module_port_id(module, port)); return port_types_[module][port]; } /* Find if a port is a wire connection */ -bool ModuleManager::port_is_wire(const ModuleId& module, const ModulePortId& port) const { +bool ModuleManager::port_is_wire(const ModuleId& module, + const ModulePortId& port) const { /* validate both module id and port id*/ VTR_ASSERT(valid_module_port_id(module, port)); return port_is_wire_[module][port]; } /* Find if a port is a mappable i/o */ -bool ModuleManager::port_is_mappable_io(const ModuleId& module, const ModulePortId& port) const { +bool ModuleManager::port_is_mappable_io(const ModuleId& module, + const ModulePortId& port) const { /* validate both module id and port id*/ VTR_ASSERT(valid_module_port_id(module, port)); return port_is_mappable_io_[module][port]; } /* Find if a port is register */ -bool ModuleManager::port_is_register(const ModuleId& module, const ModulePortId& port) const { +bool ModuleManager::port_is_register(const ModuleId& module, + const ModulePortId& port) const { /* validate both module id and port id*/ VTR_ASSERT(valid_module_port_id(module, port)); return port_is_register_[module][port]; } /* Return the pre-processing flag of a port */ -std::string ModuleManager::port_preproc_flag(const ModuleId& module, const ModulePortId& port) const { +std::string ModuleManager::port_preproc_flag(const ModuleId& module, + const ModulePortId& port) const { /* validate both module id and port id*/ VTR_ASSERT(valid_module_port_id(module, port)); return port_preproc_flags_[module][port]; } /* Find a net from an instance of a module */ -ModuleNetId ModuleManager::module_instance_port_net(const ModuleId& parent_module, - const ModuleId& child_module, const size_t& child_instance, - const ModulePortId& child_port, const size_t& child_pin) const { +ModuleNetId ModuleManager::module_instance_port_net( + const ModuleId& parent_module, const ModuleId& child_module, + const size_t& child_instance, const ModulePortId& child_port, + const size_t& child_pin) const { /* Validate parent_module */ VTR_ASSERT(valid_module_id(parent_module)); - + /* Validate child_module */ VTR_ASSERT(valid_module_id(child_module)); @@ -389,12 +439,14 @@ ModuleNetId ModuleManager::module_instance_port_net(const ModuleId& parent_modul /* Validate child_pin */ VTR_ASSERT(child_pin < module_port(child_module, child_port).get_width()); - - return net_lookup_[parent_module][child_module][child_instance][child_port][child_pin]; + + return net_lookup_[parent_module][child_module][child_instance][child_port] + [child_pin]; } /* Find the name of net */ -std::string ModuleManager::net_name(const ModuleId& module, const ModuleNetId& net) const { +std::string ModuleManager::net_name(const ModuleId& module, + const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -402,7 +454,8 @@ std::string ModuleManager::net_name(const ModuleId& module, const ModuleNetId& n } /* Find the source modules of a net */ -vtr::vector ModuleManager::net_source_modules(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_source_modules( + const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -416,7 +469,8 @@ vtr::vector ModuleManager::net_source_modules(const Mo } /* Find the ids of source instances of a net */ -vtr::vector ModuleManager::net_source_instances(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_source_instances( + const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -424,7 +478,8 @@ vtr::vector ModuleManager::net_source_instances(const Mo } /* Find the source ports of a net */ -vtr::vector ModuleManager::net_source_ports(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_source_ports( + const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -438,17 +493,22 @@ vtr::vector ModuleManager::net_source_ports(const } /* Find the source pin indices of a net */ -vtr::vector ModuleManager::net_source_pins(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_source_pins( + const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); return net_src_pin_ids_[module][net]; } -/* Identify if a pin of a port in a module already exists in the net source list*/ -bool ModuleManager::net_source_exist(const ModuleId& module, const ModuleNetId& net, - const ModuleId& src_module, const size_t& instance_id, - const ModulePortId& src_port, const size_t& src_pin) { +/* Identify if a pin of a port in a module already exists in the net source + * list*/ +bool ModuleManager::net_source_exist(const ModuleId& module, + const ModuleNetId& net, + const ModuleId& src_module, + const size_t& instance_id, + const ModulePortId& src_port, + const size_t& src_pin) { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -457,10 +517,14 @@ bool ModuleManager::net_source_exist(const ModuleId& module, const ModuleNetId& * we can say that the source has already been added to this net! */ for (const ModuleNetSrcId& net_src : module_net_sources(module, net)) { - if ( (src_module == net_terminal_storage_[net_src_terminal_ids_[module][net][net_src]].first) - && (instance_id == net_source_instances(module, net)[net_src]) - && (src_port == net_terminal_storage_[net_src_terminal_ids_[module][net][net_src]].second) - && (src_pin == net_source_pins(module, net)[net_src]) ) { + if ((src_module == + net_terminal_storage_[net_src_terminal_ids_[module][net][net_src]] + .first) && + (instance_id == net_source_instances(module, net)[net_src]) && + (src_port == + net_terminal_storage_[net_src_terminal_ids_[module][net][net_src]] + .second) && + (src_pin == net_source_pins(module, net)[net_src])) { return true; } } @@ -470,7 +534,8 @@ bool ModuleManager::net_source_exist(const ModuleId& module, const ModuleNetId& } /* Find the sink modules of a net */ -vtr::vector ModuleManager::net_sink_modules(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_sink_modules( + const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -484,7 +549,8 @@ vtr::vector ModuleManager::net_sink_modules(const Mod } /* Find the ids of sink instances of a net */ -vtr::vector ModuleManager::net_sink_instances(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_sink_instances( + const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -492,7 +558,8 @@ vtr::vector ModuleManager::net_sink_instances(const Mod } /* Find the sink ports of a net */ -vtr::vector ModuleManager::net_sink_ports(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_sink_ports( + const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -506,7 +573,8 @@ vtr::vector ModuleManager::net_sink_ports(const M } /* Find the sink pin indices of a net */ -vtr::vector ModuleManager::net_sink_pins(const ModuleId& module, const ModuleNetId& net) const { +vtr::vector ModuleManager::net_sink_pins( + const ModuleId& module, const ModuleNetId& net) const { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -514,21 +582,28 @@ vtr::vector ModuleManager::net_sink_pins(const ModuleId } /* Identify if a pin of a port in a module already exists in the net sink list*/ -bool ModuleManager::net_sink_exist(const ModuleId& module, const ModuleNetId& net, - const ModuleId& sink_module, const size_t& instance_id, - const ModulePortId& sink_port, const size_t& sink_pin) { +bool ModuleManager::net_sink_exist(const ModuleId& module, + const ModuleNetId& net, + const ModuleId& sink_module, + const size_t& instance_id, + const ModulePortId& sink_port, + const size_t& sink_pin) { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); /* Iterate over each sink of the net. - * If a net sink has the same sink_module, instance_id, sink_port and sink_pin, - * we can say that the sink has already been added to this net! + * If a net sink has the same sink_module, instance_id, sink_port and + * sink_pin, we can say that the sink has already been added to this net! */ for (const ModuleNetSinkId& net_sink : module_net_sinks(module, net)) { - if ( (sink_module == net_terminal_storage_[net_sink_terminal_ids_[module][net][net_sink]].first) - && (instance_id == net_sink_instances(module, net)[net_sink]) - && (sink_port == net_terminal_storage_[net_sink_terminal_ids_[module][net][net_sink]].second) - && (sink_pin == net_sink_pins(module, net)[net_sink]) ) { + if ((sink_module == + net_terminal_storage_[net_sink_terminal_ids_[module][net][net_sink]] + .first) && + (instance_id == net_sink_instances(module, net)[net_sink]) && + (sink_port == + net_terminal_storage_[net_sink_terminal_ids_[module][net][net_sink]] + .second) && + (sink_pin == net_sink_pins(module, net)[net_sink])) { return true; } } @@ -540,7 +615,8 @@ bool ModuleManager::net_sink_exist(const ModuleId& module, const ModuleNetId& ne /****************************************************************************** * Private Accessors ******************************************************************************/ -size_t ModuleManager::find_child_module_index_in_parent_module(const ModuleId& parent_module, const ModuleId& child_module) const { +size_t ModuleManager::find_child_module_index_in_parent_module( + const ModuleId& parent_module, const ModuleId& child_module) const { /* validate both module ids */ VTR_ASSERT(valid_module_id(parent_module)); VTR_ASSERT(valid_module_id(child_module)); @@ -548,7 +624,7 @@ size_t ModuleManager::find_child_module_index_in_parent_module(const ModuleId& p for (size_t i = 0; i < children_[parent_module].size(); ++i) { if (child_module == children_[parent_module][i]) { /* Found, return the number of instances */ - return i; + return i; } } /* Not found: return an valid value */ @@ -560,7 +636,8 @@ size_t ModuleManager::find_child_module_index_in_parent_module(const ModuleId& p ******************************************************************************/ /* Add a module */ ModuleId ModuleManager::add_module(const std::string& name) { - /* Find if the name has been used. If used, return an invalid Id and report error! */ + /* Find if the name has been used. If used, return an invalid Id and report + * error! */ std::map::iterator it = name_id_map_.find(name); if (it != name_id_map_.end()) { return ModuleId::INVALID(); @@ -582,8 +659,8 @@ ModuleId ModuleManager::add_module(const std::string& name) { configurable_child_regions_.emplace_back(); configurable_child_coordinates_.emplace_back(); - config_region_ids_.emplace_back(); - config_region_children_.emplace_back(); + config_region_ids_.emplace_back(); + config_region_children_.emplace_back(); io_children_.emplace_back(); io_child_instances_.emplace_back(); @@ -627,10 +704,11 @@ ModuleId ModuleManager::add_module(const std::string& name) { } /* Add a port to a module */ -ModulePortId ModuleManager::add_port(const ModuleId& module, - const BasicPort& port_info, const enum e_module_port_type& port_type) { +ModulePortId ModuleManager::add_port(const ModuleId& module, + const BasicPort& port_info, + const enum e_module_port_type& port_type) { /* Validate the id of module */ - VTR_ASSERT( valid_module_id(module) ); + VTR_ASSERT(valid_module_id(module)); /* Add port and fill port attributes */ ModulePortId port = ModulePortId(port_ids_[module].size()); @@ -640,42 +718,49 @@ ModulePortId ModuleManager::add_port(const ModuleId& module, port_is_wire_[module].push_back(false); port_is_mappable_io_[module].push_back(false); port_is_register_[module].push_back(false); - port_preproc_flags_[module].emplace_back(); /* Create an empty string for the pre-processing flags */ + port_preproc_flags_[module] + .emplace_back(); /* Create an empty string for the pre-processing flags */ /* Update fast look-up for port */ port_lookup_[module][port_type].push_back(port); /* Update fast look-up for nets */ VTR_ASSERT_SAFE(1 == net_lookup_[module][module].size()); - net_lookup_[module][module][0][port].resize(port_info.get_width(), ModuleNetId::INVALID()); + net_lookup_[module][module][0][port].resize(port_info.get_width(), + ModuleNetId::INVALID()); return port; } /* Set a name for a module port */ -void ModuleManager::set_module_port_name(const ModuleId& module, const ModulePortId& module_port, +void ModuleManager::set_module_port_name(const ModuleId& module, + const ModulePortId& module_port, const std::string& port_name) { /* Validate the id of module port */ - VTR_ASSERT( valid_module_port_id(module, module_port) ); - + VTR_ASSERT(valid_module_port_id(module, module_port)); + ports_[module][module_port].set_name(port_name); } /* Set a name for a module */ -void ModuleManager::set_module_name(const ModuleId& module, const std::string& name) { +void ModuleManager::set_module_name(const ModuleId& module, + const std::string& name) { /* Validate the id of module */ - VTR_ASSERT( valid_module_id(module) ); + VTR_ASSERT(valid_module_id(module)); names_[module] = name; } -void ModuleManager::set_module_usage(const ModuleId& module, const e_module_usage_type& usage) { +void ModuleManager::set_module_usage(const ModuleId& module, + const e_module_usage_type& usage) { /* Validate the id of module */ - VTR_ASSERT( valid_module_id(module) ); + VTR_ASSERT(valid_module_id(module)); usages_[module] = usage; } /* Set a port to be a wire */ -void ModuleManager::set_port_is_wire(const ModuleId& module, const std::string& port_name, const bool& is_wire) { +void ModuleManager::set_port_is_wire(const ModuleId& module, + const std::string& port_name, + const bool& is_wire) { /* Find the port */ ModulePortId port = find_module_port(module, port_name); /* Must find something, otherwise drop an error */ @@ -684,14 +769,18 @@ void ModuleManager::set_port_is_wire(const ModuleId& module, const std::string& } /* Set a port to be a mappable I/O */ -void ModuleManager::set_port_is_mappable_io(const ModuleId& module, const ModulePortId& port_id, const bool& is_mappable_io) { +void ModuleManager::set_port_is_mappable_io(const ModuleId& module, + const ModulePortId& port_id, + const bool& is_mappable_io) { /* Must find something, otherwise drop an error */ VTR_ASSERT(valid_module_port_id(module, port_id)); port_is_mappable_io_[module][port_id] = is_mappable_io; } /* Set a port to be a register */ -void ModuleManager::set_port_is_register(const ModuleId& module, const std::string& port_name, const bool& is_register) { +void ModuleManager::set_port_is_register(const ModuleId& module, + const std::string& port_name, + const bool& is_register) { /* Find the port */ ModulePortId port = find_module_port(module, port_name); /* Must find something, otherwise drop an error */ @@ -700,26 +789,34 @@ void ModuleManager::set_port_is_register(const ModuleId& module, const std::stri } /* Set the preprocessing flag for a port */ -void ModuleManager::set_port_preproc_flag(const ModuleId& module, const ModulePortId& port, const std::string& preproc_flag) { +void ModuleManager::set_port_preproc_flag(const ModuleId& module, + const ModulePortId& port, + const std::string& preproc_flag) { /* Must find something, otherwise drop an error */ VTR_ASSERT(valid_module_port_id(module, port)); port_preproc_flags_[module][port] = preproc_flag; } /* Add a child module to a parent module */ -void ModuleManager::add_child_module(const ModuleId& parent_module, const ModuleId& child_module, const bool& is_io_child) { +void ModuleManager::add_child_module(const ModuleId& parent_module, + const ModuleId& child_module, + const bool& is_io_child) { /* Validate the id of both parent and child modules */ - VTR_ASSERT ( valid_module_id(parent_module) ); - VTR_ASSERT ( valid_module_id(child_module) ); + VTR_ASSERT(valid_module_id(parent_module)); + VTR_ASSERT(valid_module_id(child_module)); /* Try to find if the parent module is already in the list */ - std::vector::iterator parent_it = std::find(parents_[child_module].begin(), parents_[child_module].end(), parent_module); + std::vector::iterator parent_it = + std::find(parents_[child_module].begin(), parents_[child_module].end(), + parent_module); if (parent_it == parents_[child_module].end()) { /* Update the parent module of child module */ parents_[child_module].push_back(parent_module); } - std::vector::iterator child_it = std::find(children_[parent_module].begin(), children_[parent_module].end(), child_module); + std::vector::iterator child_it = + std::find(children_[parent_module].begin(), children_[parent_module].end(), + child_module); int child_instance_id = -1; if (child_it == children_[parent_module].end()) { /* Update the child module of parent module */ @@ -731,9 +828,14 @@ void ModuleManager::add_child_module(const ModuleId& parent_module, const Module child_instance_names_[parent_module].back().emplace_back(); } else { /* Increase the counter of instances */ - child_instance_id = num_child_instances_[parent_module][child_it - children_[parent_module].begin()]; - num_child_instances_[parent_module][child_it - children_[parent_module].begin()]++; - child_instance_names_[parent_module][child_it - children_[parent_module].begin()].emplace_back(); + child_instance_id = + num_child_instances_[parent_module] + [child_it - children_[parent_module].begin()]; + num_child_instances_[parent_module] + [child_it - children_[parent_module].begin()]++; + child_instance_names_[parent_module] + [child_it - children_[parent_module].begin()] + .emplace_back(); } /* Add to I/O child if needed */ @@ -746,26 +848,29 @@ void ModuleManager::add_child_module(const ModuleId& parent_module, const Module net_lookup_[parent_module][child_module].emplace_back(); /* Find the ports for the child module and update the fast look-up */ for (ModulePortId child_port : port_ids_[child_module]) { - net_lookup_[parent_module][child_module][instance_id][child_port].resize(ports_[child_module][child_port].get_width(), ModuleNetId::INVALID()); - } + net_lookup_[parent_module][child_module][instance_id][child_port].resize( + ports_[child_module][child_port].get_width(), ModuleNetId::INVALID()); + } } /* Set the instance name of a child module */ -void ModuleManager::set_child_instance_name(const ModuleId& parent_module, - const ModuleId& child_module, - const size_t& instance_id, +void ModuleManager::set_child_instance_name(const ModuleId& parent_module, + const ModuleId& child_module, + const size_t& instance_id, const std::string& instance_name) { /* Validate the id of both parent and child modules */ - VTR_ASSERT ( valid_module_id(parent_module) ); - VTR_ASSERT ( valid_module_id(child_module) ); + VTR_ASSERT(valid_module_id(parent_module)); + VTR_ASSERT(valid_module_id(child_module)); /* Ensure that the instance id is in range */ - VTR_ASSERT ( instance_id < num_instance(parent_module, child_module)); + VTR_ASSERT(instance_id < num_instance(parent_module, child_module)); /* Try to find the child_module in the children list of parent_module*/ - size_t child_index = find_child_module_index_in_parent_module(parent_module, child_module); + size_t child_index = + find_child_module_index_in_parent_module(parent_module, child_module); /* We must find something! */ VTR_ASSERT(size_t(-1) != child_index); /* Set the name */ - child_instance_names_[parent_module][child_index][instance_id] = instance_name; + child_instance_names_[parent_module][child_index][instance_id] = + instance_name; } /* Add a configurable child module to module @@ -773,26 +878,28 @@ void ModuleManager::set_child_instance_name(const ModuleId& parent_module, * It will check if the child module does exist in the parent module * And the instance id is in range or not */ -void ModuleManager::add_configurable_child(const ModuleId& parent_module, - const ModuleId& child_module, +void ModuleManager::add_configurable_child(const ModuleId& parent_module, + const ModuleId& child_module, const size_t& child_instance, const vtr::Point coord) { /* Validate the id of both parent and child modules */ - VTR_ASSERT ( valid_module_id(parent_module) ); - VTR_ASSERT ( valid_module_id(child_module) ); + VTR_ASSERT(valid_module_id(parent_module)); + VTR_ASSERT(valid_module_id(child_module)); /* Ensure that the instance id is in range */ - VTR_ASSERT ( child_instance < num_instance(parent_module, child_module)); + VTR_ASSERT(child_instance < num_instance(parent_module, child_module)); configurable_children_[parent_module].push_back(child_module); configurable_child_instances_[parent_module].push_back(child_instance); - configurable_child_regions_[parent_module].push_back(ConfigRegionId::INVALID()); + configurable_child_regions_[parent_module].push_back( + ConfigRegionId::INVALID()); configurable_child_coordinates_[parent_module].push_back(coord); } void ModuleManager::reserve_configurable_child(const ModuleId& parent_module, const size_t& num_children) { - VTR_ASSERT ( valid_module_id(parent_module) ); - /* Do reserve when the number of children is larger than current size of lists */ + VTR_ASSERT(valid_module_id(parent_module)); + /* Do reserve when the number of children is larger than current size of lists + */ if (num_children > configurable_children_[parent_module].size()) { configurable_children_[parent_module].reserve(num_children); } @@ -809,56 +916,63 @@ void ModuleManager::reserve_configurable_child(const ModuleId& parent_module, ConfigRegionId ModuleManager::add_config_region(const ModuleId& module) { /* Validate the module id */ - VTR_ASSERT ( valid_module_id(module) ); + VTR_ASSERT(valid_module_id(module)); /* Create an new id */ - ConfigRegionId config_region_id = ConfigRegionId(config_region_ids_[module].size()); + ConfigRegionId config_region_id = + ConfigRegionId(config_region_ids_[module].size()); config_region_ids_[module].push_back(config_region_id); - + config_region_children_[module].emplace_back(); return config_region_id; } -void ModuleManager::add_configurable_child_to_region(const ModuleId& parent_module, - const ConfigRegionId& config_region, - const ModuleId& child_module, - const size_t& child_instance, - const size_t& config_child_id) { +void ModuleManager::add_configurable_child_to_region( + const ModuleId& parent_module, const ConfigRegionId& config_region, + const ModuleId& child_module, const size_t& child_instance, + const size_t& config_child_id) { /* Validate the module id */ - VTR_ASSERT ( valid_module_id(parent_module) ); - VTR_ASSERT ( valid_module_id(child_module) ); - VTR_ASSERT ( valid_region_id(parent_module, config_region) ); + VTR_ASSERT(valid_module_id(parent_module)); + VTR_ASSERT(valid_module_id(child_module)); + VTR_ASSERT(valid_region_id(parent_module, config_region)); /* Ensure that the child module is in the configurable children list */ - VTR_ASSERT(child_module == configurable_children(parent_module)[config_child_id]); - VTR_ASSERT(child_instance == configurable_child_instances(parent_module)[config_child_id]); + VTR_ASSERT(child_module == + configurable_children(parent_module)[config_child_id]); + VTR_ASSERT(child_instance == + configurable_child_instances(parent_module)[config_child_id]); /* If the child is already in another region, error out */ - if ( (true == valid_region_id(parent_module, configurable_child_regions_[parent_module][config_child_id])) - && (config_region != configurable_child_regions_[parent_module][config_child_id]) ) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Try to add a configurable child '%s[%lu]' to region '%lu' which is already added to another region '%lu'!\n", - module_name(child_module).c_str(), - child_instance, - size_t(config_region), - size_t(configurable_child_regions_[parent_module][config_child_id])); + if ((true == + valid_region_id( + parent_module, + configurable_child_regions_[parent_module][config_child_id])) && + (config_region != + configurable_child_regions_[parent_module][config_child_id])) { + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Try to add a configurable child '%s[%lu]' to region '%lu' which is " + "already added to another region '%lu'!\n", + module_name(child_module).c_str(), child_instance, size_t(config_region), + size_t(configurable_child_regions_[parent_module][config_child_id])); exit(1); } /* Passed all the checks, add the child to the region */ - config_region_children_[parent_module][config_region].push_back(config_child_id); + config_region_children_[parent_module][config_region].push_back( + config_child_id); } -void ModuleManager::add_io_child(const ModuleId& parent_module, - const ModuleId& child_module, +void ModuleManager::add_io_child(const ModuleId& parent_module, + const ModuleId& child_module, const size_t& child_instance, const vtr::Point coord) { /* Validate the id of both parent and child modules */ - VTR_ASSERT ( valid_module_id(parent_module) ); - VTR_ASSERT ( valid_module_id(child_module) ); + VTR_ASSERT(valid_module_id(parent_module)); + VTR_ASSERT(valid_module_id(child_module)); /* Ensure that the instance id is in range */ - VTR_ASSERT ( child_instance < num_instance(parent_module, child_module)); + VTR_ASSERT(child_instance < num_instance(parent_module, child_module)); io_children_[parent_module].push_back(child_module); io_child_instances_[parent_module].push_back(child_instance); @@ -867,8 +981,9 @@ void ModuleManager::add_io_child(const ModuleId& parent_module, void ModuleManager::reserve_io_child(const ModuleId& parent_module, const size_t& num_children) { - VTR_ASSERT ( valid_module_id(parent_module) ); - /* Do reserve when the number of children is larger than current size of lists */ + VTR_ASSERT(valid_module_id(parent_module)); + /* Do reserve when the number of children is larger than current size of lists + */ if (num_children > io_children_[parent_module].size()) { io_children_[parent_module].reserve(num_children); } @@ -883,7 +998,7 @@ void ModuleManager::reserve_io_child(const ModuleId& parent_module, void ModuleManager::reserve_module_nets(const ModuleId& module, const size_t& num_nets) { /* Validate the module id */ - VTR_ASSERT ( valid_module_id(module) ); + VTR_ASSERT(valid_module_id(module)); net_names_[module].reserve(num_nets); net_src_ids_[module].reserve(num_nets); @@ -897,15 +1012,15 @@ void ModuleManager::reserve_module_nets(const ModuleId& module, net_sink_pin_ids_[module].reserve(num_nets); } -/* Add a net to the connection graph of the module */ +/* Add a net to the connection graph of the module */ ModuleNetId ModuleManager::create_module_net(const ModuleId& module) { /* Validate the module id */ - VTR_ASSERT ( valid_module_id(module) ); + VTR_ASSERT(valid_module_id(module)); /* Create an new id */ ModuleNetId net = ModuleNetId(num_nets_[module]); num_nets_[module]++; - + /* Allocate net-related data structures */ net_names_[module].emplace_back(); net_src_ids_[module].emplace_back(); @@ -936,7 +1051,8 @@ void ModuleManager::set_net_name(const ModuleId& module, const ModuleNetId& net, net_names_[module][net] = name; } -void ModuleManager::reserve_module_net_sources(const ModuleId& module, const ModuleNetId& net, +void ModuleManager::reserve_module_net_sources(const ModuleId& module, + const ModuleNetId& net, const size_t& num_sources) { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -948,9 +1064,10 @@ void ModuleManager::reserve_module_net_sources(const ModuleId& module, const Mod } /* Add a source to a net in the connection graph */ -ModuleNetSrcId ModuleManager::add_module_net_source(const ModuleId& module, const ModuleNetId& net, - const ModuleId& src_module, const size_t& instance_id, - const ModulePortId& src_port, const size_t& src_pin) { +ModuleNetSrcId ModuleManager::add_module_net_source( + const ModuleId& module, const ModuleNetId& net, const ModuleId& src_module, + const size_t& instance_id, const ModulePortId& src_port, + const size_t& src_pin) { /* Validate the module and net id */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -969,15 +1086,15 @@ ModuleNetSrcId ModuleManager::add_module_net_source(const ModuleId& module, cons * Otherwise, add the pair */ std::pair terminal(src_module, src_port); - std::vector>::iterator it = std::find(net_terminal_storage_.begin(), - net_terminal_storage_.end(), - terminal); + std::vector>::iterator it = std::find( + net_terminal_storage_.begin(), net_terminal_storage_.end(), terminal); if (it == net_terminal_storage_.end()) { net_src_terminal_ids_[module][net].push_back(net_terminal_storage_.size()); net_terminal_storage_.push_back(terminal); } else { - VTR_ASSERT_SAFE(it != net_terminal_storage_.end()); - net_src_terminal_ids_[module][net].push_back(std::distance(net_terminal_storage_.begin(), it)); + VTR_ASSERT_SAFE(it != net_terminal_storage_.end()); + net_src_terminal_ids_[module][net].push_back( + std::distance(net_terminal_storage_.begin(), it)); } /* if it has the same id as module, our instance id will be by default 0 */ @@ -987,9 +1104,9 @@ ModuleNetSrcId ModuleManager::add_module_net_source(const ModuleId& module, cons net_src_instance_ids_[module][net].push_back(src_instance_id); } else { /* Check the instance id of the src module */ - VTR_ASSERT (src_instance_id < num_instance(module, src_module)); + VTR_ASSERT(src_instance_id < num_instance(module, src_module)); net_src_instance_ids_[module][net].push_back(src_instance_id); - } + } /* Validate the pin id is in the range of the port width */ VTR_ASSERT(src_pin < module_port(src_module, src_port).get_width()); @@ -1001,7 +1118,8 @@ ModuleNetSrcId ModuleManager::add_module_net_source(const ModuleId& module, cons return net_src; } -void ModuleManager::reserve_module_net_sinks(const ModuleId& module, const ModuleNetId& net, +void ModuleManager::reserve_module_net_sinks(const ModuleId& module, + const ModuleNetId& net, const size_t& num_sinks) { /* Validate module net */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -1013,9 +1131,10 @@ void ModuleManager::reserve_module_net_sinks(const ModuleId& module, const Modul } /* Add a sink to a net in the connection graph */ -ModuleNetSinkId ModuleManager::add_module_net_sink(const ModuleId& module, const ModuleNetId& net, - const ModuleId& sink_module, const size_t& instance_id, - const ModulePortId& sink_port, const size_t& sink_pin) { +ModuleNetSinkId ModuleManager::add_module_net_sink( + const ModuleId& module, const ModuleNetId& net, const ModuleId& sink_module, + const size_t& instance_id, const ModulePortId& sink_port, + const size_t& sink_pin) { /* Validate the module and net id */ VTR_ASSERT(valid_module_net_id(module, net)); @@ -1034,15 +1153,15 @@ ModuleNetSinkId ModuleManager::add_module_net_sink(const ModuleId& module, const * Otherwise, add the pair */ std::pair terminal(sink_module, sink_port); - std::vector>::iterator it = std::find(net_terminal_storage_.begin(), - net_terminal_storage_.end(), - terminal); + std::vector>::iterator it = std::find( + net_terminal_storage_.begin(), net_terminal_storage_.end(), terminal); if (it == net_terminal_storage_.end()) { net_sink_terminal_ids_[module][net].push_back(net_terminal_storage_.size()); net_terminal_storage_.push_back(terminal); } else { - VTR_ASSERT_SAFE(it != net_terminal_storage_.end()); - net_sink_terminal_ids_[module][net].push_back(std::distance(net_terminal_storage_.begin(), it)); + VTR_ASSERT_SAFE(it != net_terminal_storage_.end()); + net_sink_terminal_ids_[module][net].push_back( + std::distance(net_terminal_storage_.begin(), it)); } /* if it has the same id as module, our instance id will be by default 0 */ @@ -1052,9 +1171,9 @@ ModuleNetSinkId ModuleManager::add_module_net_sink(const ModuleId& module, const net_sink_instance_ids_[module][net].push_back(sink_instance_id); } else { /* Check the instance id of the src module */ - VTR_ASSERT (sink_instance_id < num_instance(module, sink_module)); + VTR_ASSERT(sink_instance_id < num_instance(module, sink_module)); net_sink_instance_ids_[module][net].push_back(sink_instance_id); - } + } /* Validate the pin id is in the range of the port width */ VTR_ASSERT(sink_pin < module_port(sink_module, sink_port).get_width()); @@ -1097,31 +1216,34 @@ void ModuleManager::clear_io_children(const ModuleId& parent_module) { * Private validators/invalidators ******************************************************************************/ bool ModuleManager::valid_module_id(const ModuleId& module) const { - return ( size_t(module) < ids_.size() ) && ( module == ids_[module] ); + return (size_t(module) < ids_.size()) && (module == ids_[module]); } -bool ModuleManager::valid_module_port_id(const ModuleId& module, const ModulePortId& port) const { +bool ModuleManager::valid_module_port_id(const ModuleId& module, + const ModulePortId& port) const { if (false == valid_module_id(module)) { return false; } - return ( size_t(port) < port_ids_[module].size() ) && ( port == port_ids_[module][port] ); + return (size_t(port) < port_ids_[module].size()) && + (port == port_ids_[module][port]); } -bool ModuleManager::valid_module_net_id(const ModuleId& module, const ModuleNetId& net) const { +bool ModuleManager::valid_module_net_id(const ModuleId& module, + const ModuleNetId& net) const { if (false == valid_module_id(module)) { return false; } - return ( size_t(net) < num_nets_[module] ); + return (size_t(net) < num_nets_[module]); } bool ModuleManager::valid_module_instance_id(const ModuleId& parent_module, const ModuleId& child_module, const size_t& instance_id) const { - if ( (false == valid_module_id(parent_module)) - || (false == valid_module_id(child_module))) { + if ((false == valid_module_id(parent_module)) || + (false == valid_module_id(child_module))) { return false; } - return ( instance_id < num_instance(parent_module, child_module) ); + return (instance_id < num_instance(parent_module, child_module)); } bool ModuleManager::valid_region_id(const ModuleId& module, @@ -1129,19 +1251,14 @@ bool ModuleManager::valid_region_id(const ModuleId& module, if (false == valid_module_id(module)) { return false; } - return ( size_t(region) < config_region_ids_[module].size() ) && ( region == config_region_ids_[module][region] ); + return (size_t(region) < config_region_ids_[module].size()) && + (region == config_region_ids_[module][region]); } -void ModuleManager::invalidate_name2id_map() { - name_id_map_.clear(); -} +void ModuleManager::invalidate_name2id_map() { name_id_map_.clear(); } -void ModuleManager::invalidate_port_lookup() { - port_lookup_.clear(); -} +void ModuleManager::invalidate_port_lookup() { port_lookup_.clear(); } -void ModuleManager::invalidate_net_lookup() { - net_lookup_.clear(); -} +void ModuleManager::invalidate_net_lookup() { net_lookup_.clear(); } } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/module_manager.h b/openfpga/src/fabric/module_manager.h index 49d32d6e1..4c12873af 100644 --- a/openfpga/src/fabric/module_manager.h +++ b/openfpga/src/fabric/module_manager.h @@ -1,451 +1,605 @@ #ifndef MODULE_MANAGER_H #define MODULE_MANAGER_H -#include #include +#include #include -#include #include +#include -#include "vtr_vector.h" -#include "vtr_geometry.h" #include "module_manager_fwd.h" #include "openfpga_port.h" +#include "vtr_geometry.h" +#include "vtr_vector.h" /* begin namespace openfpga */ namespace openfpga { /****************************************************************************** * This files includes data structures for module management. - * It keeps a list of modules that have been generated, the port map of the modules, - * parents and children of each modules. This will ease instanciation of modules - * with explicit port map and outputting a hierarchy of modules + * It keeps a list of modules that have been generated, the port map of the + *modules, parents and children of each modules. This will ease instanciation of + *modules with explicit port map and outputting a hierarchy of modules * * Module includes the basic information: * 1. unique identifier - * 2. module name: which should be unique + * 2. module name: which should be unique * 3. port list: basic information of all the ports belonging to the module * 4. port types: types of each port, which will matter how we output the ports * 5. parent modules: ids of parent modules - * 6. children modules: ids of child modules + * 6. children modules: ids of child modules ******************************************************************************/ class ModuleManager { - public: /* Private data structures */ - /* A type to indicate the usage of ports - * Test bench generator use this to identify - * what signals to drive - */ - enum e_module_port_type { - MODULE_GLOBAL_PORT, /* Global inputs */ - MODULE_GPIN_PORT, /* General-purpose input */ - MODULE_GPOUT_PORT, /* General-purpose outputs, could be used for spypads */ - MODULE_GPIO_PORT, /* General-purpose IOs, which are data IOs of the fabric */ - MODULE_INOUT_PORT, /* Normal (non-global) inout ports */ - MODULE_INPUT_PORT, /* Normal (non-global) input ports */ - MODULE_OUTPUT_PORT, /* Normal (non-global) output ports */ - MODULE_CLOCK_PORT, /* Normal (non-global) clock ports*/ - NUM_MODULE_PORT_TYPES - }; + public: /* Private data structures */ + /* A type to indicate the usage of ports + * Test bench generator use this to identify + * what signals to drive + */ + enum e_module_port_type { + MODULE_GLOBAL_PORT, /* Global inputs */ + MODULE_GPIN_PORT, /* General-purpose input */ + MODULE_GPOUT_PORT, /* General-purpose outputs, could be used for spypads */ + MODULE_GPIO_PORT, /* General-purpose IOs, which are data IOs of the fabric + */ + MODULE_INOUT_PORT, /* Normal (non-global) inout ports */ + MODULE_INPUT_PORT, /* Normal (non-global) input ports */ + MODULE_OUTPUT_PORT, /* Normal (non-global) output ports */ + MODULE_CLOCK_PORT, /* Normal (non-global) clock ports*/ + NUM_MODULE_PORT_TYPES + }; - /* A type to indicate the usage of module - * This helps FPGA-SPICE to identify which VDD/VSS - * port should be applied to modules - */ - enum e_module_usage_type { - MODULE_TOP, /* Top-level module */ - MODULE_CONFIG, /* Configuration modules, i.e., decoders, sram etc. */ - MODULE_INTERC, /* Programmable interconnection, e.g., routing multiplexer etc. */ - MODULE_GRID, /* Grids (programmable blocks) */ - MODULE_LUT, /* Look-Up Table (LUT) modules */ - MODULE_HARD_IP, /* Hard IP modules */ - MODULE_SB, /* Switch block modules */ - MODULE_CB, /* Connection block modules */ - MODULE_IO, /* I/O modules */ - MODULE_VDD, /* Local VDD lines to generate constant voltages */ - MODULE_VSS, /* Local VSS lines to generate constant voltages */ - NUM_MODULE_USAGE_TYPES - }; + /* A type to indicate the usage of module + * This helps FPGA-SPICE to identify which VDD/VSS + * port should be applied to modules + */ + enum e_module_usage_type { + MODULE_TOP, /* Top-level module */ + MODULE_CONFIG, /* Configuration modules, i.e., decoders, sram etc. */ + MODULE_INTERC, /* Programmable interconnection, e.g., routing multiplexer + etc. */ + MODULE_GRID, /* Grids (programmable blocks) */ + MODULE_LUT, /* Look-Up Table (LUT) modules */ + MODULE_HARD_IP, /* Hard IP modules */ + MODULE_SB, /* Switch block modules */ + MODULE_CB, /* Connection block modules */ + MODULE_IO, /* I/O modules */ + MODULE_VDD, /* Local VDD lines to generate constant voltages */ + MODULE_VSS, /* Local VSS lines to generate constant voltages */ + NUM_MODULE_USAGE_TYPES + }; - public: /* Public Constructors */ + public: /* Public Constructors */ + public: /* Type implementations */ + /* + * This class (forward delcared above) is a template used to represent a + * lazily calculated iterator of the specified ID type. The key assumption + * made is that the ID space is contiguous and can be walked by incrementing + * the underlying ID value. To account for invalid IDs, it keeps a reference + * to the invalid ID set and returns ID::INVALID() for ID values in the set. + * + * It is used to lazily create an iteration range (e.g. as returned by + * RRGraph::edges() RRGraph::nodes()) just based on the count of allocated + * elements (i.e. RRGraph::num_nodes_ or RRGraph::num_edges_), and the set of + * any invalid IDs (i.e. RRGraph::invalid_node_ids_, + * RRGraph::invalid_edge_ids_). + */ + template + class lazy_id_iterator + : public std::iterator { + public: + // Since we pass ID as a template to std::iterator we need to use an + // explicit 'typename' to bring the value_type and iterator names into scope + typedef + typename std::iterator::value_type + value_type; + typedef + typename std::iterator::iterator + iterator; - public: /* Type implementations */ - /* - * This class (forward delcared above) is a template used to represent a lazily calculated - * iterator of the specified ID type. The key assumption made is that the ID space is - * contiguous and can be walked by incrementing the underlying ID value. To account for - * invalid IDs, it keeps a reference to the invalid ID set and returns ID::INVALID() for - * ID values in the set. - * - * It is used to lazily create an iteration range (e.g. as returned by RRGraph::edges() RRGraph::nodes()) - * just based on the count of allocated elements (i.e. RRGraph::num_nodes_ or RRGraph::num_edges_), - * and the set of any invalid IDs (i.e. RRGraph::invalid_node_ids_, RRGraph::invalid_edge_ids_). - */ - template - class lazy_id_iterator : public std::iterator { - public: - //Since we pass ID as a template to std::iterator we need to use an explicit 'typename' - //to bring the value_type and iterator names into scope - typedef typename std::iterator::value_type value_type; - typedef typename std::iterator::iterator iterator; + lazy_id_iterator(value_type init, const std::unordered_set& invalid_ids) + : value_(init), invalid_ids_(invalid_ids) {} - lazy_id_iterator(value_type init, const std::unordered_set& invalid_ids) - : value_(init) - , invalid_ids_(invalid_ids) {} + // Advance to the next ID value + iterator operator++() { + value_ = ID(size_t(value_) + 1); + return *this; + } - //Advance to the next ID value - iterator operator++() { - value_ = ID(size_t(value_) + 1); - return *this; - } + // Advance to the previous ID value + iterator operator--() { + value_ = ID(size_t(value_) - 1); + return *this; + } - //Advance to the previous ID value - iterator operator--() { - value_ = ID(size_t(value_) - 1); - return *this; - } + // Dereference the iterator + value_type operator*() const { + return (invalid_ids_.count(value_)) ? ID::INVALID() : value_; + } - //Dereference the iterator - value_type operator*() const { return (invalid_ids_.count(value_)) ? ID::INVALID() : value_; } + friend bool operator==(const lazy_id_iterator lhs, + const lazy_id_iterator rhs) { + return lhs.value_ == rhs.value_; + } + friend bool operator!=(const lazy_id_iterator lhs, + const lazy_id_iterator rhs) { + return !(lhs == rhs); + } - friend bool operator==(const lazy_id_iterator lhs, const lazy_id_iterator rhs) { return lhs.value_ == rhs.value_; } - friend bool operator!=(const lazy_id_iterator lhs, const lazy_id_iterator rhs) { return !(lhs == rhs); } + private: + value_type value_; + const std::unordered_set& invalid_ids_; + }; - private: - value_type value_; - const std::unordered_set& invalid_ids_; - }; + public: /* Types and ranges */ + // Lazy iterator utility forward declaration + template + class lazy_id_iterator; - public: /* Types and ranges */ - //Lazy iterator utility forward declaration - template - class lazy_id_iterator; + typedef vtr::vector::const_iterator module_iterator; + typedef vtr::vector::const_iterator + module_port_iterator; + typedef lazy_id_iterator module_net_iterator; + typedef vtr::vector::const_iterator + module_net_src_iterator; + typedef vtr::vector::const_iterator + module_net_sink_iterator; + typedef vtr::vector::const_iterator + region_iterator; - typedef vtr::vector::const_iterator module_iterator; - typedef vtr::vector::const_iterator module_port_iterator; - typedef lazy_id_iterator module_net_iterator; - typedef vtr::vector::const_iterator module_net_src_iterator; - typedef vtr::vector::const_iterator module_net_sink_iterator; - typedef vtr::vector::const_iterator region_iterator; + typedef vtr::Range module_range; + typedef vtr::Range module_port_range; + typedef vtr::Range module_net_range; + typedef vtr::Range module_net_src_range; + typedef vtr::Range module_net_sink_range; + typedef vtr::Range region_range; - typedef vtr::Range module_range; - typedef vtr::Range module_port_range; - typedef vtr::Range module_net_range; - typedef vtr::Range module_net_src_range; - typedef vtr::Range module_net_sink_range; - typedef vtr::Range region_range; + public: /* Public aggregators */ + /* Find all the modules */ + module_range modules() const; + /* Find all the ports belonging to a module */ + module_port_range module_ports(const ModuleId& module) const; + /* Find all the nets belonging to a module */ + module_net_range module_nets(const ModuleId& module) const; + /* Find all the child modules under a parent module */ + std::vector child_modules(const ModuleId& parent_module) const; + /* Find all the instances under a parent module */ + std::vector child_module_instances( + const ModuleId& parent_module, const ModuleId& child_module) const; + /* Find all the configurable child modules under a parent module */ + std::vector configurable_children( + const ModuleId& parent_module) const; + /* Find all the instances of configurable child modules under a parent module + */ + std::vector configurable_child_instances( + const ModuleId& parent_module) const; + /* Find the coordindate of a configurable child module under a parent module + */ + std::vector> configurable_child_coordinates( + const ModuleId& parent_module) const; - public: /* Public aggregators */ - /* Find all the modules */ - module_range modules() const; - /* Find all the ports belonging to a module */ - module_port_range module_ports(const ModuleId& module) const; - /* Find all the nets belonging to a module */ - module_net_range module_nets(const ModuleId& module) const; - /* Find all the child modules under a parent module */ - std::vector child_modules(const ModuleId& parent_module) const; - /* Find all the instances under a parent module */ - std::vector child_module_instances(const ModuleId& parent_module, const ModuleId& child_module) const; - /* Find all the configurable child modules under a parent module */ - std::vector configurable_children(const ModuleId& parent_module) const; - /* Find all the instances of configurable child modules under a parent module */ - std::vector configurable_child_instances(const ModuleId& parent_module) const; - /* Find the coordindate of a configurable child module under a parent module */ - std::vector> configurable_child_coordinates(const ModuleId& parent_module) const; + /* Find all the I/O child modules under a parent module */ + std::vector io_children(const ModuleId& parent_module) const; + /* Find all the instances of I/O child modules under a parent module */ + std::vector io_child_instances(const ModuleId& parent_module) const; + /* Find the coordindate of an I/O child module under a parent module */ + std::vector> io_child_coordinates( + const ModuleId& parent_module) const; - /* Find all the I/O child modules under a parent module */ - std::vector io_children(const ModuleId& parent_module) const; - /* Find all the instances of I/O child modules under a parent module */ - std::vector io_child_instances(const ModuleId& parent_module) const; - /* Find the coordindate of an I/O child module under a parent module */ - std::vector> io_child_coordinates(const ModuleId& parent_module) const; + /* Find the source ids of modules */ + module_net_src_range module_net_sources(const ModuleId& module, + const ModuleNetId& net) const; + /* Find the sink ids of modules */ + module_net_sink_range module_net_sinks(const ModuleId& module, + const ModuleNetId& net) const; - /* Find the source ids of modules */ - module_net_src_range module_net_sources(const ModuleId& module, const ModuleNetId& net) const; - /* Find the sink ids of modules */ - module_net_sink_range module_net_sinks(const ModuleId& module, const ModuleNetId& net) const; + /* Find all the regions */ + region_range regions(const ModuleId& module) const; + /* Find all the configurable child modules under a region of a parent module + */ + std::vector region_configurable_children( + const ModuleId& parent_module, const ConfigRegionId& region) const; + /* Find all the instances of configurable child modules under a region of a + * parent module */ + std::vector region_configurable_child_instances( + const ModuleId& parent_module, const ConfigRegionId& region) const; - /* Find all the regions */ - region_range regions(const ModuleId& module) const; - /* Find all the configurable child modules under a region of a parent module */ - std::vector region_configurable_children(const ModuleId& parent_module, - const ConfigRegionId& region) const; - /* Find all the instances of configurable child modules under a region of a parent module */ - std::vector region_configurable_child_instances(const ModuleId& parent_module, - const ConfigRegionId& region) const; + /* Find all the coordinates of configurable child modules under a region of a + * parent module */ + std::vector> region_configurable_child_coordinates( + const ModuleId& parent_module, const ConfigRegionId& region) const; - /* Find all the coordinates of configurable child modules under a region of a parent module */ - std::vector> region_configurable_child_coordinates(const ModuleId& parent_module, - const ConfigRegionId& region) const; - - public: /* Public accessors */ - size_t num_modules() const; - size_t num_nets(const ModuleId& module) const; - std::string module_name(const ModuleId& module_id) const; - e_module_usage_type module_usage(const ModuleId& module_id) const; - std::string module_port_type_str(const enum e_module_port_type& port_type) const; - std::vector module_ports_by_type(const ModuleId& module_id, const enum e_module_port_type& port_type) const; - std::vector module_port_ids_by_type(const ModuleId& module_id, const enum e_module_port_type& port_type) const; - /* Find a port of a module by a given name */ - ModulePortId find_module_port(const ModuleId& module_id, const std::string& port_name) const; - /* Find the Port information with a given port id */ - BasicPort module_port(const ModuleId& module_id, const ModulePortId& port_id) const; - /* Find a module by a given name */ - ModuleId find_module(const std::string& name) const; - /* Find the number of instances of a child module in the parent module */ - size_t num_instance(const ModuleId& parent_module, const ModuleId& child_module) const; - /* Find the instance name of a child module */ - std::string instance_name(const ModuleId& parent_module, const ModuleId& child_module, - const size_t& instance_id) const; - /* Find the instance id of a given instance name */ - size_t instance_id(const ModuleId& parent_module, const ModuleId& child_module, - const std::string& instance_name) const; - /* Find the type of a port */ - ModuleManager::e_module_port_type port_type(const ModuleId& module, const ModulePortId& port) const; - /* Find if a port is a wire connection */ - bool port_is_wire(const ModuleId& module, const ModulePortId& port) const; - /* Find if a port is mappable to an I/O from users' implementations */ - bool port_is_mappable_io(const ModuleId& module, const ModulePortId& port) const; - /* Find if a port is register */ - bool port_is_register(const ModuleId& module, const ModulePortId& port) const; - /* Return the pre-processing flag of a port */ - std::string port_preproc_flag(const ModuleId& module, const ModulePortId& port) const; - /* Find a net from an instance of a module */ - ModuleNetId module_instance_port_net(const ModuleId& parent_module, - const ModuleId& child_module, const size_t& child_instance, - const ModulePortId& child_port, const size_t& child_pin) const; - /* Find the name of net */ - std::string net_name(const ModuleId& module, const ModuleNetId& net) const; - /* Find the source modules of a net */ - vtr::vector net_source_modules(const ModuleId& module, const ModuleNetId& net) const; - /* Find the ids of source instances of a net */ - vtr::vector net_source_instances(const ModuleId& module, const ModuleNetId& net) const; - /* Find the source ports of a net */ - vtr::vector net_source_ports(const ModuleId& module, const ModuleNetId& net) const; - /* Find the source pin indices of a net */ - vtr::vector net_source_pins(const ModuleId& module, const ModuleNetId& net) const; - /* Identify if a pin of a port in a module already exists in the net source list*/ - bool net_source_exist(const ModuleId& module, const ModuleNetId& net, - const ModuleId& src_module, const size_t& instance_id, - const ModulePortId& src_port, const size_t& src_pin); + public: /* Public accessors */ + size_t num_modules() const; + size_t num_nets(const ModuleId& module) const; + std::string module_name(const ModuleId& module_id) const; + e_module_usage_type module_usage(const ModuleId& module_id) const; + std::string module_port_type_str( + const enum e_module_port_type& port_type) const; + std::vector module_ports_by_type( + const ModuleId& module_id, const enum e_module_port_type& port_type) const; + std::vector module_port_ids_by_type( + const ModuleId& module_id, const enum e_module_port_type& port_type) const; + /* Find a port of a module by a given name */ + ModulePortId find_module_port(const ModuleId& module_id, + const std::string& port_name) const; + /* Find the Port information with a given port id */ + BasicPort module_port(const ModuleId& module_id, + const ModulePortId& port_id) const; + /* Find a module by a given name */ + ModuleId find_module(const std::string& name) const; + /* Find the number of instances of a child module in the parent module */ + size_t num_instance(const ModuleId& parent_module, + const ModuleId& child_module) const; + /* Find the instance name of a child module */ + std::string instance_name(const ModuleId& parent_module, + const ModuleId& child_module, + const size_t& instance_id) const; + /* Find the instance id of a given instance name */ + size_t instance_id(const ModuleId& parent_module, + const ModuleId& child_module, + const std::string& instance_name) const; + /* Find the type of a port */ + ModuleManager::e_module_port_type port_type(const ModuleId& module, + const ModulePortId& port) const; + /* Find if a port is a wire connection */ + bool port_is_wire(const ModuleId& module, const ModulePortId& port) const; + /* Find if a port is mappable to an I/O from users' implementations */ + bool port_is_mappable_io(const ModuleId& module, + const ModulePortId& port) const; + /* Find if a port is register */ + bool port_is_register(const ModuleId& module, const ModulePortId& port) const; + /* Return the pre-processing flag of a port */ + std::string port_preproc_flag(const ModuleId& module, + const ModulePortId& port) const; + /* Find a net from an instance of a module */ + ModuleNetId module_instance_port_net(const ModuleId& parent_module, + const ModuleId& child_module, + const size_t& child_instance, + const ModulePortId& child_port, + const size_t& child_pin) const; + /* Find the name of net */ + std::string net_name(const ModuleId& module, const ModuleNetId& net) const; + /* Find the source modules of a net */ + vtr::vector net_source_modules( + const ModuleId& module, const ModuleNetId& net) const; + /* Find the ids of source instances of a net */ + vtr::vector net_source_instances( + const ModuleId& module, const ModuleNetId& net) const; + /* Find the source ports of a net */ + vtr::vector net_source_ports( + const ModuleId& module, const ModuleNetId& net) const; + /* Find the source pin indices of a net */ + vtr::vector net_source_pins( + const ModuleId& module, const ModuleNetId& net) const; + /* Identify if a pin of a port in a module already exists in the net source + * list*/ + bool net_source_exist(const ModuleId& module, const ModuleNetId& net, + const ModuleId& src_module, const size_t& instance_id, + const ModulePortId& src_port, const size_t& src_pin); - /* Find the sink modules of a net */ - vtr::vector net_sink_modules(const ModuleId& module, const ModuleNetId& net) const; - /* Find the ids of sink instances of a net */ - vtr::vector net_sink_instances(const ModuleId& module, const ModuleNetId& net) const; - /* Find the sink ports of a net */ - vtr::vector net_sink_ports(const ModuleId& module, const ModuleNetId& net) const; - /* Find the sink pin indices of a net */ - vtr::vector net_sink_pins(const ModuleId& module, const ModuleNetId& net) const; - /* Identify if a pin of a port in a module already exists in the net sink list*/ - bool net_sink_exist(const ModuleId& module, const ModuleNetId& net, - const ModuleId& sink_module, const size_t& instance_id, - const ModulePortId& sink_port, const size_t& sink_pin); + /* Find the sink modules of a net */ + vtr::vector net_sink_modules( + const ModuleId& module, const ModuleNetId& net) const; + /* Find the ids of sink instances of a net */ + vtr::vector net_sink_instances( + const ModuleId& module, const ModuleNetId& net) const; + /* Find the sink ports of a net */ + vtr::vector net_sink_ports( + const ModuleId& module, const ModuleNetId& net) const; + /* Find the sink pin indices of a net */ + vtr::vector net_sink_pins( + const ModuleId& module, const ModuleNetId& net) const; + /* Identify if a pin of a port in a module already exists in the net sink + * list*/ + bool net_sink_exist(const ModuleId& module, const ModuleNetId& net, + const ModuleId& sink_module, const size_t& instance_id, + const ModulePortId& sink_port, const size_t& sink_pin); - private: /* Private accessors */ - size_t find_child_module_index_in_parent_module(const ModuleId& parent_module, const ModuleId& child_module) const; - public: /* Public mutators */ - /* Add a module */ - ModuleId add_module(const std::string& name); - /* Add a port to a module */ - ModulePortId add_port(const ModuleId& module, - const BasicPort& port_info, const enum e_module_port_type& port_type); - /* Set a name for a module port */ - void set_module_port_name(const ModuleId& module, const ModulePortId& module_port, const std::string& port_name); - /* Set a name for a module */ - void set_module_name(const ModuleId& module, const std::string& name); - /* Set a usage for a module */ - void set_module_usage(const ModuleId& module, const e_module_usage_type& usage); - /* Set a port to be a wire */ - void set_port_is_wire(const ModuleId& module, const std::string& port_name, const bool& is_wire); - /* Set a port to be mappable to an I/O from users' implemenations */ - void set_port_is_mappable_io(const ModuleId& module, const ModulePortId& port_id, const bool& is_mappable_io); - /* Set a port to be a register */ - void set_port_is_register(const ModuleId& module, const std::string& port_name, const bool& is_register); - /* Set the preprocessing flag for a port */ - void set_port_preproc_flag(const ModuleId& module, const ModulePortId& port, const std::string& preproc_flag); - /** @brief Add a child module to a parent module. - * By default, it considers the child module as an I/O child, and update the children list of I/O modules inside - * It not needed, just turn it off. Then you need to call add_io_child() API to update child list - * - * .. note:: By default, we assume the I/O indexing to the same as sequence when adding child modules to a parent. However, it may not be true all the time, especially for the top-level module, where customization is needed. - */ - void add_child_module(const ModuleId& parent_module, const ModuleId& child_module, const bool& is_io_child = true); - /* Set the instance name of a child module */ - void set_child_instance_name(const ModuleId& parent_module, const ModuleId& child_module, const size_t& instance_id, const std::string& instance_name); - /* Add a configurable child module to module - * This function also set the coordinate of a configurable child - * The coordinate is a relative position in each region, which is used to - * idenify BL/WL sharing - * By default, it is an invalid coordinate - */ - void add_configurable_child(const ModuleId& module, const ModuleId& child_module, const size_t& child_instance, const vtr::Point coord = vtr::Point(-1, -1)); - /* Reserved a number of configurable children for memory efficiency */ - void reserve_configurable_child(const ModuleId& module, const size_t& num_children); + private: /* Private accessors */ + size_t find_child_module_index_in_parent_module( + const ModuleId& parent_module, const ModuleId& child_module) const; - /* Create a new configurable region under a module */ - ConfigRegionId add_config_region(const ModuleId& module); - /* Add a configurable child module to a region - * Note: - * - The child module must be added as a configurable child to the parent module - * before calling this function! - */ - void add_configurable_child_to_region(const ModuleId& parent_module, - const ConfigRegionId& config_region, - const ModuleId& child_module, - const size_t& child_instance, - const size_t& config_child_id); - /** @brief Add a I/O child to module - * This function also set the coordinate of a configurable child - * The coordinate is used for build I/O location map. So it is consistent with the VPR coordinate system - * By default, it is an invalid coordinate - * - * .. note:: I/O child does not necessary have to be a I/O block. It just provide a sequence for other functions, e.g., connect_gpio_module() to index the I/Os from each child module/instance. - */ - void add_io_child(const ModuleId& module, const ModuleId& child_module, const size_t& child_instance, const vtr::Point coord = vtr::Point(-1, -1)); - /** @brief Reserved a number of I/O children for memory efficiency */ - void reserve_io_child(const ModuleId& module, const size_t& num_children); + public: /* Public mutators */ + /* Add a module */ + ModuleId add_module(const std::string& name); + /* Add a port to a module */ + ModulePortId add_port(const ModuleId& module, const BasicPort& port_info, + const enum e_module_port_type& port_type); + /* Set a name for a module port */ + void set_module_port_name(const ModuleId& module, + const ModulePortId& module_port, + const std::string& port_name); + /* Set a name for a module */ + void set_module_name(const ModuleId& module, const std::string& name); + /* Set a usage for a module */ + void set_module_usage(const ModuleId& module, + const e_module_usage_type& usage); + /* Set a port to be a wire */ + void set_port_is_wire(const ModuleId& module, const std::string& port_name, + const bool& is_wire); + /* Set a port to be mappable to an I/O from users' implemenations */ + void set_port_is_mappable_io(const ModuleId& module, + const ModulePortId& port_id, + const bool& is_mappable_io); + /* Set a port to be a register */ + void set_port_is_register(const ModuleId& module, + const std::string& port_name, + const bool& is_register); + /* Set the preprocessing flag for a port */ + void set_port_preproc_flag(const ModuleId& module, const ModulePortId& port, + const std::string& preproc_flag); + /** @brief Add a child module to a parent module. + * By default, it considers the child module as an I/O child, and update the + * children list of I/O modules inside It not needed, just turn it off. Then + * you need to call add_io_child() API to update child list + * + * .. note:: By default, we assume the I/O indexing to the same as sequence + * when adding child modules to a parent. However, it may not be true all the + * time, especially for the top-level module, where customization is needed. + */ + void add_child_module(const ModuleId& parent_module, + const ModuleId& child_module, + const bool& is_io_child = true); + /* Set the instance name of a child module */ + void set_child_instance_name(const ModuleId& parent_module, + const ModuleId& child_module, + const size_t& instance_id, + const std::string& instance_name); + /* Add a configurable child module to module + * This function also set the coordinate of a configurable child + * The coordinate is a relative position in each region, which is used to + * idenify BL/WL sharing + * By default, it is an invalid coordinate + */ + void add_configurable_child( + const ModuleId& module, const ModuleId& child_module, + const size_t& child_instance, + const vtr::Point coord = vtr::Point(-1, -1)); + /* Reserved a number of configurable children for memory efficiency */ + void reserve_configurable_child(const ModuleId& module, + const size_t& num_children); - /* Reserved a number of module nets for a given module for memory efficiency */ - void reserve_module_nets(const ModuleId& module, const size_t& num_nets); + /* Create a new configurable region under a module */ + ConfigRegionId add_config_region(const ModuleId& module); + /* Add a configurable child module to a region + * Note: + * - The child module must be added as a configurable child to the parent + * module before calling this function! + */ + void add_configurable_child_to_region(const ModuleId& parent_module, + const ConfigRegionId& config_region, + const ModuleId& child_module, + const size_t& child_instance, + const size_t& config_child_id); + /** @brief Add a I/O child to module + * This function also set the coordinate of a configurable child + * The coordinate is used for build I/O location map. So it is consistent with + * the VPR coordinate system By default, it is an invalid coordinate + * + * .. note:: I/O child does not necessary have to be a I/O block. It just + * provide a sequence for other functions, e.g., connect_gpio_module() to + * index the I/Os from each child module/instance. + */ + void add_io_child(const ModuleId& module, const ModuleId& child_module, + const size_t& child_instance, + const vtr::Point coord = vtr::Point(-1, -1)); + /** @brief Reserved a number of I/O children for memory efficiency */ + void reserve_io_child(const ModuleId& module, const size_t& num_children); - /* Add a net to the connection graph of the module */ - ModuleNetId create_module_net(const ModuleId& module); - /* Set the name of net */ - void set_net_name(const ModuleId& module, const ModuleNetId& net, - const std::string& name); + /* Reserved a number of module nets for a given module for memory efficiency + */ + void reserve_module_nets(const ModuleId& module, const size_t& num_nets); - /* Reserved a number of sources for a module net for a given module for memory efficiency */ - void reserve_module_net_sources(const ModuleId& module, const ModuleNetId& net, - const size_t& num_sources); + /* Add a net to the connection graph of the module */ + ModuleNetId create_module_net(const ModuleId& module); + /* Set the name of net */ + void set_net_name(const ModuleId& module, const ModuleNetId& net, + const std::string& name); - /* Add a source to a net in the connection graph */ - ModuleNetSrcId add_module_net_source(const ModuleId& module, const ModuleNetId& net, - const ModuleId& src_module, const size_t& instance_id, - const ModulePortId& src_port, const size_t& src_pin); + /* Reserved a number of sources for a module net for a given module for memory + * efficiency */ + void reserve_module_net_sources(const ModuleId& module, + const ModuleNetId& net, + const size_t& num_sources); - /* Reserved a number of sinks for a module net for a given module for memory efficiency */ - void reserve_module_net_sinks(const ModuleId& module, const ModuleNetId& net, - const size_t& num_sinks); + /* Add a source to a net in the connection graph */ + ModuleNetSrcId add_module_net_source(const ModuleId& module, + const ModuleNetId& net, + const ModuleId& src_module, + const size_t& instance_id, + const ModulePortId& src_port, + const size_t& src_pin); - /* Add a sink to a net in the connection graph */ - ModuleNetSinkId add_module_net_sink(const ModuleId& module, const ModuleNetId& net, - const ModuleId& sink_module, const size_t& instance_id, - const ModulePortId& sink_port, const size_t& sink_pin); - public: /* Public deconstructors */ - /* This is a strong function which will remove all the configurable children - * under a given parent module - * It is mainly used by loading fabric keys - * Do NOT use unless you know what you are doing!!! - */ - void clear_configurable_children(const ModuleId& parent_module); + /* Reserved a number of sinks for a module net for a given module for memory + * efficiency */ + void reserve_module_net_sinks(const ModuleId& module, const ModuleNetId& net, + const size_t& num_sinks); - /* This is a strong function which will remove all the configurable regions - * under a given parent module - * It is mainly used by loading fabric keys - * Do NOT use unless you know what you are doing!!! - */ - void clear_config_region(const ModuleId& parent_module); + /* Add a sink to a net in the connection graph */ + ModuleNetSinkId add_module_net_sink(const ModuleId& module, + const ModuleNetId& net, + const ModuleId& sink_module, + const size_t& instance_id, + const ModulePortId& sink_port, + const size_t& sink_pin); - /* This is a strong function which will remove all the io children - * under a given parent module - * It is mainly used by other functions which want to force an I/O sequence - * Do NOT use unless you know what you are doing!!! - */ - void clear_io_children(const ModuleId& parent_module); + public: /* Public deconstructors */ + /* This is a strong function which will remove all the configurable children + * under a given parent module + * It is mainly used by loading fabric keys + * Do NOT use unless you know what you are doing!!! + */ + void clear_configurable_children(const ModuleId& parent_module); - public: /* Public validators/invalidators */ - bool valid_module_id(const ModuleId& module) const; - bool valid_module_port_id(const ModuleId& module, const ModulePortId& port) const; - bool valid_module_net_id(const ModuleId& module, const ModuleNetId& net) const; - bool valid_module_instance_id(const ModuleId& parent_module, - const ModuleId& child_module, - const size_t& instance_id) const; - bool valid_region_id(const ModuleId& module, - const ConfigRegionId& region) const; - private: /* Private validators/invalidators */ - void invalidate_name2id_map(); - void invalidate_port_lookup(); - void invalidate_net_lookup(); - private: /* Internal data */ - /* Module-level data */ - vtr::vector ids_; /* Unique identifier for each Module */ - vtr::vector names_; /* Unique identifier for each Module */ - vtr::vector usages_; /* Usage of each module */ - vtr::vector> parents_; /* Parent modules that include the module */ - vtr::vector> children_; /* Child modules that this module contain */ - vtr::vector> num_child_instances_; /* Number of children instance in each child module */ - vtr::vector>> child_instance_names_; /* Number of children instance in each child module */ + /* This is a strong function which will remove all the configurable regions + * under a given parent module + * It is mainly used by loading fabric keys + * Do NOT use unless you know what you are doing!!! + */ + void clear_config_region(const ModuleId& parent_module); - /* Configurable child modules are used to record the position of configurable modules in bitstream - * The sequence of children in the list denotes which one is configured first, etc. - * Note that the sequence can be totally different from the children_ list - * This is really dependent how the configuration protocol is organized - * which should be made by users/designers - */ - vtr::vector> configurable_children_; /* Child modules with configurable memory bits that this module contain */ - vtr::vector> configurable_child_instances_; /* Instances of child modules with configurable memory bits that this module contain */ - vtr::vector> configurable_child_regions_; /* Instances of child modules with configurable memory bits that this module contain */ - vtr::vector>> configurable_child_coordinates_; /* Relative coorindates of child modules with configurable memory bits that this module contain */ + /* This is a strong function which will remove all the io children + * under a given parent module + * It is mainly used by other functions which want to force an I/O sequence + * Do NOT use unless you know what you are doing!!! + */ + void clear_io_children(const ModuleId& parent_module); - /* Configurable regions to group the configurable children - * Note: - * - Each child can only be added a group - */ - vtr::vector> config_region_ids_; - vtr::vector>> config_region_children_; + public: /* Public validators/invalidators */ + bool valid_module_id(const ModuleId& module) const; + bool valid_module_port_id(const ModuleId& module, + const ModulePortId& port) const; + bool valid_module_net_id(const ModuleId& module, + const ModuleNetId& net) const; + bool valid_module_instance_id(const ModuleId& parent_module, + const ModuleId& child_module, + const size_t& instance_id) const; + bool valid_region_id(const ModuleId& module, + const ConfigRegionId& region) const; - /* I/O child modules are used to record the position of I/O modules in GPIO indexing - * The sequence of children in the list denotes which one is indexed in the GPIO first, etc. - * Note that the sequence can be totally different from the children_ list - * This is really dependent how the I/O indexing is organized which should be made by users/designers - */ - vtr::vector> io_children_; - vtr::vector> io_child_instances_; - vtr::vector>> io_child_coordinates_; + private: /* Private validators/invalidators */ + void invalidate_name2id_map(); + void invalidate_port_lookup(); + void invalidate_net_lookup(); - /* Port-level data */ - vtr::vector> port_ids_; /* List of ports for each Module */ - vtr::vector> ports_; /* List of ports for each Module */ - vtr::vector> port_types_; /* Type of ports */ - vtr::vector> port_is_mappable_io_; /* If the port is mappable to an I/O for user's implementations */ - vtr::vector> port_is_wire_; /* If the port is a wire, use for Verilog port definition. If enabled: reg */ - vtr::vector> port_is_register_; /* If the port is a register, use for Verilog port definition. If enabled: reg */ - vtr::vector> port_preproc_flags_; /* If a port is available only when a pre-processing flag is enabled. This is to record the pre-processing flags */ + private: /* Internal data */ + /* Module-level data */ + vtr::vector ids_; /* Unique identifier for each Module */ + vtr::vector + names_; /* Unique identifier for each Module */ + vtr::vector usages_; /* Usage of each module */ + vtr::vector> + parents_; /* Parent modules that include the module */ + vtr::vector> + children_; /* Child modules that this module contain */ + vtr::vector> + num_child_instances_; /* Number of children instance in each child module */ + vtr::vector>> + child_instance_names_; /* Number of children instance in each child module + */ - /* Graph-level data: - * We use nets to model the connection between pins of modules and instances. - * To avoid large memory footprint, we do NOT create pins, - * To enable fast look-up on pins, we create a fast look-up - */ - vtr::vector num_nets_; /* List of nets for each Module */ - vtr::vector> invalid_net_ids_; /* Invalid net ids */ - vtr::vector> net_names_; /* Name of net */ + /* Configurable child modules are used to record the position of configurable + * modules in bitstream The sequence of children in the list denotes which one + * is configured first, etc. Note that the sequence can be totally different + * from the children_ list This is really dependent how the configuration + * protocol is organized which should be made by users/designers + */ + vtr::vector> + configurable_children_; /* Child modules with configurable memory bits that + this module contain */ + vtr::vector> + configurable_child_instances_; /* Instances of child modules with + configurable memory bits that this module + contain */ + vtr::vector> + configurable_child_regions_; /* Instances of child modules with configurable + memory bits that this module contain */ + vtr::vector>> + configurable_child_coordinates_; /* Relative coorindates of child modules + with configurable memory bits that this + module contain */ - vtr::vector>> net_src_ids_; /* Unique id of the source that drive the net */ - vtr::vector>> net_src_terminal_ids_; /* Pin ids that drive the net */ - vtr::vector>> net_src_instance_ids_; /* Pin ids that drive the net */ - vtr::vector>> net_src_pin_ids_; /* Pin ids that drive the net */ + /* Configurable regions to group the configurable children + * Note: + * - Each child can only be added a group + */ + vtr::vector> + config_region_ids_; + vtr::vector>> + config_region_children_; + /* I/O child modules are used to record the position of I/O modules in GPIO + * indexing The sequence of children in the list denotes which one is indexed + * in the GPIO first, etc. Note that the sequence can be totally different + * from the children_ list This is really dependent how the I/O indexing is + * organized which should be made by users/designers + */ + vtr::vector> io_children_; + vtr::vector> io_child_instances_; + vtr::vector>> io_child_coordinates_; - vtr::vector>> net_sink_ids_; /* Unique ids of the sink that the net drives */ - vtr::vector>> net_sink_terminal_ids_; /* Pin ids that the net drives */ - vtr::vector>> net_sink_instance_ids_; /* Pin ids that drive the net */ - vtr::vector>> net_sink_pin_ids_; /* Pin ids that drive the net */ + /* Port-level data */ + vtr::vector> + port_ids_; /* List of ports for each Module */ + vtr::vector> + ports_; /* List of ports for each Module */ + vtr::vector> + port_types_; /* Type of ports */ + vtr::vector> + port_is_mappable_io_; /* If the port is mappable to an I/O for user's + implementations */ + vtr::vector> + port_is_wire_; /* If the port is a wire, use for Verilog port definition. If + enabled: reg */ + vtr:: + vector> + port_is_register_; /* If the port is a register, use for Verilog port + definition. If enabled: reg + */ + vtr::vector> + port_preproc_flags_; /* If a port is available only when a pre-processing + flag is enabled. This is to record the + pre-processing flags */ - /* fast look-up for module */ - std::map name_id_map_; - /* fast look-up for ports */ - typedef vtr::vector>> PortLookup; - mutable PortLookup port_lookup_; /* [module_ids][port_types][port_ids] */ + /* Graph-level data: + * We use nets to model the connection between pins of modules and instances. + * To avoid large memory footprint, we do NOT create pins, + * To enable fast look-up on pins, we create a fast look-up + */ + vtr::vector num_nets_; /* List of nets for each Module */ + vtr::vector> + invalid_net_ids_; /* Invalid net ids */ + vtr::vector> + net_names_; /* Name of net */ - /* fast look-up for nets */ - typedef vtr::vector>>>> NetLookup; - mutable NetLookup net_lookup_; /* [module_ids][module_ids][instance_ids][port_ids][pin_ids] */ + vtr::vector< + ModuleId, + vtr::vector>> + net_src_ids_; /* Unique id of the source that drive the net */ + vtr::vector>> + net_src_terminal_ids_; /* Pin ids that drive the net */ + vtr::vector>> + net_src_instance_ids_; /* Pin ids that drive the net */ + vtr::vector>> + net_src_pin_ids_; /* Pin ids that drive the net */ - /* Store pairs of a module and a port, which are frequently used in net terminals - * (either source or sink) - */ - std::vector> net_terminal_storage_; + vtr::vector< + ModuleId, + vtr::vector>> + net_sink_ids_; /* Unique ids of the sink that the net drives */ + vtr::vector>> + net_sink_terminal_ids_; /* Pin ids that the net drives */ + vtr::vector>> + net_sink_instance_ids_; /* Pin ids that drive the net */ + vtr::vector>> + net_sink_pin_ids_; /* Pin ids that drive the net */ + + /* fast look-up for module */ + std::map name_id_map_; + /* fast look-up for ports */ + typedef vtr::vector>> + PortLookup; + mutable PortLookup port_lookup_; /* [module_ids][port_types][port_ids] */ + + /* fast look-up for nets */ + typedef vtr::vector< + ModuleId, + std::map>>>> + NetLookup; + mutable NetLookup + net_lookup_; /* [module_ids][module_ids][instance_ids][port_ids][pin_ids] */ + + /* Store pairs of a module and a port, which are frequently used in net + * terminals (either source or sink) + */ + std::vector> net_terminal_storage_; }; } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/module_manager_fwd.h b/openfpga/src/fabric/module_manager_fwd.h index 5aea7f71f..afa596df3 100644 --- a/openfpga/src/fabric/module_manager_fwd.h +++ b/openfpga/src/fabric/module_manager_fwd.h @@ -1,5 +1,5 @@ /************************************************** - * This file includes only declarations for + * This file includes only declarations for * the data structures for module managers * Please refer to module_manager.h for more details *************************************************/ @@ -34,4 +34,4 @@ class ModuleManager; } /* end namespace openfpga */ -#endif +#endif diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index 8c89c3aaf..7196a6781 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -1,37 +1,34 @@ /******************************************************************** * This file includes functions to build bitstream from a mapped * FPGA fabric. - * We decode the bitstream from configuration of routing multiplexers - * and Look-Up Tables (LUTs) which locate in CLBs and global routing architecture + * We decode the bitstream from configuration of routing multiplexers + * and Look-Up Tables (LUTs) which locate in CLBs and global routing + *architecture *******************************************************************/ #include /* Headers from vtrutil library */ -#include "vtr_log.h" -#include "vtr_assert.h" -#include "vtr_time.h" - -#include "openfpga_naming.h" - -#include "memory_utils.h" -#include "module_manager_utils.h" - +#include "build_device_bitstream.h" #include "build_grid_bitstream.h" #include "build_routing_bitstream.h" -#include "build_device_bitstream.h" +#include "memory_utils.h" +#include "module_manager_utils.h" +#include "openfpga_naming.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** * Estimate the number of blocks to be added to the whole device bitstream - * This function will recursively walk through the module graph + * This function will recursively walk through the module graph * from the specified top module and count the number of configurable children * which are the blocks that will be added to the bitstream manager *******************************************************************/ -static -size_t rec_estimate_device_bitstream_num_blocks(const ModuleManager& module_manager, - const ModuleId& top_module) { +static size_t rec_estimate_device_bitstream_num_blocks( + const ModuleManager& module_manager, const ModuleId& top_module) { size_t num_blocks = 0; /* Those child modules which have no children are @@ -42,10 +39,13 @@ size_t rec_estimate_device_bitstream_num_blocks(const ModuleManager& module_mana return 0; } - size_t num_configurable_children = module_manager.configurable_children(top_module).size(); + size_t num_configurable_children = + module_manager.configurable_children(top_module).size(); for (size_t ichild = 0; ichild < num_configurable_children; ++ichild) { - ModuleId child_module = module_manager.configurable_children(top_module)[ichild]; - num_blocks += rec_estimate_device_bitstream_num_blocks(module_manager, child_module); + ModuleId child_module = + module_manager.configurable_children(top_module)[ichild]; + num_blocks += + rec_estimate_device_bitstream_num_blocks(module_manager, child_module); } /* Add the number of blocks at current level */ @@ -55,19 +55,17 @@ size_t rec_estimate_device_bitstream_num_blocks(const ModuleManager& module_mana } /******************************************************************** - * Estimate the number of configuration bits to be added to the whole device bitstream - * This function will recursively walk through the module graph - * from the specified top module and count the number of leaf configurable children + * Estimate the number of configuration bits to be added to the whole device + *bitstream This function will recursively walk through the module graph from + *the specified top module and count the number of leaf configurable children * which are the bits that will be added to the bitstream manager *******************************************************************/ -static -size_t rec_estimate_device_bitstream_num_bits(const ModuleManager& module_manager, - const ModuleId& top_module, - const ModuleId& parent_module, - const ConfigProtocol& config_protocol) { +static size_t rec_estimate_device_bitstream_num_bits( + const ModuleManager& module_manager, const ModuleId& top_module, + const ModuleId& parent_module, const ConfigProtocol& config_protocol) { size_t num_bits = 0; - /* If a child module has no configurable children, this is a leaf node + /* If a child module has no configurable children, this is a leaf node * We can count it in. Otherwise, we should go recursively. */ if (0 == module_manager.configurable_children(parent_module).size()) { @@ -76,40 +74,52 @@ size_t rec_estimate_device_bitstream_num_bits(const ModuleManager& module_manage /* Two cases to walk through configurable children: * - For top-level module: - * Iterate over the multiple regions and visit each configuration child under any region - * In each region, frame-based configuration protocol or memory bank protocol will contain - * decoders. We should bypass them when count the bitstream size + * Iterate over the multiple regions and visit each configuration child + * under any region In each region, frame-based configuration protocol or + * memory bank protocol will contain decoders. We should bypass them when + * count the bitstream size * - For other modules: * Iterate over the configurable children regardless of regions */ if (parent_module == top_module) { - for (const ConfigRegionId& config_region : module_manager.regions(parent_module)) { - size_t curr_region_num_config_child = module_manager.region_configurable_children(parent_module, config_region).size(); - size_t num_child_to_skip = estimate_num_configurable_children_to_skip_by_config_protocol(config_protocol, curr_region_num_config_child); + for (const ConfigRegionId& config_region : + module_manager.regions(parent_module)) { + size_t curr_region_num_config_child = + module_manager + .region_configurable_children(parent_module, config_region) + .size(); + size_t num_child_to_skip = + estimate_num_configurable_children_to_skip_by_config_protocol( + config_protocol, curr_region_num_config_child); curr_region_num_config_child -= num_child_to_skip; /* Visit all the children in a recursively way */ for (size_t ichild = 0; ichild < curr_region_num_config_child; ++ichild) { - ModuleId child_module = module_manager.region_configurable_children(parent_module, config_region)[ichild]; - num_bits += rec_estimate_device_bitstream_num_bits(module_manager, top_module, child_module, config_protocol); + ModuleId child_module = module_manager.region_configurable_children( + parent_module, config_region)[ichild]; + num_bits += rec_estimate_device_bitstream_num_bits( + module_manager, top_module, child_module, config_protocol); } } } else { VTR_ASSERT_SAFE(parent_module != top_module); - size_t num_configurable_children = module_manager.configurable_children(parent_module).size(); + size_t num_configurable_children = + module_manager.configurable_children(parent_module).size(); /* Frame-based configuration protocol will have 1 decoder * if there are more than 1 configurable children */ - if ( (CONFIG_MEM_FRAME_BASED == config_protocol.type()) - && (2 <= num_configurable_children)) { + if ((CONFIG_MEM_FRAME_BASED == config_protocol.type()) && + (2 <= num_configurable_children)) { num_configurable_children--; } for (size_t ichild = 0; ichild < num_configurable_children; ++ichild) { - ModuleId child_module = module_manager.configurable_children(parent_module)[ichild]; - num_bits += rec_estimate_device_bitstream_num_bits(module_manager, top_module, child_module, config_protocol); + ModuleId child_module = + module_manager.configurable_children(parent_module)[ichild]; + num_bits += rec_estimate_device_bitstream_num_bits( + module_manager, top_module, child_module, config_protocol); } } @@ -118,9 +128,9 @@ size_t rec_estimate_device_bitstream_num_bits(const ModuleManager& module_manage /******************************************************************** * A top-level function to build a bistream from the FPGA device - * 1. It will organize the bitstream w.r.t. the hierarchy of module graphs + * 1. It will organize the bitstream w.r.t. the hierarchy of module graphs * describing the FPGA fabric - * 2. It will decode configuration bits from routing multiplexers used in + * 2. It will decode configuration bits from routing multiplexers used in * global routing architecture * 3. It will decode configuration bits from routing multiplexers and LUTs * used in CLBs @@ -132,72 +142,65 @@ size_t rec_estimate_device_bitstream_num_bits(const ModuleManager& module_manage BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, const OpenfpgaContext& openfpga_ctx, const bool& verbose) { - - std::string timer_message = std::string("\nBuild fabric-independent bitstream for implementation '") + vpr_ctx.atom().nlist.netlist_name() + std::string("'\n"); + std::string timer_message = + std::string("\nBuild fabric-independent bitstream for implementation '") + + vpr_ctx.atom().nlist.netlist_name() + std::string("'\n"); vtr::ScopedStartFinishTimer timer(timer_message); /* Bitstream manager to be built */ BitstreamManager bitstream_manager; - /* Create the top-level block for bitstream - * This is related to the top-level module of fpga + /* Create the top-level block for bitstream + * This is related to the top-level module of fpga */ std::string top_block_name = generate_fpga_top_module_name(); ConfigBlockId top_block = bitstream_manager.add_block(top_block_name); - const ModuleId& top_module = openfpga_ctx.module_graph().find_module(top_block_name); + const ModuleId& top_module = + openfpga_ctx.module_graph().find_module(top_block_name); VTR_ASSERT(true == openfpga_ctx.module_graph().valid_module_id(top_module)); /* Estimate the number of blocks to be added to the database */ - size_t num_blocks_to_reserve = rec_estimate_device_bitstream_num_blocks(openfpga_ctx.module_graph(), - top_module); + size_t num_blocks_to_reserve = rec_estimate_device_bitstream_num_blocks( + openfpga_ctx.module_graph(), top_module); bitstream_manager.reserve_blocks(num_blocks_to_reserve); - VTR_LOGV(verbose, "Reserved %lu configurable blocks\n", num_blocks_to_reserve); + VTR_LOGV(verbose, "Reserved %lu configurable blocks\n", + num_blocks_to_reserve); /* Estimate the number of bits to be added to the database */ - size_t num_bits_to_reserve = rec_estimate_device_bitstream_num_bits(openfpga_ctx.module_graph(), - top_module, - top_module, - openfpga_ctx.arch().config_protocol); + size_t num_bits_to_reserve = rec_estimate_device_bitstream_num_bits( + openfpga_ctx.module_graph(), top_module, top_module, + openfpga_ctx.arch().config_protocol); bitstream_manager.reserve_bits(num_bits_to_reserve); VTR_LOGV(verbose, "Reserved %lu configuration bits\n", num_bits_to_reserve); /* Reserve child blocks for the top level block */ - bitstream_manager.reserve_child_blocks(top_block, - count_module_manager_module_configurable_children(openfpga_ctx.module_graph(), top_module)); + bitstream_manager.reserve_child_blocks( + top_block, count_module_manager_module_configurable_children( + openfpga_ctx.module_graph(), top_module)); /* Create bitstream from grids */ VTR_LOGV(verbose, "Building grid bitstream...\n"); - build_grid_bitstream(bitstream_manager, top_block, - openfpga_ctx.module_graph(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.mux_lib(), - vpr_ctx.device().grid, - vpr_ctx.atom(), - openfpga_ctx.vpr_device_annotation(), - openfpga_ctx.vpr_clustering_annotation(), - openfpga_ctx.vpr_placement_annotation(), - openfpga_ctx.vpr_bitstream_annotation(), - verbose); + build_grid_bitstream( + bitstream_manager, top_block, openfpga_ctx.module_graph(), + openfpga_ctx.arch().circuit_lib, openfpga_ctx.mux_lib(), + vpr_ctx.device().grid, vpr_ctx.atom(), openfpga_ctx.vpr_device_annotation(), + openfpga_ctx.vpr_clustering_annotation(), + openfpga_ctx.vpr_placement_annotation(), + openfpga_ctx.vpr_bitstream_annotation(), verbose); VTR_LOGV(verbose, "Done\n"); /* Create bitstream from routing architectures */ VTR_LOGV(verbose, "Building routing bitstream...\n"); - build_routing_bitstream(bitstream_manager, top_block, - openfpga_ctx.module_graph(), - 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()); + build_routing_bitstream( + bitstream_manager, top_block, openfpga_ctx.module_graph(), + 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()); VTR_LOGV(verbose, "Done\n"); - VTR_LOGV(verbose, - "Decoded %lu configuration bits into %lu blocks\n", - bitstream_manager.num_bits(), - bitstream_manager.num_blocks()); + VTR_LOGV(verbose, "Decoded %lu configuration bits into %lu blocks\n", + bitstream_manager.num_bits(), bitstream_manager.num_blocks()); VTR_ASSERT(num_blocks_to_reserve == bitstream_manager.num_blocks()); VTR_ASSERT(num_bits_to_reserve == bitstream_manager.num_bits()); diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.h b/openfpga/src/fpga_bitstream/build_device_bitstream.h index 3926f2733..3bddf9211 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.h @@ -5,8 +5,9 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "vpr_context.h" + #include "openfpga_context.h" +#include "vpr_context.h" /******************************************************************** * Function declaration diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp index 216f44354..141237841 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp @@ -1,9 +1,9 @@ /******************************************************************** * This file includes functions to build fabric dependent bitstream *******************************************************************/ -#include -#include #include +#include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" @@ -11,15 +11,13 @@ #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_decode.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" - -#include "decoder_library_utils.h" #include "bitstream_manager_utils.h" #include "build_fabric_bitstream.h" #include "build_fabric_bitstream_memory_bank.h" +#include "decoder_library_utils.h" +#include "openfpga_decode.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" /* begin namespace openfpga */ namespace openfpga { @@ -28,77 +26,87 @@ namespace openfpga { * This function aims to build a bitstream for configuration chain-like protocol * It will walk through all the configurable children under a module * in a recursive way, following a Depth-First Search (DFS) strategy - * For each configuration child, we use its instance name as a key to spot the + * For each configuration child, we use its instance name as a key to spot the * configuration bits in bitstream manager. - * Note that it is guarentee that the instance name in module manager is + * Note that it is guarentee that the instance name in module manager is * consistent with the block names in bitstream manager - * We use this link to reorganize the bitstream in the sequence of memories as we stored - * in the configurable_children() and configurable_child_instances() of each module of module manager + * We use this link to reorganize the bitstream in the sequence of memories as + *we stored in the configurable_children() and configurable_child_instances() of + *each module of module manager *******************************************************************/ -static -void rec_build_module_fabric_dependent_chain_bitstream(const BitstreamManager& bitstream_manager, - const ConfigBlockId& parent_block, - const ModuleManager& module_manager, - const ModuleId& top_module, - const ModuleId& parent_module, - const ConfigRegionId& config_region, - FabricBitstream& fabric_bitstream, - const FabricBitRegionId& fabric_bitstream_region) { - - /* Depth-first search: if we have any children in the parent_block, - * we dive to the next level first! +static void rec_build_module_fabric_dependent_chain_bitstream( + const BitstreamManager& bitstream_manager, const ConfigBlockId& parent_block, + const ModuleManager& module_manager, const ModuleId& top_module, + const ModuleId& parent_module, const ConfigRegionId& config_region, + FabricBitstream& fabric_bitstream, + const FabricBitRegionId& fabric_bitstream_region) { + /* Depth-first search: if we have any children in the parent_block, + * we dive to the next level first! */ if (0 < bitstream_manager.block_children(parent_block).size()) { if (parent_module == top_module) { - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(parent_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(parent_module, config_region)[child_id]; - size_t child_instance = module_manager.region_configurable_child_instances(parent_module, config_region)[child_id]; + for (size_t child_id = 0; child_id < module_manager + .region_configurable_children( + parent_module, config_region) + .size(); + ++child_id) { + ModuleId child_module = module_manager.region_configurable_children( + parent_module, config_region)[child_id]; + size_t child_instance = + module_manager.region_configurable_child_instances( + parent_module, config_region)[child_id]; /* Get the instance name and ensure it is not empty */ - std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); - - /* Find the child block that matches the instance name! */ - ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name); + std::string instance_name = module_manager.instance_name( + parent_module, child_module, child_instance); + + /* Find the child block that matches the instance name! */ + ConfigBlockId child_block = + bitstream_manager.find_child_block(parent_block, instance_name); /* We must have one valid block id! */ VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); /* Go recursively */ - rec_build_module_fabric_dependent_chain_bitstream(bitstream_manager, child_block, - module_manager, top_module, - child_module, - config_region, - fabric_bitstream, - fabric_bitstream_region); + rec_build_module_fabric_dependent_chain_bitstream( + bitstream_manager, child_block, module_manager, top_module, + child_module, config_region, fabric_bitstream, + fabric_bitstream_region); } - } else { - for (size_t child_id = 0; child_id < module_manager.configurable_children(parent_module).size(); ++child_id) { - ModuleId child_module = module_manager.configurable_children(parent_module)[child_id]; - size_t child_instance = module_manager.configurable_child_instances(parent_module)[child_id]; + } else { + for (size_t child_id = 0; + child_id < + module_manager.configurable_children(parent_module).size(); + ++child_id) { + ModuleId child_module = + module_manager.configurable_children(parent_module)[child_id]; + size_t child_instance = + module_manager.configurable_child_instances(parent_module)[child_id]; /* Get the instance name and ensure it is not empty */ - std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); - - /* Find the child block that matches the instance name! */ - ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name); + std::string instance_name = module_manager.instance_name( + parent_module, child_module, child_instance); + + /* Find the child block that matches the instance name! */ + ConfigBlockId child_block = + bitstream_manager.find_child_block(parent_block, instance_name); /* We must have one valid block id! */ VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); /* Go recursively */ - rec_build_module_fabric_dependent_chain_bitstream(bitstream_manager, child_block, - module_manager, top_module, - child_module, - config_region, - fabric_bitstream, - fabric_bitstream_region); + rec_build_module_fabric_dependent_chain_bitstream( + bitstream_manager, child_block, module_manager, top_module, + child_module, config_region, fabric_bitstream, + fabric_bitstream_region); } } /* Ensure that there should be no configuration bits in the parent block */ VTR_ASSERT(0 == bitstream_manager.block_bits(parent_block).size()); } - /* Note that, reach here, it means that this is a leaf node. + /* Note that, reach here, it means that this is a leaf node. * We add the configuration bits to the fabric_bitstream, * And then, we can return */ - for (const ConfigBitId& config_bit : bitstream_manager.block_bits(parent_block)) { + for (const ConfigBitId& config_bit : + bitstream_manager.block_bits(parent_block)) { FabricBitId fabric_bit = fabric_bitstream.add_bit(config_bit); fabric_bitstream.add_bit_to_region(fabric_bitstream_region, fabric_bit); } @@ -108,74 +116,73 @@ void rec_build_module_fabric_dependent_chain_bitstream(const BitstreamManager& b * This function aims to build a bitstream for memory-bank protocol * It will walk through all the configurable children under a module * in a recursive way, following a Depth-First Search (DFS) strategy - * For each configuration child, we use its instance name as a key to spot the + * For each configuration child, we use its instance name as a key to spot the * configuration bits in bitstream manager. - * Note that it is guarentee that the instance name in module manager is + * Note that it is guarentee that the instance name in module manager is * consistent with the block names in bitstream manager - * We use this link to reorganize the bitstream in the sequence of memories as we stored - * in the configurable_children() and configurable_child_instances() of each module of module manager + * We use this link to reorganize the bitstream in the sequence of memories as + *we stored in the configurable_children() and configurable_child_instances() of + *each module of module manager * * In such configuration organization, each memory cell has an unique index. * Using this index, we can infer the address codes for both BL and WL decoders. * Note that, we must get the number of BLs and WLs before using this function! *******************************************************************/ -static -void rec_build_module_fabric_dependent_memory_bank_bitstream(const BitstreamManager& bitstream_manager, - const ConfigBlockId& parent_block, - const ModuleManager& module_manager, - const ModuleId& top_module, - const ModuleId& parent_module, - const ConfigRegionId& config_region, - const size_t& bl_addr_size, - const size_t& wl_addr_size, - const size_t& num_bls, - const size_t& num_wls, - size_t& cur_mem_index, - FabricBitstream& fabric_bitstream, - const FabricBitRegionId& fabric_bitstream_region) { - - /* Depth-first search: if we have any children in the parent_block, - * we dive to the next level first! +static void rec_build_module_fabric_dependent_memory_bank_bitstream( + const BitstreamManager& bitstream_manager, const ConfigBlockId& parent_block, + const ModuleManager& module_manager, const ModuleId& top_module, + const ModuleId& parent_module, const ConfigRegionId& config_region, + const size_t& bl_addr_size, const size_t& wl_addr_size, const size_t& num_bls, + const size_t& num_wls, size_t& cur_mem_index, + FabricBitstream& fabric_bitstream, + const FabricBitRegionId& fabric_bitstream_region) { + /* Depth-first search: if we have any children in the parent_block, + * we dive to the next level first! */ if (0 < bitstream_manager.block_children(parent_block).size()) { /* For top module: * - Use regional configurable children - * - we will skip the two decoders at the end of the configurable children list + * - we will skip the two decoders at the end of the configurable children + * list */ if (parent_module == top_module) { - std::vector configurable_children = module_manager.region_configurable_children(parent_module, config_region); + std::vector configurable_children = + module_manager.region_configurable_children(parent_module, + config_region); - VTR_ASSERT(2 <= configurable_children.size()); + VTR_ASSERT(2 <= configurable_children.size()); size_t num_configurable_children = configurable_children.size() - 2; /* Early exit if there is no configurable children */ if (0 == num_configurable_children) { - /* Ensure that there should be no configuration bits in the parent block */ + /* Ensure that there should be no configuration bits in the parent block + */ VTR_ASSERT(0 == bitstream_manager.block_bits(parent_block).size()); return; } - for (size_t child_id = 0; child_id < num_configurable_children; ++child_id) { - ModuleId child_module = configurable_children[child_id]; - size_t child_instance = module_manager.region_configurable_child_instances(parent_module, config_region)[child_id]; + for (size_t child_id = 0; child_id < num_configurable_children; + ++child_id) { + ModuleId child_module = configurable_children[child_id]; + size_t child_instance = + module_manager.region_configurable_child_instances( + parent_module, config_region)[child_id]; /* Get the instance name and ensure it is not empty */ - std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); - - /* Find the child block that matches the instance name! */ - ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name); + std::string instance_name = module_manager.instance_name( + parent_module, child_module, child_instance); + + /* Find the child block that matches the instance name! */ + ConfigBlockId child_block = + bitstream_manager.find_child_block(parent_block, instance_name); /* We must have one valid block id! */ VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); /* Go recursively */ - rec_build_module_fabric_dependent_memory_bank_bitstream(bitstream_manager, child_block, - module_manager, top_module, child_module, - config_region, - bl_addr_size, wl_addr_size, - num_bls, num_wls, - cur_mem_index, - fabric_bitstream, - fabric_bitstream_region); + rec_build_module_fabric_dependent_memory_bank_bitstream( + bitstream_manager, child_block, module_manager, top_module, + child_module, config_region, bl_addr_size, wl_addr_size, num_bls, + num_wls, cur_mem_index, fabric_bitstream, fabric_bitstream_region); } } else { VTR_ASSERT(parent_module != top_module); @@ -183,38 +190,40 @@ void rec_build_module_fabric_dependent_memory_bank_bitstream(const BitstreamMana * - Use configurable children directly * - no need to exclude decoders as they are not there */ - std::vector configurable_children = module_manager.configurable_children(parent_module); + std::vector configurable_children = + module_manager.configurable_children(parent_module); size_t num_configurable_children = configurable_children.size(); /* Early exit if there is no configurable children */ if (0 == num_configurable_children) { - /* Ensure that there should be no configuration bits in the parent block */ + /* Ensure that there should be no configuration bits in the parent block + */ VTR_ASSERT(0 == bitstream_manager.block_bits(parent_block).size()); return; } - for (size_t child_id = 0; child_id < num_configurable_children; ++child_id) { - ModuleId child_module = configurable_children[child_id]; - size_t child_instance = module_manager.configurable_child_instances(parent_module)[child_id]; + for (size_t child_id = 0; child_id < num_configurable_children; + ++child_id) { + ModuleId child_module = configurable_children[child_id]; + size_t child_instance = + module_manager.configurable_child_instances(parent_module)[child_id]; /* Get the instance name and ensure it is not empty */ - std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); - - /* Find the child block that matches the instance name! */ - ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name); + std::string instance_name = module_manager.instance_name( + parent_module, child_module, child_instance); + + /* Find the child block that matches the instance name! */ + ConfigBlockId child_block = + bitstream_manager.find_child_block(parent_block, instance_name); /* We must have one valid block id! */ VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); /* Go recursively */ - rec_build_module_fabric_dependent_memory_bank_bitstream(bitstream_manager, child_block, - module_manager, top_module, child_module, - config_region, - bl_addr_size, wl_addr_size, - num_bls, num_wls, - cur_mem_index, - fabric_bitstream, - fabric_bitstream_region); + rec_build_module_fabric_dependent_memory_bank_bitstream( + bitstream_manager, child_block, module_manager, top_module, + child_module, config_region, bl_addr_size, wl_addr_size, num_bls, + num_wls, cur_mem_index, fabric_bitstream, fabric_bitstream_region); } } /* Ensure that there should be no configuration bits in the parent block */ @@ -223,29 +232,33 @@ void rec_build_module_fabric_dependent_memory_bank_bitstream(const BitstreamMana return; } - /* Note that, reach here, it means that this is a leaf node. + /* Note that, reach here, it means that this is a leaf node. * We add the configuration bits to the fabric_bitstream, * And then, we can return */ - for (const ConfigBitId& config_bit : bitstream_manager.block_bits(parent_block)) { + for (const ConfigBitId& config_bit : + bitstream_manager.block_bits(parent_block)) { FabricBitId fabric_bit = fabric_bitstream.add_bit(config_bit); - + /* Find BL address */ size_t cur_bl_index = std::floor(cur_mem_index / num_bls); - std::vector bl_addr_bits_vec = itobin_charvec(cur_bl_index, bl_addr_size); + std::vector bl_addr_bits_vec = + itobin_charvec(cur_bl_index, bl_addr_size); /* Find WL address */ size_t cur_wl_index = cur_mem_index % num_wls; - std::vector wl_addr_bits_vec = itobin_charvec(cur_wl_index, wl_addr_size); + std::vector wl_addr_bits_vec = + itobin_charvec(cur_wl_index, wl_addr_size); /* Set BL address */ fabric_bitstream.set_bit_bl_address(fabric_bit, bl_addr_bits_vec); /* Set WL address */ fabric_bitstream.set_bit_wl_address(fabric_bit, wl_addr_bits_vec); - + /* Set data input */ - fabric_bitstream.set_bit_din(fabric_bit, bitstream_manager.bit_value(config_bit)); + fabric_bitstream.set_bit_din(fabric_bit, + bitstream_manager.bit_value(config_bit)); /* Add the bit to the region */ fabric_bitstream.add_bit_to_region(fabric_bitstream_region, fabric_bit); @@ -256,42 +269,40 @@ void rec_build_module_fabric_dependent_memory_bank_bitstream(const BitstreamMana } /******************************************************************** - * This function aims to build a bitstream for frame-based configuration protocol - * It will walk through all the configurable children under a module - * in a recursive way, following a Depth-First Search (DFS) strategy - * For each configuration child, we use its instance name as a key to spot the + * This function aims to build a bitstream for frame-based configuration + *protocol It will walk through all the configurable children under a module in + *a recursive way, following a Depth-First Search (DFS) strategy For each + *configuration child, we use its instance name as a key to spot the * configuration bits in bitstream manager. - * Note that it is guarenteed that the instance name in module manager is + * Note that it is guarenteed that the instance name in module manager is * consistent with the block names in bitstream manager - * We use this link to reorganize the bitstream in the sequence of memories as we stored - * in the configurable_children() and configurable_child_instances() of each module of module manager + * We use this link to reorganize the bitstream in the sequence of memories as + *we stored in the configurable_children() and configurable_child_instances() of + *each module of module manager * - * For each configuration bits, we will infer its address based on + * For each configuration bits, we will infer its address based on * - the child index in the configurable children list of current module - * - the child index of all the parent modules in their configurable children list - * until the top in the hierarchy + * - the child index of all the parent modules in their configurable children + *list until the top in the hierarchy * * The address will be organized as follows: * ... * The address will be decoded to a binary format * - * For each configuration bit, the data_in for the frame-based decoders will be + * For each configuration bit, the data_in for the frame-based decoders will be * the same as the configuration bit in bitstream manager. *******************************************************************/ -static -void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& bitstream_manager, - const std::vector& parent_blocks, - const ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigRegionId& config_region, - const std::vector& parent_modules, - const std::vector& addr_code, - const char& bitstream_dont_care_char, - FabricBitstream& fabric_bitstream, - FabricBitRegionId& fabric_bitstream_region) { - - /* Depth-first search: if we have any children in the parent_block, - * we dive to the next level first! +static void rec_build_module_fabric_dependent_frame_bitstream( + const BitstreamManager& bitstream_manager, + const std::vector& parent_blocks, + const ModuleManager& module_manager, const ModuleId& top_module, + const ConfigRegionId& config_region, + const std::vector& parent_modules, + const std::vector& addr_code, const char& bitstream_dont_care_char, + FabricBitstream& fabric_bitstream, + FabricBitRegionId& fabric_bitstream_region) { + /* Depth-first search: if we have any children in the parent_block, + * we dive to the next level first! */ if (0 < bitstream_manager.block_children(parent_blocks.back()).size()) { const ConfigBlockId& parent_block = parent_blocks.back(); @@ -300,23 +311,29 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b std::vector configurable_children; std::vector configurable_child_instances; if (top_module == parent_module) { - configurable_children = module_manager.region_configurable_children(parent_module, config_region); - configurable_child_instances = module_manager.region_configurable_child_instances(parent_module, config_region); + configurable_children = module_manager.region_configurable_children( + parent_module, config_region); + configurable_child_instances = + module_manager.region_configurable_child_instances(parent_module, + config_region); } else { VTR_ASSERT(top_module != parent_module); - configurable_children = module_manager.configurable_children(parent_module); - configurable_child_instances = module_manager.configurable_child_instances(parent_module); + configurable_children = + module_manager.configurable_children(parent_module); + configurable_child_instances = + module_manager.configurable_child_instances(parent_module); } size_t num_configurable_children = configurable_children.size(); - + size_t max_child_addr_code_size = 0; bool add_addr_code = true; ModuleId decoder_module = ModuleId::INVALID(); /* Early exit if there is no configurable children */ if (0 == num_configurable_children) { - /* Ensure that there should be no configuration bits in the parent block */ + /* Ensure that there should be no configuration bits in the parent block + */ VTR_ASSERT(0 == bitstream_manager.block_bits(parent_block).size()); return; } @@ -327,36 +344,44 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b if (1 == num_configurable_children) { add_addr_code = false; } else { - /* For more than 2 children, there is a decoder in the tail of the list - * We will not decode that, but will access the address size from that module - * So, we reduce the number of children by 1 - */ + /* For more than 2 children, there is a decoder in the tail of the list + * We will not decode that, but will access the address size from that + * module So, we reduce the number of children by 1 + */ VTR_ASSERT(2 < num_configurable_children); num_configurable_children--; decoder_module = configurable_children.back(); - /* The max address code size is the max address code size of all the + /* The max address code size is the max address code size of all the * configurable children in all the regions */ - for (const ModuleId& child_module : module_manager.configurable_children(parent_module)) { + for (const ModuleId& child_module : + module_manager.configurable_children(parent_module)) { /* Bypass any decoder module (which no configurable children */ if (module_manager.configurable_children(child_module).empty()) { continue; } - const ModulePortId& child_addr_port_id = module_manager.find_module_port(child_module, std::string(DECODER_ADDRESS_PORT_NAME)); - const BasicPort& child_addr_port = module_manager.module_port(child_module, child_addr_port_id); - max_child_addr_code_size = std::max(child_addr_port.get_width(), max_child_addr_code_size); + const ModulePortId& child_addr_port_id = + module_manager.find_module_port( + child_module, std::string(DECODER_ADDRESS_PORT_NAME)); + const BasicPort& child_addr_port = + module_manager.module_port(child_module, child_addr_port_id); + max_child_addr_code_size = + std::max(child_addr_port.get_width(), max_child_addr_code_size); } } - for (size_t child_id = 0; child_id < num_configurable_children; ++child_id) { - ModuleId child_module = configurable_children[child_id]; - size_t child_instance = configurable_child_instances[child_id]; + for (size_t child_id = 0; child_id < num_configurable_children; + ++child_id) { + ModuleId child_module = configurable_children[child_id]; + size_t child_instance = configurable_child_instances[child_id]; /* Get the instance name and ensure it is not empty */ - std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); - - /* Find the child block that matches the instance name! */ - ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name); + std::string instance_name = module_manager.instance_name( + parent_module, child_module, child_instance); + + /* Find the child block that matches the instance name! */ + ConfigBlockId child_block = + bitstream_manager.find_child_block(parent_block, instance_name); /* We must have one valid block id! */ VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); @@ -367,28 +392,35 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b std::vector child_modules = parent_modules; child_modules.push_back(child_module); - /* Set address, apply binary conversion from the first to the last element in the address list */ + /* Set address, apply binary conversion from the first to the last element + * in the address list */ std::vector child_addr_code = addr_code; - if (true == add_addr_code) { + if (true == add_addr_code) { /* Find the address port from the decoder module */ - const ModulePortId& decoder_addr_port_id = module_manager.find_module_port(decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); - const BasicPort& decoder_addr_port = module_manager.module_port(decoder_module, decoder_addr_port_id); - std::vector addr_bits_vec = itobin_charvec(child_id, decoder_addr_port.get_width()); + const ModulePortId& decoder_addr_port_id = + module_manager.find_module_port( + decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); + const BasicPort& decoder_addr_port = + module_manager.module_port(decoder_module, decoder_addr_port_id); + std::vector addr_bits_vec = + itobin_charvec(child_id, decoder_addr_port.get_width()); - /* For top-level module, the child address should be added to the tail + /* For top-level module, the child address should be added to the tail * For other modules, the child address should be added to the head */ if (top_module == parent_module) { - child_addr_code.insert(child_addr_code.end(), addr_bits_vec.begin(), addr_bits_vec.end()); + child_addr_code.insert(child_addr_code.end(), addr_bits_vec.begin(), + addr_bits_vec.end()); } else { VTR_ASSERT_SAFE(top_module != parent_module); - child_addr_code.insert(child_addr_code.begin(), addr_bits_vec.begin(), addr_bits_vec.end()); + child_addr_code.insert(child_addr_code.begin(), addr_bits_vec.begin(), + addr_bits_vec.end()); } - /* Note that the address port size of the child module may be smaller than the maximum - * of other child modules at this level. - * We will add dummy '0's to the head of addr_bit_vec. + /* Note that the address port size of the child module may be smaller + * than the maximum of other child modules at this level. We will add + * dummy '0's to the head of addr_bit_vec. * * For example: * Decoder is the decoder to access all the child modules @@ -397,8 +429,8 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b * we should add dummy '0' to fill the gap * * Addr_code for child[0]: '000' + addr_bits_vec - * Addr_code for child[1]: '00' + addr_bits_vec - * Addr_code for child[2]: '0' + addr_bits_vec + * Addr_code for child[1]: '00' + addr_bits_vec + * Addr_code for child[2]: '0' + addr_bits_vec * * Addr[6:8] * | @@ -406,7 +438,7 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b * +-------------------------------------------+ * | Decoder Module | * +-------------------------------------------+ - * + * * Addr[0:2] Addr[0:3] Addr[0:4] * | | | * v v v @@ -417,33 +449,34 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b * Child[2] has the maximum address lines among the children * */ - const ModulePortId& child_addr_port_id = module_manager.find_module_port(child_module, std::string(DECODER_ADDRESS_PORT_NAME)); - const BasicPort& child_addr_port = module_manager.module_port(child_module, child_addr_port_id); + const ModulePortId& child_addr_port_id = + module_manager.find_module_port( + child_module, std::string(DECODER_ADDRESS_PORT_NAME)); + const BasicPort& child_addr_port = + module_manager.module_port(child_module, child_addr_port_id); if (0 < max_child_addr_code_size - child_addr_port.get_width()) { /* Deposit don't care state for the dummy bits */ - std::vector dummy_codes(max_child_addr_code_size - child_addr_port.get_width(), bitstream_dont_care_char); - child_addr_code.insert(child_addr_code.begin(), dummy_codes.begin(), dummy_codes.end()); + std::vector dummy_codes( + max_child_addr_code_size - child_addr_port.get_width(), + bitstream_dont_care_char); + child_addr_code.insert(child_addr_code.begin(), dummy_codes.begin(), + dummy_codes.end()); } } /* Go recursively */ - rec_build_module_fabric_dependent_frame_bitstream(bitstream_manager, child_blocks, - module_manager, - top_module, - config_region, - child_modules, - child_addr_code, - bitstream_dont_care_char, - fabric_bitstream, - fabric_bitstream_region); + rec_build_module_fabric_dependent_frame_bitstream( + bitstream_manager, child_blocks, module_manager, top_module, + config_region, child_modules, child_addr_code, bitstream_dont_care_char, + fabric_bitstream, fabric_bitstream_region); } /* Ensure that there should be no configuration bits in the parent block */ VTR_ASSERT(0 == bitstream_manager.block_bits(parent_block).size()); - + return; } - /* Note that, reach here, it means that this is a leaf node. + /* Note that, reach here, it means that this is a leaf node. * A leaf node (a memory module) always has a decoder inside * which is the last of configurable children. * We will find the address bit and add it to addr_code @@ -451,33 +484,42 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b */ std::vector configurable_children; if (top_module == parent_modules.back()) { - configurable_children = module_manager.region_configurable_children(parent_modules.back(), config_region); + configurable_children = module_manager.region_configurable_children( + parent_modules.back(), config_region); } else { VTR_ASSERT(top_module != parent_modules.back()); - configurable_children = module_manager.configurable_children(parent_modules.back()); + configurable_children = + module_manager.configurable_children(parent_modules.back()); } ModuleId decoder_module = configurable_children.back(); /* Find the address port from the decoder module */ - const ModulePortId& decoder_addr_port_id = module_manager.find_module_port(decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); - const BasicPort& decoder_addr_port = module_manager.module_port(decoder_module, decoder_addr_port_id); + const ModulePortId& decoder_addr_port_id = module_manager.find_module_port( + decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); + const BasicPort& decoder_addr_port = + module_manager.module_port(decoder_module, decoder_addr_port_id); - for (size_t ibit = 0; ibit < bitstream_manager.block_bits(parent_blocks.back()).size(); ++ibit) { - - ConfigBitId config_bit = bitstream_manager.block_bits(parent_blocks.back())[ibit]; - std::vector addr_bits_vec = itobin_charvec(ibit, decoder_addr_port.get_width()); + for (size_t ibit = 0; + ibit < bitstream_manager.block_bits(parent_blocks.back()).size(); + ++ibit) { + ConfigBitId config_bit = + bitstream_manager.block_bits(parent_blocks.back())[ibit]; + std::vector addr_bits_vec = + itobin_charvec(ibit, decoder_addr_port.get_width()); std::vector child_addr_code = addr_code; - child_addr_code.insert(child_addr_code.begin(), addr_bits_vec.begin(), addr_bits_vec.end()); + child_addr_code.insert(child_addr_code.begin(), addr_bits_vec.begin(), + addr_bits_vec.end()); const FabricBitId& fabric_bit = fabric_bitstream.add_bit(config_bit); /* Set address */ fabric_bitstream.set_bit_address(fabric_bit, child_addr_code); - + /* Set data input */ - fabric_bitstream.set_bit_din(fabric_bit, bitstream_manager.bit_value(config_bit)); + fabric_bitstream.set_bit_din(fabric_bit, + bitstream_manager.bit_value(config_bit)); /* Add the bit to the region */ fabric_bitstream.add_bit_to_region(fabric_bitstream_region, fabric_bit); @@ -486,198 +528,208 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b /******************************************************************** * Main function to build a fabric-dependent bitstream - * by considering the configuration protocol types + * by considering the configuration protocol types *******************************************************************/ -static -void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protocol, - const CircuitLibrary& circuit_lib, - const BitstreamManager& bitstream_manager, - const ConfigBlockId& top_block, - const ModuleManager& module_manager, - const ModuleId& top_module, - FabricBitstream& fabric_bitstream) { - +static void build_module_fabric_dependent_bitstream( + const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib, + const BitstreamManager& bitstream_manager, const ConfigBlockId& top_block, + const ModuleManager& module_manager, const ModuleId& top_module, + FabricBitstream& fabric_bitstream) { switch (config_protocol.type()) { - case CONFIG_MEM_STANDALONE: { - /* Reserve bits before build-up */ - fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); + case CONFIG_MEM_STANDALONE: { + /* Reserve bits before build-up */ + fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region(); - rec_build_module_fabric_dependent_chain_bitstream(bitstream_manager, top_block, - module_manager, top_module, - top_module, - config_region, - fabric_bitstream, - fabric_bitstream_region); - } - - break; - } - case CONFIG_MEM_SCAN_CHAIN: { - /* Reserve bits before build-up */ - fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); - - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region(); - rec_build_module_fabric_dependent_chain_bitstream(bitstream_manager, top_block, - module_manager, top_module, - top_module, - config_region, - fabric_bitstream, - fabric_bitstream_region); - fabric_bitstream.reverse_region_bits(fabric_bitstream_region); - } - break; - } - case CONFIG_MEM_MEMORY_BANK: { - /* Find global BL address port size */ - ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); - BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port); - - /* Find global WL address port size */ - ModulePortId wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); - BasicPort wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port); - - /* Reserve bits before build-up */ - fabric_bitstream.set_use_address(true); - fabric_bitstream.set_use_wl_address(true); - fabric_bitstream.set_bl_address_length(bl_addr_port_info.get_width()); - fabric_bitstream.set_wl_address_length(wl_addr_port_info.get_width()); - fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); - - /* Build bitstreams by region */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - size_t cur_mem_index = 0; - - /* Find port information for local BL and WL decoder in this region */ - std::vector configurable_children = module_manager.region_configurable_children(top_module, config_region); - VTR_ASSERT(2 <= configurable_children.size()); - ModuleId bl_decoder_module = configurable_children[configurable_children.size() - 2]; - ModuleId wl_decoder_module = configurable_children[configurable_children.size() - 1]; - - ModulePortId bl_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); - BasicPort bl_port_info = module_manager.module_port(bl_decoder_module, bl_port); - - ModulePortId wl_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); - BasicPort wl_port_info = module_manager.module_port(wl_decoder_module, wl_port); - - /* Build the bitstream for all the blocks in this region */ - FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region(); - rec_build_module_fabric_dependent_memory_bank_bitstream(bitstream_manager, top_block, - module_manager, top_module, top_module, - config_region, - bl_addr_port_info.get_width(), - wl_addr_port_info.get_width(), - bl_port_info.get_width(), - wl_port_info.get_width(), - cur_mem_index, - fabric_bitstream, - fabric_bitstream_region); - } - break; - } - case CONFIG_MEM_QL_MEMORY_BANK: { - build_module_fabric_dependent_bitstream_ql_memory_bank(config_protocol, circuit_lib, - bitstream_manager, top_block, - module_manager, top_module, - fabric_bitstream); - break; - } - case CONFIG_MEM_FRAME_BASED: { - - /* Find address port size */ - ModulePortId addr_port = module_manager.find_module_port(top_module, std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort addr_port_info = module_manager.module_port(top_module, addr_port); - - /* Reserve bits before build-up */ - fabric_bitstream.set_use_address(true); - fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); - fabric_bitstream.set_address_length(addr_port_info.get_width()); - - /* Avoid use don't care if there is only a region */ - char bitstream_dont_care_char = DONT_CARE_CHAR; - if (1 == module_manager.regions(top_module).size()) { - bitstream_dont_care_char = '0'; - } - - /* Find the maximum decoder address among all the configurable regions */ - size_t max_decoder_addr_size = 0; - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - std::vector configurable_children = module_manager.region_configurable_children(top_module, config_region); - /* Bypass the regions that have no decoders */ - if ( (0 == configurable_children.size()) - || (1 == configurable_children.size())) { - continue; - } - ModuleId decoder_module = configurable_children.back(); - ModulePortId decoder_addr_port_id = module_manager.find_module_port(decoder_module, DECODER_ADDRESS_PORT_NAME); - BasicPort decoder_addr_port = module_manager.module_port(decoder_module, decoder_addr_port_id); - max_decoder_addr_size = std::max(max_decoder_addr_size, decoder_addr_port.get_width()); - } - - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - std::vector configurable_children = module_manager.region_configurable_children(top_module, config_region); - - /* Bypass non-configurable regions */ - if (0 == configurable_children.size()) { - continue; + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + FabricBitRegionId fabric_bitstream_region = + fabric_bitstream.add_region(); + rec_build_module_fabric_dependent_chain_bitstream( + bitstream_manager, top_block, module_manager, top_module, top_module, + config_region, fabric_bitstream, fabric_bitstream_region); } - /* Find the idle address bit which should be added to the head of the address bit - * This depends on the number of address bits required by this region - * For example: - * Top-level address is addr[0:4] - * There are 4 decoders in the top-level module, whose address sizes are - * decoder A: addr[0:4] - * decoder B: addr[0:3] - * decoder C: addr[0:2] - * decoder D: addr[0:3] - * For decoder A, the address fit well - * For decoder B, an idle bit should be added '0' + addr[0:3] - * For decoder C, two idle bits should be added '00' + addr[0:2] - * For decoder D, an idle bit should be added '0' + addr[0:3] - */ - ModuleId decoder_module = configurable_children.back(); - ModulePortId decoder_addr_port_id = module_manager.find_module_port(decoder_module, DECODER_ADDRESS_PORT_NAME); - BasicPort decoder_addr_port = module_manager.module_port(decoder_module, decoder_addr_port_id); - VTR_ASSERT(max_decoder_addr_size >= decoder_addr_port.get_width()); - std::vector idle_addr_bits(max_decoder_addr_size - decoder_addr_port.get_width(), bitstream_dont_care_char); - - FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region(); - rec_build_module_fabric_dependent_frame_bitstream(bitstream_manager, - std::vector(1, top_block), - module_manager, - top_module, - config_region, - std::vector(1, top_module), - idle_addr_bits, - bitstream_dont_care_char, - fabric_bitstream, - fabric_bitstream_region); + break; } - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid SRAM organization.\n"); - exit(1); + case CONFIG_MEM_SCAN_CHAIN: { + /* Reserve bits before build-up */ + fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); + + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + FabricBitRegionId fabric_bitstream_region = + fabric_bitstream.add_region(); + rec_build_module_fabric_dependent_chain_bitstream( + bitstream_manager, top_block, module_manager, top_module, top_module, + config_region, fabric_bitstream, fabric_bitstream_region); + fabric_bitstream.reverse_region_bits(fabric_bitstream_region); + } + break; + } + case CONFIG_MEM_MEMORY_BANK: { + /* Find global BL address port size */ + ModulePortId bl_addr_port = module_manager.find_module_port( + top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); + BasicPort bl_addr_port_info = + module_manager.module_port(top_module, bl_addr_port); + + /* Find global WL address port size */ + ModulePortId wl_addr_port = module_manager.find_module_port( + top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); + BasicPort wl_addr_port_info = + module_manager.module_port(top_module, wl_addr_port); + + /* Reserve bits before build-up */ + fabric_bitstream.set_use_address(true); + fabric_bitstream.set_use_wl_address(true); + fabric_bitstream.set_bl_address_length(bl_addr_port_info.get_width()); + fabric_bitstream.set_wl_address_length(wl_addr_port_info.get_width()); + fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); + + /* Build bitstreams by region */ + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + size_t cur_mem_index = 0; + + /* Find port information for local BL and WL decoder in this region */ + std::vector configurable_children = + module_manager.region_configurable_children(top_module, + config_region); + VTR_ASSERT(2 <= configurable_children.size()); + ModuleId bl_decoder_module = + configurable_children[configurable_children.size() - 2]; + ModuleId wl_decoder_module = + configurable_children[configurable_children.size() - 1]; + + ModulePortId bl_port = module_manager.find_module_port( + bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort bl_port_info = + module_manager.module_port(bl_decoder_module, bl_port); + + ModulePortId wl_port = module_manager.find_module_port( + wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort wl_port_info = + module_manager.module_port(wl_decoder_module, wl_port); + + /* Build the bitstream for all the blocks in this region */ + FabricBitRegionId fabric_bitstream_region = + fabric_bitstream.add_region(); + rec_build_module_fabric_dependent_memory_bank_bitstream( + bitstream_manager, top_block, module_manager, top_module, top_module, + config_region, bl_addr_port_info.get_width(), + wl_addr_port_info.get_width(), bl_port_info.get_width(), + wl_port_info.get_width(), cur_mem_index, fabric_bitstream, + fabric_bitstream_region); + } + break; + } + case CONFIG_MEM_QL_MEMORY_BANK: { + build_module_fabric_dependent_bitstream_ql_memory_bank( + config_protocol, circuit_lib, bitstream_manager, top_block, + module_manager, top_module, fabric_bitstream); + break; + } + case CONFIG_MEM_FRAME_BASED: { + /* Find address port size */ + ModulePortId addr_port = module_manager.find_module_port( + top_module, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort addr_port_info = + module_manager.module_port(top_module, addr_port); + + /* Reserve bits before build-up */ + fabric_bitstream.set_use_address(true); + fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); + fabric_bitstream.set_address_length(addr_port_info.get_width()); + + /* Avoid use don't care if there is only a region */ + char bitstream_dont_care_char = DONT_CARE_CHAR; + if (1 == module_manager.regions(top_module).size()) { + bitstream_dont_care_char = '0'; + } + + /* Find the maximum decoder address among all the configurable regions */ + size_t max_decoder_addr_size = 0; + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + std::vector configurable_children = + module_manager.region_configurable_children(top_module, + config_region); + /* Bypass the regions that have no decoders */ + if ((0 == configurable_children.size()) || + (1 == configurable_children.size())) { + continue; + } + ModuleId decoder_module = configurable_children.back(); + ModulePortId decoder_addr_port_id = module_manager.find_module_port( + decoder_module, DECODER_ADDRESS_PORT_NAME); + BasicPort decoder_addr_port = + module_manager.module_port(decoder_module, decoder_addr_port_id); + max_decoder_addr_size = + std::max(max_decoder_addr_size, decoder_addr_port.get_width()); + } + + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + std::vector configurable_children = + module_manager.region_configurable_children(top_module, + config_region); + + /* Bypass non-configurable regions */ + if (0 == configurable_children.size()) { + continue; + } + + /* Find the idle address bit which should be added to the head of the + * address bit This depends on the number of address bits required by + * this region For example: Top-level address is addr[0:4] There are 4 + * decoders in the top-level module, whose address sizes are decoder A: + * addr[0:4] decoder B: addr[0:3] decoder C: addr[0:2] decoder D: + * addr[0:3] For decoder A, the address fit well For decoder B, an idle + * bit should be added '0' + addr[0:3] For decoder C, two idle bits + * should be added '00' + addr[0:2] For decoder D, an idle bit should be + * added '0' + addr[0:3] + */ + ModuleId decoder_module = configurable_children.back(); + ModulePortId decoder_addr_port_id = module_manager.find_module_port( + decoder_module, DECODER_ADDRESS_PORT_NAME); + BasicPort decoder_addr_port = + module_manager.module_port(decoder_module, decoder_addr_port_id); + VTR_ASSERT(max_decoder_addr_size >= decoder_addr_port.get_width()); + std::vector idle_addr_bits( + max_decoder_addr_size - decoder_addr_port.get_width(), + bitstream_dont_care_char); + + FabricBitRegionId fabric_bitstream_region = + fabric_bitstream.add_region(); + rec_build_module_fabric_dependent_frame_bitstream( + bitstream_manager, std::vector(1, top_block), + module_manager, top_module, config_region, + std::vector(1, top_module), idle_addr_bits, + bitstream_dont_care_char, fabric_bitstream, fabric_bitstream_region); + } + break; + } + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid SRAM organization.\n"); + exit(1); } /* Time-consuming sanity check: Uncomment these codes only for debugging!!! - * Check which configuration bits are not touched + * Check which configuration bits are not touched */ /* for (const ConfigBitId& config_bit : bitstream_manager.bits()) { - std::vector::iterator it = std::find(fabric_bitstream.begin(), fabric_bitstream.end(), config_bit); - if (it == fabric_bitstream.end()) { - std::vector block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, bitstream_manager.bit_parent_block(config_bit)); - std::string block_hierarchy_name; - for (const ConfigBlockId& temp_block : block_hierarchy) { - block_hierarchy_name += std::string("/") + bitstream_manager.block_name(temp_block); + std::vector::iterator it = std::find(fabric_bitstream.begin(), + fabric_bitstream.end(), config_bit); if (it == fabric_bitstream.end()) { + std::vector block_hierarchy = + find_bitstream_manager_block_hierarchy(bitstream_manager, + bitstream_manager.bit_parent_block(config_bit)); std::string + block_hierarchy_name; for (const ConfigBlockId& temp_block : block_hierarchy) + { block_hierarchy_name += std::string("/") + + bitstream_manager.block_name(temp_block); } - vpr_printf(TIO_MESSAGE_INFO, - "bit (parent_block = %s) is not touched!\n", + vpr_printf(TIO_MESSAGE_INFO, + "bit (parent_block = %s) is not touched!\n", block_hierarchy_name.c_str()); } } @@ -688,25 +740,25 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc } /******************************************************************** - * A top-level function re-organizes the bitstream for a specific + * A top-level function re-organizes the bitstream for a specific * FPGA fabric, where configuration bits are organized in the sequence * that can be directly loaded to the FPGA configuration protocol. * Support: * 1. Configuration chain * 2. Memory decoders * This function does NOT modify the bitstream database - * Instead, it builds a vector of ids for configuration bits in bitstream manager + * Instead, it builds a vector of ids for configuration bits in bitstream + *manager * - * This function can be called ONLY after the function build_device_bitstream() - * Note that this function does NOT decode bitstreams from circuit implementation - * It was done in the function build_device_bitstream() + * This function can be called ONLY after the function build_device_bitstream() + * Note that this function does NOT decode bitstreams from circuit + *implementation It was done in the function build_device_bitstream() *******************************************************************/ -FabricBitstream build_fabric_dependent_bitstream(const BitstreamManager& bitstream_manager, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const bool& verbose) { - FabricBitstream fabric_bitstream; +FabricBitstream build_fabric_dependent_bitstream( + const BitstreamManager& bitstream_manager, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const ConfigProtocol& config_protocol, const bool& verbose) { + FabricBitstream fabric_bitstream; vtr::ScopedStartFinishTimer timer("\nBuild fabric dependent bitstream\n"); @@ -716,19 +768,19 @@ FabricBitstream build_fabric_dependent_bitstream(const BitstreamManager& bitstre VTR_ASSERT(true == module_manager.valid_module_id(top_module)); /* Find the top block in bitstream manager, which has not parents */ - std::vector top_block = find_bitstream_manager_top_blocks(bitstream_manager); + std::vector top_block = + find_bitstream_manager_top_blocks(bitstream_manager); /* Make sure we have only 1 top block and its name matches the top module */ VTR_ASSERT(1 == top_block.size()); - VTR_ASSERT(0 == top_module_name.compare(bitstream_manager.block_name(top_block[0]))); + VTR_ASSERT( + 0 == top_module_name.compare(bitstream_manager.block_name(top_block[0]))); /* Start build-up formally */ - build_module_fabric_dependent_bitstream(config_protocol, circuit_lib, - bitstream_manager, top_block[0], - module_manager, top_module, - fabric_bitstream); + build_module_fabric_dependent_bitstream( + config_protocol, circuit_lib, bitstream_manager, top_block[0], + module_manager, top_module, fabric_bitstream); - VTR_LOGV(verbose, - "Built %lu configuration bits for fabric\n", + VTR_LOGV(verbose, "Built %lu configuration bits for fabric\n", fabric_bitstream.num_bits()); return fabric_bitstream; diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.h b/openfpga/src/fpga_bitstream/build_fabric_bitstream.h index 8905b03a5..5f5deb1c6 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.h @@ -5,9 +5,10 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "config_protocol.h" -#include "circuit_library.h" + #include "bitstream_manager.h" +#include "circuit_library.h" +#include "config_protocol.h" #include "fabric_bitstream.h" #include "module_manager.h" @@ -18,11 +19,10 @@ /* begin namespace openfpga */ namespace openfpga { -FabricBitstream build_fabric_dependent_bitstream(const BitstreamManager& bitstream_manager, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const bool& verbose); +FabricBitstream build_fabric_dependent_bitstream( + const BitstreamManager& bitstream_manager, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const ConfigProtocol& config_protocol, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp index 96833b984..97fe97d90 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -2,9 +2,9 @@ * This file includes functions to build fabric dependent bitstream * for memory bank configuration protocol *******************************************************************/ -#include -#include #include +#include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" @@ -12,16 +12,14 @@ #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_decode.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" - -#include "decoder_library_utils.h" #include "bitstream_manager_utils.h" -#include "memory_utils.h" -#include "memory_bank_utils.h" #include "build_fabric_bitstream_memory_bank.h" +#include "decoder_library_utils.h" +#include "memory_bank_utils.h" +#include "memory_utils.h" +#include "openfpga_decode.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" /* begin namespace openfpga */ namespace openfpga { @@ -30,90 +28,93 @@ namespace openfpga { * This function aims to build a bitstream for memory-bank protocol * It will walk through all the configurable children under a module * in a recursive way, following a Depth-First Search (DFS) strategy - * For each configuration child, we use its instance name as a key to spot the + * For each configuration child, we use its instance name as a key to spot the * configuration bits in bitstream manager. - * Note that it is guarentee that the instance name in module manager is + * Note that it is guarentee that the instance name in module manager is * consistent with the block names in bitstream manager - * We use this link to reorganize the bitstream in the sequence of memories as we stored - * in the configurable_children() and configurable_child_instances() of each module of module manager + * We use this link to reorganize the bitstream in the sequence of memories as + *we stored in the configurable_children() and configurable_child_instances() of + *each module of module manager * * In such configuration organization, each memory cell has an unique index. * Using this index, we can infer the address codes for both BL and WL decoders. * Note that, we must get the number of BLs and WLs before using this function! *******************************************************************/ -static -void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const BitstreamManager& bitstream_manager, - const ConfigBlockId& parent_block, - const ModuleManager& module_manager, - const ModuleId& top_module, - const ModuleId& parent_module, - const ConfigRegionId& config_region, - const ConfigProtocol& config_protocol, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const size_t& bl_addr_size, - const size_t& wl_addr_size, - size_t& num_bls_cur_tile, - const std::map& bl_start_index_per_tile, - size_t& num_wls_cur_tile, - const std::map& wl_start_index_per_tile, - vtr::Point& tile_coord, - std::map, size_t>& cur_mem_index, - FabricBitstream& fabric_bitstream, - const FabricBitRegionId& fabric_bitstream_region) { - - /* Depth-first search: if we have any children in the parent_block, - * we dive to the next level first! +static void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream( + const BitstreamManager& bitstream_manager, const ConfigBlockId& parent_block, + const ModuleManager& module_manager, const ModuleId& top_module, + const ModuleId& parent_module, const ConfigRegionId& config_region, + const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, const size_t& bl_addr_size, + const size_t& wl_addr_size, size_t& num_bls_cur_tile, + const std::map& bl_start_index_per_tile, + size_t& num_wls_cur_tile, + const std::map& wl_start_index_per_tile, + vtr::Point& tile_coord, std::map, size_t>& cur_mem_index, + FabricBitstream& fabric_bitstream, + const FabricBitRegionId& fabric_bitstream_region) { + /* Depth-first search: if we have any children in the parent_block, + * we dive to the next level first! */ if (0 < bitstream_manager.block_children(parent_block).size()) { /* For top module: * - Use regional configurable children - * - we will skip the two decoders at the end of the configurable children list + * - we will skip the two decoders at the end of the configurable children + * list */ if (parent_module == top_module) { - std::vector configurable_children = module_manager.region_configurable_children(parent_module, config_region); + std::vector configurable_children = + module_manager.region_configurable_children(parent_module, + config_region); - VTR_ASSERT(2 <= configurable_children.size()); - size_t num_config_child_to_skip = estimate_num_configurable_children_to_skip_by_config_protocol(config_protocol, - configurable_children.size()); - size_t num_configurable_children = configurable_children.size() - num_config_child_to_skip; + VTR_ASSERT(2 <= configurable_children.size()); + size_t num_config_child_to_skip = + estimate_num_configurable_children_to_skip_by_config_protocol( + config_protocol, configurable_children.size()); + size_t num_configurable_children = + configurable_children.size() - num_config_child_to_skip; /* Early exit if there is no configurable children */ if (0 == num_configurable_children) { - /* Ensure that there should be no configuration bits in the parent block */ + /* Ensure that there should be no configuration bits in the parent block + */ VTR_ASSERT(0 == bitstream_manager.block_bits(parent_block).size()); return; } - for (size_t child_id = 0; child_id < num_configurable_children; ++child_id) { - ModuleId child_module = configurable_children[child_id]; - size_t child_instance = module_manager.region_configurable_child_instances(parent_module, config_region)[child_id]; + for (size_t child_id = 0; child_id < num_configurable_children; + ++child_id) { + ModuleId child_module = configurable_children[child_id]; + size_t child_instance = + module_manager.region_configurable_child_instances( + parent_module, config_region)[child_id]; - tile_coord = module_manager.region_configurable_child_coordinates(parent_module, config_region)[child_id]; - num_bls_cur_tile = find_module_ql_memory_bank_num_blwls(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_BL); - num_wls_cur_tile = find_module_ql_memory_bank_num_blwls(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_WL); + tile_coord = module_manager.region_configurable_child_coordinates( + parent_module, config_region)[child_id]; + num_bls_cur_tile = find_module_ql_memory_bank_num_blwls( + module_manager, child_module, circuit_lib, sram_model, + CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_BL); + num_wls_cur_tile = find_module_ql_memory_bank_num_blwls( + module_manager, child_module, circuit_lib, sram_model, + CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_WL); /* Get the instance name and ensure it is not empty */ - std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); - - /* Find the child block that matches the instance name! */ - ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name); + std::string instance_name = module_manager.instance_name( + parent_module, child_module, child_instance); + + /* Find the child block that matches the instance name! */ + ConfigBlockId child_block = + bitstream_manager.find_child_block(parent_block, instance_name); /* We must have one valid block id! */ VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); /* Go recursively */ - rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, child_block, - module_manager, top_module, child_module, - config_region, - config_protocol, - circuit_lib, sram_model, - bl_addr_size, wl_addr_size, - num_bls_cur_tile, bl_start_index_per_tile, - num_wls_cur_tile, wl_start_index_per_tile, - tile_coord, - cur_mem_index, - fabric_bitstream, - fabric_bitstream_region); + rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream( + bitstream_manager, child_block, module_manager, top_module, + child_module, config_region, config_protocol, circuit_lib, sram_model, + bl_addr_size, wl_addr_size, num_bls_cur_tile, bl_start_index_per_tile, + num_wls_cur_tile, wl_start_index_per_tile, tile_coord, cur_mem_index, + fabric_bitstream, fabric_bitstream_region); } } else { VTR_ASSERT(parent_module != top_module); @@ -121,42 +122,42 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B * - Use configurable children directly * - no need to exclude decoders as they are not there */ - std::vector configurable_children = module_manager.configurable_children(parent_module); + std::vector configurable_children = + module_manager.configurable_children(parent_module); size_t num_configurable_children = configurable_children.size(); /* Early exit if there is no configurable children */ if (0 == num_configurable_children) { - /* Ensure that there should be no configuration bits in the parent block */ + /* Ensure that there should be no configuration bits in the parent block + */ VTR_ASSERT(0 == bitstream_manager.block_bits(parent_block).size()); return; } - for (size_t child_id = 0; child_id < num_configurable_children; ++child_id) { - ModuleId child_module = configurable_children[child_id]; - size_t child_instance = module_manager.configurable_child_instances(parent_module)[child_id]; + for (size_t child_id = 0; child_id < num_configurable_children; + ++child_id) { + ModuleId child_module = configurable_children[child_id]; + size_t child_instance = + module_manager.configurable_child_instances(parent_module)[child_id]; /* Get the instance name and ensure it is not empty */ - std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); - - /* Find the child block that matches the instance name! */ - ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name); + std::string instance_name = module_manager.instance_name( + parent_module, child_module, child_instance); + + /* Find the child block that matches the instance name! */ + ConfigBlockId child_block = + bitstream_manager.find_child_block(parent_block, instance_name); /* We must have one valid block id! */ VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); /* Go recursively */ - rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, child_block, - module_manager, top_module, child_module, - config_region, - config_protocol, - circuit_lib, sram_model, - bl_addr_size, wl_addr_size, - num_bls_cur_tile, bl_start_index_per_tile, - num_wls_cur_tile, wl_start_index_per_tile, - tile_coord, - cur_mem_index, - fabric_bitstream, - fabric_bitstream_region); + rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream( + bitstream_manager, child_block, module_manager, top_module, + child_module, config_region, config_protocol, circuit_lib, sram_model, + bl_addr_size, wl_addr_size, num_bls_cur_tile, bl_start_index_per_tile, + num_wls_cur_tile, wl_start_index_per_tile, tile_coord, cur_mem_index, + fabric_bitstream, fabric_bitstream_region); } } /* Ensure that there should be no configuration bits in the parent block */ @@ -165,45 +166,57 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B return; } - /* Note that, reach here, it means that this is a leaf node. + /* Note that, reach here, it means that this is a leaf node. * We add the configuration bits to the fabric_bitstream, * And then, we can return */ - for (const ConfigBitId& config_bit : bitstream_manager.block_bits(parent_block)) { + for (const ConfigBitId& config_bit : + bitstream_manager.block_bits(parent_block)) { FabricBitId fabric_bit = fabric_bitstream.add_bit(config_bit); - + /* The BL address to be decoded depends on the protocol * - flatten BLs: use 1-hot decoding * - BL decoders: fully encoded * - Shift register: use 1-hot decoding */ - size_t cur_bl_index = bl_start_index_per_tile.at(tile_coord.x()) + cur_mem_index[tile_coord] % num_bls_cur_tile; + size_t cur_bl_index = bl_start_index_per_tile.at(tile_coord.x()) + + cur_mem_index[tile_coord] % num_bls_cur_tile; std::vector bl_addr_bits_vec; if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { bl_addr_bits_vec = itobin_charvec(cur_bl_index, bl_addr_size); - } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() - || BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { - bl_addr_bits_vec = ito1hot_charvec(cur_bl_index, bl_addr_size, DONT_CARE_CHAR); + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() || + BLWL_PROTOCOL_SHIFT_REGISTER == + config_protocol.bl_protocol_type()) { + bl_addr_bits_vec = + ito1hot_charvec(cur_bl_index, bl_addr_size, DONT_CARE_CHAR); } /* Find WL address */ - size_t cur_wl_index = wl_start_index_per_tile.at(tile_coord.y()) + std::floor(cur_mem_index[tile_coord] / num_bls_cur_tile); + size_t cur_wl_index = + wl_start_index_per_tile.at(tile_coord.y()) + + std::floor(cur_mem_index[tile_coord] / num_bls_cur_tile); std::vector wl_addr_bits_vec; if (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) { wl_addr_bits_vec = itobin_charvec(cur_wl_index, wl_addr_size); - } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type() - || BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()) { + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type() || + BLWL_PROTOCOL_SHIFT_REGISTER == + config_protocol.wl_protocol_type()) { wl_addr_bits_vec = ito1hot_charvec(cur_wl_index, wl_addr_size); } /* Set BL address */ - fabric_bitstream.set_bit_bl_address(fabric_bit, bl_addr_bits_vec, BLWL_PROTOCOL_DECODER != config_protocol.bl_protocol_type()); + fabric_bitstream.set_bit_bl_address( + fabric_bit, bl_addr_bits_vec, + BLWL_PROTOCOL_DECODER != config_protocol.bl_protocol_type()); /* Set WL address */ - fabric_bitstream.set_bit_wl_address(fabric_bit, wl_addr_bits_vec, BLWL_PROTOCOL_DECODER != config_protocol.wl_protocol_type()); - + fabric_bitstream.set_bit_wl_address( + fabric_bit, wl_addr_bits_vec, + BLWL_PROTOCOL_DECODER != config_protocol.wl_protocol_type()); + /* Set data input */ - fabric_bitstream.set_bit_din(fabric_bit, bitstream_manager.bit_value(config_bit)); + fabric_bitstream.set_bit_din(fabric_bit, + bitstream_manager.bit_value(config_bit)); /* Add the bit to the region */ fabric_bitstream.add_bit_to_region(fabric_bitstream_region, fabric_bit); @@ -217,73 +230,101 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B * Main function to build a fabric-dependent bitstream * by considering the QuickLogic memory banks *******************************************************************/ -void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol& config_protocol, - const CircuitLibrary& circuit_lib, - const BitstreamManager& bitstream_manager, - const ConfigBlockId& top_block, - const ModuleManager& module_manager, - const ModuleId& top_module, - FabricBitstream& fabric_bitstream) { +void build_module_fabric_dependent_bitstream_ql_memory_bank( + const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib, + const BitstreamManager& bitstream_manager, const ConfigBlockId& top_block, + const ModuleManager& module_manager, const ModuleId& top_module, + FabricBitstream& fabric_bitstream) { /* Ensure we are in the correct type of configuration protocol*/ VTR_ASSERT(config_protocol.type() == CONFIG_MEM_QL_MEMORY_BANK); - /* For different BL control protocol, the address ports are different - * - flatten BLs: the address port should be raw BL ports at top-level module. - * Due to each configuration region has separated BLs, the address port should be the one with largest size - * - BL decoders: the address port should be the BL address port at top-level module - * - Shift register: the address port size will be calculated by the total number of unique BLs per child module in each configuration region - * Due to each configuration region has separated BLs, the address port should be the one with largest size + /* For different BL control protocol, the address ports are different + * - flatten BLs: the address port should be raw BL ports at top-level module. + * Due to each configuration region has separated BLs, the + * address port should be the one with largest size + * - BL decoders: the address port should be the BL address port at top-level + * module + * - Shift register: the address port size will be calculated by the total + * number of unique BLs per child module in each configuration region Due to + * each configuration region has separated BLs, the address port should be the + * one with largest size */ ModulePortId bl_addr_port; BasicPort bl_addr_port_info; if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { - bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); + bl_addr_port = module_manager.find_module_port( + top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port); } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - ModulePortId temp_bl_addr_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), config_region)); - BasicPort temp_bl_addr_port_info = module_manager.module_port(top_module, temp_bl_addr_port); - if (!bl_addr_port || (temp_bl_addr_port_info.get_width() > bl_addr_port_info.get_width())) { + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + ModulePortId temp_bl_addr_port = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(MEMORY_BL_PORT_NAME), config_region)); + BasicPort temp_bl_addr_port_info = + module_manager.module_port(top_module, temp_bl_addr_port); + if (!bl_addr_port || (temp_bl_addr_port_info.get_width() > + bl_addr_port_info.get_width())) { bl_addr_port = temp_bl_addr_port; bl_addr_port_info = temp_bl_addr_port_info; } } } else { - VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); + VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == + config_protocol.bl_protocol_type()); bl_addr_port_info.set_width(1); /* Deposit minimum width */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - size_t num_bls = compute_memory_bank_regional_num_bls(module_manager, top_module, config_region, circuit_lib, config_protocol.memory_model()); - bl_addr_port_info.set_width(std::max(num_bls, bl_addr_port_info.get_width())); + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + size_t num_bls = compute_memory_bank_regional_num_bls( + module_manager, top_module, config_region, circuit_lib, + config_protocol.memory_model()); + bl_addr_port_info.set_width( + std::max(num_bls, bl_addr_port_info.get_width())); } } - /* For different WL control protocol, the address ports are different - * - flatten WLs: the address port should be raw WL ports at top-level module. - * Due to each configuration region has separated WLs, the address port should be the one with largest size - * - WL decoders: the address port should be the WL address port at top-level module - * - Shift register: the address port size will be calculated by the total number of unique WLs per child module in each configuration region - * Due to each configuration region has separated WLs, the address port should be the one with largest size + /* For different WL control protocol, the address ports are different + * - flatten WLs: the address port should be raw WL ports at top-level module. + * Due to each configuration region has separated WLs, the + * address port should be the one with largest size + * - WL decoders: the address port should be the WL address port at top-level + * module + * - Shift register: the address port size will be calculated by the total + * number of unique WLs per child module in each configuration region Due to + * each configuration region has separated WLs, the address port should be the + * one with largest size */ ModulePortId wl_addr_port; BasicPort wl_addr_port_info; if (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) { - wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); + wl_addr_port = module_manager.find_module_port( + top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port); } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - ModulePortId temp_wl_addr_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region)); - BasicPort temp_wl_addr_port_info = module_manager.module_port(top_module, temp_wl_addr_port); - if (!wl_addr_port || (temp_wl_addr_port_info.get_width() > wl_addr_port_info.get_width())) { + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + ModulePortId temp_wl_addr_port = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(MEMORY_WL_PORT_NAME), config_region)); + BasicPort temp_wl_addr_port_info = + module_manager.module_port(top_module, temp_wl_addr_port); + if (!wl_addr_port || (temp_wl_addr_port_info.get_width() > + wl_addr_port_info.get_width())) { wl_addr_port = temp_wl_addr_port; wl_addr_port_info = temp_wl_addr_port_info; } } } else { - VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()); + VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == + config_protocol.wl_protocol_type()); wl_addr_port_info.set_width(1); /* Deposit minimum width */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - size_t num_wls = compute_memory_bank_regional_num_wls(module_manager, top_module, config_region, circuit_lib, config_protocol.memory_model()); - wl_addr_port_info.set_width(std::max(num_wls, wl_addr_port_info.get_width())); + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { + size_t num_wls = compute_memory_bank_regional_num_wls( + module_manager, top_module, config_region, circuit_lib, + config_protocol.memory_model()); + wl_addr_port_info.set_width( + std::max(num_wls, wl_addr_port_info.get_width())); } } @@ -295,76 +336,100 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); /* Build bitstreams by region */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + for (const ConfigRegionId& config_region : + module_manager.regions(top_module)) { /* Find port information for local BL and WL decoder in this region */ - std::vector configurable_children = module_manager.region_configurable_children(top_module, config_region); - VTR_ASSERT(2 <= configurable_children.size()); + std::vector configurable_children = + module_manager.region_configurable_children(top_module, config_region); + VTR_ASSERT(2 <= configurable_children.size()); /* Build the bitstream for all the blocks in this region */ FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region(); - - /* Find the BL/WL port (different region may have different sizes of BL/WLs) */ + + /* Find the BL/WL port (different region may have different sizes of BL/WLs) + */ ModulePortId cur_bl_addr_port; BasicPort cur_bl_addr_port_info; if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { - cur_bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); - cur_bl_addr_port_info = module_manager.module_port(top_module, cur_bl_addr_port); + cur_bl_addr_port = module_manager.find_module_port( + top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); + cur_bl_addr_port_info = + module_manager.module_port(top_module, cur_bl_addr_port); } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { - cur_bl_addr_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), config_region)); - cur_bl_addr_port_info = module_manager.module_port(top_module, cur_bl_addr_port); + cur_bl_addr_port = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(MEMORY_BL_PORT_NAME), config_region)); + cur_bl_addr_port_info = + module_manager.module_port(top_module, cur_bl_addr_port); } else { - VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); - cur_bl_addr_port_info.set_width(compute_memory_bank_regional_num_bls(module_manager, top_module, config_region, circuit_lib, config_protocol.memory_model())); + VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == + config_protocol.bl_protocol_type()); + cur_bl_addr_port_info.set_width(compute_memory_bank_regional_num_bls( + module_manager, top_module, config_region, circuit_lib, + config_protocol.memory_model())); } ModulePortId cur_wl_addr_port; BasicPort cur_wl_addr_port_info; if (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) { - cur_wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); - cur_wl_addr_port_info = module_manager.module_port(top_module, cur_wl_addr_port); + cur_wl_addr_port = module_manager.find_module_port( + top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); + cur_wl_addr_port_info = + module_manager.module_port(top_module, cur_wl_addr_port); } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { - cur_wl_addr_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region)); - cur_wl_addr_port_info = module_manager.module_port(top_module, cur_wl_addr_port); + cur_wl_addr_port = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(MEMORY_WL_PORT_NAME), config_region)); + cur_wl_addr_port_info = + module_manager.module_port(top_module, cur_wl_addr_port); } else { - VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()); - cur_wl_addr_port_info.set_width(compute_memory_bank_regional_num_wls(module_manager, top_module, config_region, circuit_lib, config_protocol.memory_model())); + VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == + config_protocol.wl_protocol_type()); + cur_wl_addr_port_info.set_width(compute_memory_bank_regional_num_wls( + module_manager, top_module, config_region, circuit_lib, + config_protocol.memory_model())); } - /************************************************************** + /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric - * The distribution is a matrix which contains the starting index of BL/WL for each column or row + * The distribution is a matrix which contains the starting index of BL/WL + * for each column or row */ - std::pair child_x_range = compute_memory_bank_regional_configurable_child_x_range(module_manager, top_module, config_region); - std::pair child_y_range = compute_memory_bank_regional_configurable_child_y_range(module_manager, top_module, config_region); + std::pair child_x_range = + compute_memory_bank_regional_configurable_child_x_range( + module_manager, top_module, config_region); + std::pair child_y_range = + compute_memory_bank_regional_configurable_child_y_range( + module_manager, top_module, config_region); - std::map num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module, - config_region, - circuit_lib, config_protocol.memory_model()); - std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, - config_region, - circuit_lib, config_protocol.memory_model()); + std::map num_bls_per_tile = + compute_memory_bank_regional_bitline_numbers_per_tile( + module_manager, top_module, config_region, circuit_lib, + config_protocol.memory_model()); + std::map num_wls_per_tile = + compute_memory_bank_regional_wordline_numbers_per_tile( + module_manager, top_module, config_region, circuit_lib, + config_protocol.memory_model()); - std::map bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile); - std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); + std::map bl_start_index_per_tile = + compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, + num_bls_per_tile); + std::map wl_start_index_per_tile = + compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, + num_wls_per_tile); vtr::Point temp_coord; std::map, size_t> cur_mem_index; size_t temp_num_bls_cur_tile = 0; size_t temp_num_wls_cur_tile = 0; - rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, top_block, - module_manager, top_module, top_module, - config_region, - config_protocol, - circuit_lib, config_protocol.memory_model(), - cur_bl_addr_port_info.get_width(), - cur_wl_addr_port_info.get_width(), - temp_num_bls_cur_tile, bl_start_index_per_tile, - temp_num_wls_cur_tile, wl_start_index_per_tile, - temp_coord, - cur_mem_index, - fabric_bitstream, - fabric_bitstream_region); + rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream( + bitstream_manager, top_block, module_manager, top_module, top_module, + config_region, config_protocol, circuit_lib, + config_protocol.memory_model(), cur_bl_addr_port_info.get_width(), + cur_wl_addr_port_info.get_width(), temp_num_bls_cur_tile, + bl_start_index_per_tile, temp_num_wls_cur_tile, wl_start_index_per_tile, + temp_coord, cur_mem_index, fabric_bitstream, fabric_bitstream_region); } } diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.h b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.h index 58d511394..6068526bd 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.h +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.h @@ -5,9 +5,10 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "config_protocol.h" -#include "circuit_library.h" + #include "bitstream_manager.h" +#include "circuit_library.h" +#include "config_protocol.h" #include "fabric_bitstream.h" #include "module_manager.h" @@ -18,13 +19,11 @@ /* begin namespace openfpga */ namespace openfpga { -void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol& config_protocol, - const CircuitLibrary& circuit_lib, - const BitstreamManager& bitstream_manager, - const ConfigBlockId& top_block, - const ModuleManager& module_manager, - const ModuleId& top_module, - FabricBitstream& fabric_bitstream); +void build_module_fabric_dependent_bitstream_ql_memory_bank( + const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib, + const BitstreamManager& bitstream_manager, const ConfigBlockId& top_block, + const ModuleManager& module_manager, const ModuleId& top_module, + FabricBitstream& fabric_bitstream); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp index a28ba8425..52f07e4db 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp @@ -6,30 +6,25 @@ #include /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from vpr library */ -#include "vpr_utils.h" - -#include "pb_graph_utils.h" -#include "mux_utils.h" - +#include "build_grid_bitstream.h" +#include "build_mux_bitstream.h" #include "circuit_library_utils.h" - -#include "openfpga_interconnect_types.h" -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" -#include "mux_bitstream_constants.h" -#include "pb_type_utils.h" #include "lut_utils.h" #include "module_manager_utils.h" - -#include "build_mux_bitstream.h" +#include "mux_bitstream_constants.h" +#include "mux_utils.h" #include "openfpga_device_grid_utils.h" - -#include "build_grid_bitstream.h" +#include "openfpga_interconnect_types.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "pb_graph_utils.h" +#include "pb_type_utils.h" +#include "vpr_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -37,10 +32,10 @@ namespace openfpga { /******************************************************************** * Decode mode bits "01..." to a bitstream vector *******************************************************************/ -static -std::vector generate_mode_select_bitstream(const std::vector& mode_bits) { +static std::vector generate_mode_select_bitstream( + const std::vector& mode_bits) { std::vector mode_select_bitstream; - + for (const size_t& mode_bit : mode_bits) { /* Error out for unexpected bits */ VTR_ASSERT((0 == mode_bit) || (1 == mode_bit)); @@ -53,35 +48,33 @@ std::vector generate_mode_select_bitstream(const std::vector& mode /******************************************************************** * Generate bitstream for a primitive node and add it to bitstream manager *******************************************************************/ -static -void build_primitive_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& parent_configurable_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const VprDeviceAnnotation& device_annotation, - const PhysicalPb& physical_pb, - const PhysicalPbId& primitive_pb_id, - t_pb_type* primitive_pb_type) { - - /* Ensure a valid physical pritimive pb */ +static void build_primitive_bitstream( + BitstreamManager& bitstream_manager, + const ConfigBlockId& parent_configurable_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const VprDeviceAnnotation& device_annotation, const PhysicalPb& physical_pb, + const PhysicalPbId& primitive_pb_id, t_pb_type* primitive_pb_type) { + /* Ensure a valid physical pritimive pb */ if (nullptr == primitive_pb_type) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid primitive_pb_type!\n"); + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid primitive_pb_type!\n"); exit(1); } - CircuitModelId primitive_model = device_annotation.pb_type_circuit_model(primitive_pb_type); + CircuitModelId primitive_model = + device_annotation.pb_type_circuit_model(primitive_pb_type); VTR_ASSERT(CircuitModelId::INVALID() != primitive_model); - VTR_ASSERT( (CIRCUIT_MODEL_IOPAD == circuit_lib.model_type(primitive_model)) - || (CIRCUIT_MODEL_HARDLOGIC == circuit_lib.model_type(primitive_model)) - || (CIRCUIT_MODEL_FF == circuit_lib.model_type(primitive_model)) ); + VTR_ASSERT( + (CIRCUIT_MODEL_IOPAD == circuit_lib.model_type(primitive_model)) || + (CIRCUIT_MODEL_HARDLOGIC == circuit_lib.model_type(primitive_model)) || + (CIRCUIT_MODEL_FF == circuit_lib.model_type(primitive_model))); /* Find SRAM ports for mode-selection */ - std::vector primitive_mode_select_ports = find_circuit_mode_select_sram_ports(circuit_lib, primitive_model); + std::vector primitive_mode_select_ports = + find_circuit_mode_select_sram_ports(circuit_lib, primitive_model); /* We may have a port for mode select or not. */ - VTR_ASSERT( (0 == primitive_mode_select_ports.size()) - || (1 == primitive_mode_select_ports.size()) ); + VTR_ASSERT((0 == primitive_mode_select_ports.size()) || + (1 == primitive_mode_select_ports.size())); /* Generate bitstream for mode-select ports */ if (0 == primitive_mode_select_ports.size()) { @@ -90,38 +83,56 @@ void build_primitive_bitstream(BitstreamManager& bitstream_manager, std::vector mode_select_bitstream; if (true == physical_pb.valid_pb_id(primitive_pb_id)) { - mode_select_bitstream = generate_mode_select_bitstream(physical_pb.mode_bits(primitive_pb_id)); + mode_select_bitstream = + generate_mode_select_bitstream(physical_pb.mode_bits(primitive_pb_id)); /* If the physical pb contains fixed mode-select bitstream, overload here */ - if (false == physical_pb.fixed_mode_select_bitstream(primitive_pb_id).empty()) { - std::string fixed_mode_select_bitstream = physical_pb.fixed_mode_select_bitstream(primitive_pb_id); - size_t mode_bits_start_index = physical_pb.fixed_mode_select_bitstream_offset(primitive_pb_id); + if (false == + physical_pb.fixed_mode_select_bitstream(primitive_pb_id).empty()) { + std::string fixed_mode_select_bitstream = + physical_pb.fixed_mode_select_bitstream(primitive_pb_id); + size_t mode_bits_start_index = + physical_pb.fixed_mode_select_bitstream_offset(primitive_pb_id); /* Ensure the length matches!!! */ - if (mode_select_bitstream.size() - mode_bits_start_index < fixed_mode_select_bitstream.size()) { - VTR_LOG_ERROR("Unmatched length of fixed mode_select_bitstream %s!Expected to be less than %ld bits\n", - fixed_mode_select_bitstream.c_str(), - mode_select_bitstream.size() - mode_bits_start_index); + if (mode_select_bitstream.size() - mode_bits_start_index < + fixed_mode_select_bitstream.size()) { + VTR_LOG_ERROR( + "Unmatched length of fixed mode_select_bitstream %s!Expected to be " + "less than %ld bits\n", + fixed_mode_select_bitstream.c_str(), + mode_select_bitstream.size() - mode_bits_start_index); exit(1); } /* Overload the bitstream here */ - for (size_t bit_index = 0; bit_index < fixed_mode_select_bitstream.size(); ++bit_index) { - VTR_ASSERT('0' == fixed_mode_select_bitstream[bit_index] || '1' == fixed_mode_select_bitstream[bit_index]); - mode_select_bitstream[bit_index + mode_bits_start_index] = ('1' == fixed_mode_select_bitstream[bit_index]); + for (size_t bit_index = 0; bit_index < fixed_mode_select_bitstream.size(); + ++bit_index) { + VTR_ASSERT('0' == fixed_mode_select_bitstream[bit_index] || + '1' == fixed_mode_select_bitstream[bit_index]); + mode_select_bitstream[bit_index + mode_bits_start_index] = + ('1' == fixed_mode_select_bitstream[bit_index]); } } } else { /* get default mode_bits */ - mode_select_bitstream = generate_mode_select_bitstream(device_annotation.pb_type_mode_bits(primitive_pb_type)); + mode_select_bitstream = generate_mode_select_bitstream( + device_annotation.pb_type_mode_bits(primitive_pb_type)); } /* Ensure the length of bitstream matches the side of memory circuits */ - std::vector sram_models = find_circuit_sram_models(circuit_lib, primitive_model); + std::vector sram_models = + find_circuit_sram_models(circuit_lib, primitive_model); VTR_ASSERT(1 == sram_models.size()); - std::string mem_block_name = generate_memory_module_name(circuit_lib, primitive_model, sram_models[0], std::string(MEMORY_MODULE_POSTFIX)); + std::string mem_block_name = + generate_memory_module_name(circuit_lib, primitive_model, sram_models[0], + std::string(MEMORY_MODULE_POSTFIX)); ModuleId mem_module = module_manager.find_module(mem_block_name); - VTR_ASSERT (true == module_manager.valid_module_id(mem_module)); - ModulePortId mem_out_port_id = module_manager.find_module_port(mem_module, generate_configurable_memory_data_out_name()); - VTR_ASSERT(mode_select_bitstream.size() == module_manager.module_port(mem_module, mem_out_port_id).get_width()); + VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); + ModulePortId mem_out_port_id = module_manager.find_module_port( + mem_module, generate_configurable_memory_data_out_name()); + VTR_ASSERT( + mode_select_bitstream.size() == + module_manager.module_port(mem_module, mem_out_port_id).get_width()); - /* Create a block for the bitstream which corresponds to the memory module associated to the LUT */ + /* Create a block for the bitstream which corresponds to the memory module + * associated to the LUT */ ConfigBlockId mem_block = bitstream_manager.add_block(mem_block_name); bitstream_manager.add_child_block(parent_configurable_block, mem_block); @@ -131,277 +142,301 @@ void build_primitive_bitstream(BitstreamManager& bitstream_manager, /******************************************************************** * This function generates bitstream for a programmable routing - * multiplexer which drives an output pin of physical_pb_graph_node and its the input_edges + * multiplexer which drives an output pin of physical_pb_graph_node and its the + *input_edges * - * src_pb_graph_node.[in|out]_pins -----------------> des_pb_graph_node.[in|out]pins + * src_pb_graph_node.[in|out]_pins -----------------> + *des_pb_graph_node.[in|out]pins * /|\ * | * input_pins, edges, output_pins *******************************************************************/ -static -void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& parent_configurable_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, - const VprBitstreamAnnotation& bitstream_annotation, - const PhysicalPb& physical_pb, - t_pb_graph_pin* des_pb_graph_pin, - t_mode* physical_mode) { - /* Identify the number of fan-in (Consider interconnection edges of only selected mode) */ - t_interconnect* cur_interc = pb_graph_pin_interc(des_pb_graph_pin, physical_mode); +static void build_physical_block_pin_interc_bitstream( + BitstreamManager& bitstream_manager, + const ConfigBlockId& parent_configurable_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, const AtomContext& atom_ctx, + const VprDeviceAnnotation& device_annotation, + const VprBitstreamAnnotation& bitstream_annotation, + const PhysicalPb& physical_pb, t_pb_graph_pin* des_pb_graph_pin, + t_mode* physical_mode) { + /* Identify the number of fan-in (Consider interconnection edges of only + * selected mode) */ + t_interconnect* cur_interc = + pb_graph_pin_interc(des_pb_graph_pin, physical_mode); size_t fan_in = pb_graph_pin_inputs(des_pb_graph_pin, cur_interc).size(); - if ((nullptr == cur_interc) || (0 == fan_in)) { + if ((nullptr == cur_interc) || (0 == fan_in)) { /* No interconnection matched */ return; } /* Identify pin interconnection type */ - enum e_interconnect interc_type = device_annotation.interconnect_physical_type(cur_interc); + enum e_interconnect interc_type = + device_annotation.interconnect_physical_type(cur_interc); switch (interc_type) { - case DIRECT_INTERC: - /* Nothing to do, return */ - break; - case COMPLETE_INTERC: - case MUX_INTERC: { - /* Find the circuit model id of the mux, we need its design technology which matters the bitstream generation */ - CircuitModelId mux_model = device_annotation.interconnect_circuit_model(cur_interc); - VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)); + case DIRECT_INTERC: + /* Nothing to do, return */ + break; + case COMPLETE_INTERC: + case MUX_INTERC: { + /* Find the circuit model id of the mux, we need its design technology + * which matters the bitstream generation */ + CircuitModelId mux_model = + device_annotation.interconnect_circuit_model(cur_interc); + VTR_ASSERT(CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)); - /* Find the input size of the implementation of a routing multiplexer */ - size_t datapath_mux_size = fan_in; - VTR_ASSERT(true == valid_mux_implementation_num_inputs(datapath_mux_size)); + /* Find the input size of the implementation of a routing multiplexer */ + size_t datapath_mux_size = fan_in; + VTR_ASSERT(true == + valid_mux_implementation_num_inputs(datapath_mux_size)); - /* Cache input and output nets */ - std::vector input_nets; - AtomNetId output_net = AtomNetId::INVALID(); + /* Cache input and output nets */ + std::vector input_nets; + AtomNetId output_net = AtomNetId::INVALID(); - /* Find the path id: - * - if des pb is not valid, this is an unmapped pb, we can set a default path_id - * - There is no net mapped to des_pb_graph_pin we use default path id - * - There is a net mapped to des_pin_graph_pin: we find the path id - */ - const PhysicalPbId& des_pb_id = physical_pb.find_pb(des_pb_graph_pin->parent_node); - size_t mux_input_pin_id = 0; - if (true != physical_pb.valid_pb_id(des_pb_id)) { - mux_input_pin_id = DEFAULT_PATH_ID; - } else if (AtomNetId::INVALID() == physical_pb.pb_graph_pin_atom_net(des_pb_id, des_pb_graph_pin)) { - mux_input_pin_id = DEFAULT_PATH_ID; - } else { - output_net = physical_pb.pb_graph_pin_atom_net(des_pb_id, des_pb_graph_pin); - - for (t_pb_graph_pin* src_pb_graph_pin : pb_graph_pin_inputs(des_pb_graph_pin, cur_interc)) { - const PhysicalPbId& src_pb_id = physical_pb.find_pb(src_pb_graph_pin->parent_node); - input_nets.push_back(physical_pb.pb_graph_pin_atom_net(src_pb_id, src_pb_graph_pin)); - } - - for (t_pb_graph_pin* src_pb_graph_pin : pb_graph_pin_inputs(des_pb_graph_pin, cur_interc)) { - const PhysicalPbId& src_pb_id = physical_pb.find_pb(src_pb_graph_pin->parent_node); - /* If the src pb id is not valid, we bypass it */ - if ( (true == physical_pb.valid_pb_id(src_pb_id)) - && (AtomNetId::INVALID() != output_net) - && (physical_pb.pb_graph_pin_atom_net(src_pb_id, src_pb_graph_pin) == output_net)) { - break; - } - mux_input_pin_id++; - } - VTR_ASSERT (mux_input_pin_id <= fan_in); - /* Unmapped pin, use default path id */ - if (fan_in == mux_input_pin_id) { + /* Find the path id: + * - if des pb is not valid, this is an unmapped pb, we can set a default + * path_id + * - There is no net mapped to des_pb_graph_pin we use default path id + * - There is a net mapped to des_pin_graph_pin: we find the path id + */ + const PhysicalPbId& des_pb_id = + physical_pb.find_pb(des_pb_graph_pin->parent_node); + size_t mux_input_pin_id = 0; + if (true != physical_pb.valid_pb_id(des_pb_id)) { + mux_input_pin_id = DEFAULT_PATH_ID; + } else if (AtomNetId::INVALID() == physical_pb.pb_graph_pin_atom_net( + des_pb_id, des_pb_graph_pin)) { mux_input_pin_id = DEFAULT_PATH_ID; - } - } - - /* Overwrite the default path if defined in bitstream annotation */ - if ( (size_t(DEFAULT_PATH_ID) == mux_input_pin_id) - && (mux_input_pin_id != bitstream_annotation.interconnect_default_path_id(cur_interc)) ) { - mux_input_pin_id = bitstream_annotation.interconnect_default_path_id(cur_interc); - } - - /* Generate bitstream depend on both technology and structure of this MUX */ - std::vector mux_bitstream = build_mux_bitstream(circuit_lib, mux_model, mux_lib, datapath_mux_size, mux_input_pin_id); - - /* Create the block denoting the memory instances that drives this node in physical_block */ - std::string mem_block_name = generate_pb_memory_instance_name(GRID_MEM_INSTANCE_PREFIX, des_pb_graph_pin, std::string("")); - ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name); - bitstream_manager.add_child_block(parent_configurable_block, mux_mem_block); - - /* Find the module in module manager and ensure the bitstream size matches! */ - std::string mem_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string(MEMORY_MODULE_POSTFIX)); - ModuleId mux_mem_module = module_manager.find_module(mem_module_name); - VTR_ASSERT (true == module_manager.valid_module_id(mux_mem_module)); - ModulePortId mux_mem_out_port_id = module_manager.find_module_port(mux_mem_module, generate_configurable_memory_data_out_name()); - VTR_ASSERT(mux_bitstream.size() == module_manager.module_port(mux_mem_module, mux_mem_out_port_id).get_width()); - - /* Add the bistream to the bitstream manager */ - bitstream_manager.add_block_bits(mux_mem_block, mux_bitstream); - /* Record path ids, input and output nets */ - bitstream_manager.add_path_id_to_block(mux_mem_block, mux_input_pin_id); - - /* Add input nets */ - std::string input_net_ids; - - bool need_splitter = false; - for (const AtomNetId& input_net : input_nets) { - /* Add a space as a splitter*/ - if (true == need_splitter) { - input_net_ids += std::string(" "); - } - if (true == atom_ctx.nlist.valid_net_id(input_net)) { - input_net_ids += atom_ctx.nlist.net_name(input_net); } else { - input_net_ids += std::string("unmapped"); + output_net = + physical_pb.pb_graph_pin_atom_net(des_pb_id, des_pb_graph_pin); + + for (t_pb_graph_pin* src_pb_graph_pin : + pb_graph_pin_inputs(des_pb_graph_pin, cur_interc)) { + const PhysicalPbId& src_pb_id = + physical_pb.find_pb(src_pb_graph_pin->parent_node); + input_nets.push_back( + physical_pb.pb_graph_pin_atom_net(src_pb_id, src_pb_graph_pin)); + } + + for (t_pb_graph_pin* src_pb_graph_pin : + pb_graph_pin_inputs(des_pb_graph_pin, cur_interc)) { + const PhysicalPbId& src_pb_id = + physical_pb.find_pb(src_pb_graph_pin->parent_node); + /* If the src pb id is not valid, we bypass it */ + if ((true == physical_pb.valid_pb_id(src_pb_id)) && + (AtomNetId::INVALID() != output_net) && + (physical_pb.pb_graph_pin_atom_net(src_pb_id, src_pb_graph_pin) == + output_net)) { + break; + } + mux_input_pin_id++; + } + VTR_ASSERT(mux_input_pin_id <= fan_in); + /* Unmapped pin, use default path id */ + if (fan_in == mux_input_pin_id) { + mux_input_pin_id = DEFAULT_PATH_ID; + } } - need_splitter = true; - } - bitstream_manager.add_input_net_id_to_block(mux_mem_block, input_net_ids); - /* Add output nets */ - std::string output_net_ids; - if (true == atom_ctx.nlist.valid_net_id(output_net)) { - output_net_ids += atom_ctx.nlist.net_name(output_net); - } else { - output_net_ids += std::string("unmapped"); - } - bitstream_manager.add_output_net_id_to_block(mux_mem_block, output_net_ids); + /* Overwrite the default path if defined in bitstream annotation */ + if ((size_t(DEFAULT_PATH_ID) == mux_input_pin_id) && + (mux_input_pin_id != + bitstream_annotation.interconnect_default_path_id(cur_interc))) { + mux_input_pin_id = + bitstream_annotation.interconnect_default_path_id(cur_interc); + } - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid interconnection type for %s (Arch[LINE%d])!\n", - cur_interc->name, cur_interc->line_num); - exit(1); + /* Generate bitstream depend on both technology and structure of this MUX + */ + std::vector mux_bitstream = build_mux_bitstream( + circuit_lib, mux_model, mux_lib, datapath_mux_size, mux_input_pin_id); + + /* Create the block denoting the memory instances that drives this node in + * physical_block */ + std::string mem_block_name = generate_pb_memory_instance_name( + GRID_MEM_INSTANCE_PREFIX, des_pb_graph_pin, std::string("")); + ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name); + bitstream_manager.add_child_block(parent_configurable_block, + mux_mem_block); + + /* Find the module in module manager and ensure the bitstream size + * matches! */ + std::string mem_module_name = + generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, + std::string(MEMORY_MODULE_POSTFIX)); + ModuleId mux_mem_module = module_manager.find_module(mem_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(mux_mem_module)); + ModulePortId mux_mem_out_port_id = module_manager.find_module_port( + mux_mem_module, generate_configurable_memory_data_out_name()); + VTR_ASSERT(mux_bitstream.size() == + module_manager.module_port(mux_mem_module, mux_mem_out_port_id) + .get_width()); + + /* Add the bistream to the bitstream manager */ + bitstream_manager.add_block_bits(mux_mem_block, mux_bitstream); + /* Record path ids, input and output nets */ + bitstream_manager.add_path_id_to_block(mux_mem_block, mux_input_pin_id); + + /* Add input nets */ + std::string input_net_ids; + + bool need_splitter = false; + for (const AtomNetId& input_net : input_nets) { + /* Add a space as a splitter*/ + if (true == need_splitter) { + input_net_ids += std::string(" "); + } + if (true == atom_ctx.nlist.valid_net_id(input_net)) { + input_net_ids += atom_ctx.nlist.net_name(input_net); + } else { + input_net_ids += std::string("unmapped"); + } + need_splitter = true; + } + bitstream_manager.add_input_net_id_to_block(mux_mem_block, input_net_ids); + + /* Add output nets */ + std::string output_net_ids; + if (true == atom_ctx.nlist.valid_net_id(output_net)) { + output_net_ids += atom_ctx.nlist.net_name(output_net); + } else { + output_net_ids += std::string("unmapped"); + } + bitstream_manager.add_output_net_id_to_block(mux_mem_block, + output_net_ids); + + break; + } + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid interconnection type for %s (Arch[LINE%d])!\n", + cur_interc->name, cur_interc->line_num); + exit(1); } } /******************************************************************** * This function generates bitstream for the programmable routing - * multiplexers in a pb_graph node + * multiplexers in a pb_graph node *******************************************************************/ -static -void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& parent_configurable_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, - const VprBitstreamAnnotation& bitstream_annotation, - t_pb_graph_node* physical_pb_graph_node, - const PhysicalPb& physical_pb, - const e_circuit_pb_port_type& pb_port_type, - t_mode* physical_mode) { +static void build_physical_block_interc_port_bitstream( + BitstreamManager& bitstream_manager, + const ConfigBlockId& parent_configurable_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, const AtomContext& atom_ctx, + const VprDeviceAnnotation& device_annotation, + const VprBitstreamAnnotation& bitstream_annotation, + t_pb_graph_node* physical_pb_graph_node, const PhysicalPb& physical_pb, + const e_circuit_pb_port_type& pb_port_type, t_mode* physical_mode) { switch (pb_port_type) { - case CIRCUIT_PB_PORT_INPUT: - for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; ++ipin) { - build_physical_block_pin_interc_bitstream(bitstream_manager, parent_configurable_block, - module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, bitstream_annotation, - physical_pb, - &(physical_pb_graph_node->input_pins[iport][ipin]), - physical_mode); + case CIRCUIT_PB_PORT_INPUT: + for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; + ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; + ++ipin) { + build_physical_block_pin_interc_bitstream( + bitstream_manager, parent_configurable_block, module_manager, + circuit_lib, mux_lib, atom_ctx, device_annotation, + bitstream_annotation, physical_pb, + &(physical_pb_graph_node->input_pins[iport][ipin]), physical_mode); + } } - } - break; - case CIRCUIT_PB_PORT_OUTPUT: - for (int iport = 0; iport < physical_pb_graph_node->num_output_ports; ++iport) { - for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; ++ipin) { - build_physical_block_pin_interc_bitstream(bitstream_manager, parent_configurable_block, - module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, bitstream_annotation, - physical_pb, - &(physical_pb_graph_node->output_pins[iport][ipin]), - physical_mode); + break; + case CIRCUIT_PB_PORT_OUTPUT: + for (int iport = 0; iport < physical_pb_graph_node->num_output_ports; + ++iport) { + for (int ipin = 0; + ipin < physical_pb_graph_node->num_output_pins[iport]; ++ipin) { + build_physical_block_pin_interc_bitstream( + bitstream_manager, parent_configurable_block, module_manager, + circuit_lib, mux_lib, atom_ctx, device_annotation, + bitstream_annotation, physical_pb, + &(physical_pb_graph_node->output_pins[iport][ipin]), physical_mode); + } } - } - break; - case CIRCUIT_PB_PORT_CLOCK: - for (int iport = 0; iport < physical_pb_graph_node->num_clock_ports; ++iport) { - for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; ++ipin) { - build_physical_block_pin_interc_bitstream(bitstream_manager, parent_configurable_block, - module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, bitstream_annotation, - physical_pb, - &(physical_pb_graph_node->clock_pins[iport][ipin]), - physical_mode); - + break; + case CIRCUIT_PB_PORT_CLOCK: + for (int iport = 0; iport < physical_pb_graph_node->num_clock_ports; + ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; + ++ipin) { + build_physical_block_pin_interc_bitstream( + bitstream_manager, parent_configurable_block, module_manager, + circuit_lib, mux_lib, atom_ctx, device_annotation, + bitstream_annotation, physical_pb, + &(physical_pb_graph_node->clock_pins[iport][ipin]), physical_mode); + } } - } - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid pb port type!\n"); - exit(1); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid pb port type!\n"); + exit(1); } } /******************************************************************** * This function generates bitstream for the programmable routing - * multiplexers in a pb_graph node + * multiplexers in a pb_graph node *******************************************************************/ -static -void build_physical_block_interc_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& parent_configurable_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, - const VprBitstreamAnnotation& bitstream_annotation, - t_pb_graph_node* physical_pb_graph_node, - const PhysicalPb& physical_pb, - t_mode* physical_mode) { +static void build_physical_block_interc_bitstream( + BitstreamManager& bitstream_manager, + const ConfigBlockId& parent_configurable_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, const AtomContext& atom_ctx, + const VprDeviceAnnotation& device_annotation, + const VprBitstreamAnnotation& bitstream_annotation, + t_pb_graph_node* physical_pb_graph_node, const PhysicalPb& physical_pb, + t_mode* physical_mode) { /* Check if the pb_graph node is valid or not */ if (nullptr == physical_pb_graph_node) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid physical_pb_graph_node.\n"); + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid physical_pb_graph_node.\n"); exit(1); } /* We check output_pins of physical_pb_graph_node and its the input_edges - * Iterate over the interconnections between outputs of physical_pb_graph_node + * Iterate over the interconnections between outputs of physical_pb_graph_node * and outputs of child_pb_graph_node - * child_pb_graph_node.output_pins -----------------> physical_pb_graph_node.outpins + * child_pb_graph_node.output_pins -----------------> + * physical_pb_graph_node.outpins * /|\ * | * input_pins, edges, output_pins * Note: it is not applied to primitive pb_type! - */ - build_physical_block_interc_port_bitstream(bitstream_manager, parent_configurable_block, - module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, bitstream_annotation, - physical_pb_graph_node, physical_pb, - CIRCUIT_PB_PORT_OUTPUT, physical_mode); - + */ + build_physical_block_interc_port_bitstream( + bitstream_manager, parent_configurable_block, module_manager, circuit_lib, + mux_lib, atom_ctx, device_annotation, bitstream_annotation, + physical_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_OUTPUT, physical_mode); + /* We check input_pins of child_pb_graph_node and its the input_edges - * Iterate over the interconnections between inputs of physical_pb_graph_node + * Iterate over the interconnections between inputs of physical_pb_graph_node * and inputs of child_pb_graph_node - * physical_pb_graph_node.input_pins -----------------> child_pb_graph_node.input_pins + * physical_pb_graph_node.input_pins -----------------> + * child_pb_graph_node.input_pins * /|\ * | * input_pins, edges, output_pins - */ + */ for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ipb++) { - for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; jpb++) { - t_pb_graph_node* child_pb_graph_node = &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]); + for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; + jpb++) { + t_pb_graph_node* child_pb_graph_node = + &(physical_pb_graph_node + ->child_pb_graph_nodes[physical_mode->index][ipb][jpb]); /* For each child_pb_graph_node input pins*/ - build_physical_block_interc_port_bitstream(bitstream_manager, parent_configurable_block, - module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, bitstream_annotation, - child_pb_graph_node, physical_pb, - CIRCUIT_PB_PORT_INPUT, physical_mode); + build_physical_block_interc_port_bitstream( + bitstream_manager, parent_configurable_block, module_manager, + circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, + child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_INPUT, physical_mode); /* For clock pins, we should do the same work */ - build_physical_block_interc_port_bitstream(bitstream_manager, parent_configurable_block, - module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, bitstream_annotation, - child_pb_graph_node, physical_pb, - CIRCUIT_PB_PORT_CLOCK, physical_mode); + build_physical_block_interc_port_bitstream( + bitstream_manager, parent_configurable_block, module_manager, + circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, + child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_CLOCK, physical_mode); } } } @@ -410,112 +445,133 @@ void build_physical_block_interc_bitstream(BitstreamManager& bitstream_manager, * Generate bitstream for a LUT and add it to bitstream manager * This function supports both single-output and fracturable LUTs *******************************************************************/ -static -void build_lut_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& parent_configurable_block, - const VprDeviceAnnotation& device_annotation, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const PhysicalPb& physical_pb, - const PhysicalPbId& lut_pb_id, - t_pb_type* lut_pb_type) { - - /* Ensure a valid physical pritimive pb */ +static void build_lut_bitstream(BitstreamManager& bitstream_manager, + const ConfigBlockId& parent_configurable_block, + const VprDeviceAnnotation& device_annotation, + const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, + const PhysicalPb& physical_pb, + const PhysicalPbId& lut_pb_id, + t_pb_type* lut_pb_type) { + /* Ensure a valid physical pritimive pb */ if (nullptr == lut_pb_type) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid lut_pb_type!\n"); + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid lut_pb_type!\n"); exit(1); } - CircuitModelId lut_model = device_annotation.pb_type_circuit_model(lut_pb_type); + CircuitModelId lut_model = + device_annotation.pb_type_circuit_model(lut_pb_type); VTR_ASSERT(CircuitModelId::INVALID() != lut_model); VTR_ASSERT(CIRCUIT_MODEL_LUT == circuit_lib.model_type(lut_model)); - /* Find the input ports for LUT size, this is used to decode the LUT memory bits! */ - std::vector model_input_ports = find_lut_circuit_model_input_port(circuit_lib, lut_model, false); + /* Find the input ports for LUT size, this is used to decode the LUT memory + * bits! */ + std::vector model_input_ports = + find_lut_circuit_model_input_port(circuit_lib, lut_model, false); VTR_ASSERT(1 == model_input_ports.size()); size_t lut_size = circuit_lib.port_size(model_input_ports[0]); /* Find SRAM ports for truth tables and mode-selection */ - std::vector lut_regular_sram_ports = find_circuit_regular_sram_ports(circuit_lib, lut_model); - std::vector lut_mode_select_ports = find_circuit_mode_select_sram_ports(circuit_lib, lut_model); + std::vector lut_regular_sram_ports = + find_circuit_regular_sram_ports(circuit_lib, lut_model); + std::vector lut_mode_select_ports = + find_circuit_mode_select_sram_ports(circuit_lib, lut_model); /* We should always 1 regular sram port, where truth table is loaded to */ VTR_ASSERT(1 == lut_regular_sram_ports.size()); - /* We may have a port for mode select or not. This depends on if the LUT is fracturable or not */ - VTR_ASSERT( (0 == lut_mode_select_ports.size()) - || (1 == lut_mode_select_ports.size()) ); + /* We may have a port for mode select or not. This depends on if the LUT is + * fracturable or not */ + VTR_ASSERT((0 == lut_mode_select_ports.size()) || + (1 == lut_mode_select_ports.size())); std::vector lut_bitstream; - /* Generate bitstream for the LUT */ + /* Generate bitstream for the LUT */ if (false == physical_pb.valid_pb_id(lut_pb_id)) { - /* An empty pb means that this is an unused LUT, - * we give an empty truth table, which are full of default values (defined by users) + /* An empty pb means that this is an unused LUT, + * we give an empty truth table, which are full of default values (defined + * by users) */ - for (size_t i = 0; i < circuit_lib.port_size(lut_regular_sram_ports[0]); ++i) { - VTR_ASSERT( (0 == circuit_lib.port_default_value(lut_regular_sram_ports[0])) - || (1 == circuit_lib.port_default_value(lut_regular_sram_ports[0])) ); - lut_bitstream.push_back(1 == circuit_lib.port_default_value(lut_regular_sram_ports[0])); + for (size_t i = 0; i < circuit_lib.port_size(lut_regular_sram_ports[0]); + ++i) { + VTR_ASSERT( + (0 == circuit_lib.port_default_value(lut_regular_sram_ports[0])) || + (1 == circuit_lib.port_default_value(lut_regular_sram_ports[0]))); + lut_bitstream.push_back( + 1 == circuit_lib.port_default_value(lut_regular_sram_ports[0])); } - } else { + } else { VTR_ASSERT(true == physical_pb.valid_pb_id(lut_pb_id)); /* Find MUX graph correlated to the LUT */ - MuxId lut_mux_id = mux_lib.mux_graph(lut_model, (size_t)pow(2., lut_size)); + MuxId lut_mux_id = mux_lib.mux_graph(lut_model, (size_t)pow(2., lut_size)); const MuxGraph& mux_graph = mux_lib.mux_graph(lut_mux_id); /* Ensure the LUT MUX has the expected input and SRAM port sizes */ VTR_ASSERT(mux_graph.num_memory_bits() == lut_size); VTR_ASSERT(mux_graph.num_inputs() == (size_t)pow(2., lut_size)); /* Generate LUT bitstream */ - lut_bitstream = build_frac_lut_bitstream(circuit_lib, mux_graph, - device_annotation, - physical_pb.truth_tables(lut_pb_id), - circuit_lib.port_default_value(lut_regular_sram_ports[0])); + lut_bitstream = build_frac_lut_bitstream( + circuit_lib, mux_graph, device_annotation, + physical_pb.truth_tables(lut_pb_id), + circuit_lib.port_default_value(lut_regular_sram_ports[0])); /* If the physical pb contains fixed bitstream, overload here */ if (false == physical_pb.fixed_bitstream(lut_pb_id).empty()) { std::string fixed_bitstream = physical_pb.fixed_bitstream(lut_pb_id); size_t start_index = physical_pb.fixed_bitstream_offset(lut_pb_id); /* Ensure the length matches!!! */ if (lut_bitstream.size() - start_index < fixed_bitstream.size()) { - VTR_LOG_ERROR("Unmatched length of fixed bitstream %s!Expected to be less than %ld bits\n", - fixed_bitstream.c_str(), - lut_bitstream.size() - start_index); + VTR_LOG_ERROR( + "Unmatched length of fixed bitstream %s!Expected to be less than %ld " + "bits\n", + fixed_bitstream.c_str(), lut_bitstream.size() - start_index); exit(1); } /* Overload the bitstream here */ - for (size_t bit_index = 0; bit_index < lut_bitstream.size(); ++bit_index) { - VTR_ASSERT('0' == fixed_bitstream[bit_index] || '1' == fixed_bitstream[bit_index]); - lut_bitstream[bit_index + start_index] = ('1' == fixed_bitstream[bit_index]); + for (size_t bit_index = 0; bit_index < lut_bitstream.size(); + ++bit_index) { + VTR_ASSERT('0' == fixed_bitstream[bit_index] || + '1' == fixed_bitstream[bit_index]); + lut_bitstream[bit_index + start_index] = + ('1' == fixed_bitstream[bit_index]); } } } - + /* Generate bitstream for mode-select ports */ if (0 != lut_mode_select_ports.size()) { std::vector mode_select_bitstream; if (true == physical_pb.valid_pb_id(lut_pb_id)) { - mode_select_bitstream = generate_mode_select_bitstream(physical_pb.mode_bits(lut_pb_id)); + mode_select_bitstream = + generate_mode_select_bitstream(physical_pb.mode_bits(lut_pb_id)); - /* If the physical pb contains fixed mode-select bitstream, overload here */ + /* If the physical pb contains fixed mode-select bitstream, overload here + */ if (false == physical_pb.fixed_mode_select_bitstream(lut_pb_id).empty()) { - std::string fixed_mode_select_bitstream = physical_pb.fixed_mode_select_bitstream(lut_pb_id); - size_t mode_bits_start_index = physical_pb.fixed_mode_select_bitstream_offset(lut_pb_id); + std::string fixed_mode_select_bitstream = + physical_pb.fixed_mode_select_bitstream(lut_pb_id); + size_t mode_bits_start_index = + physical_pb.fixed_mode_select_bitstream_offset(lut_pb_id); /* Ensure the length matches!!! */ - if (mode_select_bitstream.size() - mode_bits_start_index < fixed_mode_select_bitstream.size()) { - VTR_LOG_ERROR("Unmatched length of fixed mode_select_bitstream %s!Expected to be less than %ld bits\n", - fixed_mode_select_bitstream.c_str(), - mode_select_bitstream.size() - mode_bits_start_index); + if (mode_select_bitstream.size() - mode_bits_start_index < + fixed_mode_select_bitstream.size()) { + VTR_LOG_ERROR( + "Unmatched length of fixed mode_select_bitstream %s!Expected to be " + "less than %ld bits\n", + fixed_mode_select_bitstream.c_str(), + mode_select_bitstream.size() - mode_bits_start_index); exit(1); } /* Overload the bitstream here */ - for (size_t bit_index = 0; bit_index < fixed_mode_select_bitstream.size(); ++bit_index) { - VTR_ASSERT('0' == fixed_mode_select_bitstream[bit_index] || '1' == fixed_mode_select_bitstream[bit_index]); - mode_select_bitstream[bit_index + mode_bits_start_index] = ('1' == fixed_mode_select_bitstream[bit_index]); + for (size_t bit_index = 0; + bit_index < fixed_mode_select_bitstream.size(); ++bit_index) { + VTR_ASSERT('0' == fixed_mode_select_bitstream[bit_index] || + '1' == fixed_mode_select_bitstream[bit_index]); + mode_select_bitstream[bit_index + mode_bits_start_index] = + ('1' == fixed_mode_select_bitstream[bit_index]); } - } } else { /* get default mode_bits */ - mode_select_bitstream = generate_mode_select_bitstream(device_annotation.pb_type_mode_bits(lut_pb_type)); + mode_select_bitstream = generate_mode_select_bitstream( + device_annotation.pb_type_mode_bits(lut_pb_type)); } /* Conjunct the mode-select bitstream to the lut bitstream */ @@ -525,15 +581,21 @@ void build_lut_bitstream(BitstreamManager& bitstream_manager, } /* Ensure the length of bitstream matches the side of memory circuits */ - std::vector sram_models = find_circuit_sram_models(circuit_lib, lut_model); + std::vector sram_models = + find_circuit_sram_models(circuit_lib, lut_model); VTR_ASSERT(1 == sram_models.size()); - std::string mem_block_name = generate_memory_module_name(circuit_lib, lut_model, sram_models[0], std::string(MEMORY_MODULE_POSTFIX)); + std::string mem_block_name = generate_memory_module_name( + circuit_lib, lut_model, sram_models[0], std::string(MEMORY_MODULE_POSTFIX)); ModuleId mem_module = module_manager.find_module(mem_block_name); - VTR_ASSERT (true == module_manager.valid_module_id(mem_module)); - ModulePortId mem_out_port_id = module_manager.find_module_port(mem_module, generate_configurable_memory_data_out_name()); - VTR_ASSERT(lut_bitstream.size() == module_manager.module_port(mem_module, mem_out_port_id).get_width()); + VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); + ModulePortId mem_out_port_id = module_manager.find_module_port( + mem_module, generate_configurable_memory_data_out_name()); + VTR_ASSERT( + lut_bitstream.size() == + module_manager.module_port(mem_module, mem_out_port_id).get_width()); - /* Create a block for the bitstream which corresponds to the memory module associated to the LUT */ + /* Create a block for the bitstream which corresponds to the memory module + * associated to the LUT */ ConfigBlockId mem_block = bitstream_manager.add_block(mem_block_name); bitstream_manager.add_child_block(parent_configurable_block, mem_block); @@ -542,30 +604,25 @@ void build_lut_bitstream(BitstreamManager& bitstream_manager, } /******************************************************************** - * This function generates bitstream for a physical block, which is - * a child block of a grid + * This function generates bitstream for a physical block, which is + * a child block of a grid * This function will follow a recursive way in generating bitstreams * It will follow the same sequence in visiting all the sub blocks * in a physical as we did during module generation * - * Note: if you want to bind your bitstream with a FPGA fabric generated by FPGA-X2P - * Please follow the same sequence in visiting pb_graph nodes!!! - * For more details, you may refer to function rec_build_physical_block_modules() + * Note: if you want to bind your bitstream with a FPGA fabric generated by + *FPGA-X2P Please follow the same sequence in visiting pb_graph nodes!!! For + *more details, you may refer to function rec_build_physical_block_modules() *******************************************************************/ -static -void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& parent_configurable_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, - const VprBitstreamAnnotation& bitstream_annotation, - const e_side& border_side, - const PhysicalPb& physical_pb, - const PhysicalPbId& pb_id, - t_pb_graph_node* physical_pb_graph_node, - const size_t& pb_graph_node_index) { +static void rec_build_physical_block_bitstream( + BitstreamManager& bitstream_manager, + const ConfigBlockId& parent_configurable_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, const AtomContext& atom_ctx, + const VprDeviceAnnotation& device_annotation, + const VprBitstreamAnnotation& bitstream_annotation, const e_side& border_side, + const PhysicalPb& physical_pb, const PhysicalPbId& pb_id, + t_pb_graph_node* physical_pb_graph_node, const size_t& pb_graph_node_index) { /* Get the physical pb_type that is linked to the pb_graph node */ t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; @@ -573,86 +630,93 @@ void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager, t_mode* physical_mode = device_annotation.physical_mode(physical_pb_type); /* Early exit if this parent module has no configurable child modules */ - std::string pb_module_name = generate_physical_block_module_name(physical_pb_type); + std::string pb_module_name = + generate_physical_block_module_name(physical_pb_type); ModuleId pb_module = module_manager.find_module(pb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); - + /* Skip module with no configurable children */ if (0 == module_manager.configurable_children(pb_module).size()) { return; } - /* Create a block for the physical block under the grid block in bitstream manager */ - std::string pb_block_name = generate_physical_block_instance_name(physical_pb_type, pb_graph_node_index); - ConfigBlockId pb_configurable_block = bitstream_manager.add_block(pb_block_name); - bitstream_manager.add_child_block(parent_configurable_block, pb_configurable_block); + /* Create a block for the physical block under the grid block in bitstream + * manager */ + std::string pb_block_name = generate_physical_block_instance_name( + physical_pb_type, pb_graph_node_index); + ConfigBlockId pb_configurable_block = + bitstream_manager.add_block(pb_block_name); + bitstream_manager.add_child_block(parent_configurable_block, + pb_configurable_block); /* Reserve child blocks for new created block */ - bitstream_manager.reserve_child_blocks(parent_configurable_block, - count_module_manager_module_configurable_children(module_manager, pb_module)); + bitstream_manager.reserve_child_blocks( + parent_configurable_block, + count_module_manager_module_configurable_children(module_manager, + pb_module)); /* Recursively finish all the child pb_types*/ - if (false == is_primitive_pb_type(physical_pb_type)) { + if (false == is_primitive_pb_type(physical_pb_type)) { for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) { - for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; ++jpb) { + for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; + ++jpb) { PhysicalPbId child_pb = PhysicalPbId::INVALID(); - /* Find the child pb that is mapped, and the mapping info is not stored in the physical mode ! */ + /* Find the child pb that is mapped, and the mapping info is not stored + * in the physical mode ! */ if (true == physical_pb.valid_pb_id(pb_id)) { - child_pb = physical_pb.child(pb_id, &(physical_mode->pb_type_children[ipb]), jpb); + child_pb = physical_pb.child( + pb_id, &(physical_mode->pb_type_children[ipb]), jpb); VTR_ASSERT(true == physical_pb.valid_pb_id(child_pb)); } /* Go recursively */ - rec_build_physical_block_bitstream(bitstream_manager, pb_configurable_block, - module_manager, circuit_lib, mux_lib, - atom_ctx, - device_annotation, bitstream_annotation, - border_side, - physical_pb, child_pb, - &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), - jpb); + rec_build_physical_block_bitstream( + bitstream_manager, pb_configurable_block, module_manager, circuit_lib, + mux_lib, atom_ctx, device_annotation, bitstream_annotation, + border_side, physical_pb, child_pb, + &(physical_pb_graph_node + ->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), + jpb); } } } /* Check if this has defined a circuit_model*/ - if (true == is_primitive_pb_type(physical_pb_type)) { - CircuitModelId primitive_circuit_model = device_annotation.pb_type_circuit_model(physical_pb_type); + if (true == is_primitive_pb_type(physical_pb_type)) { + CircuitModelId primitive_circuit_model = + device_annotation.pb_type_circuit_model(physical_pb_type); VTR_ASSERT(CircuitModelId::INVALID() != primitive_circuit_model); switch (circuit_lib.model_type(primitive_circuit_model)) { - case CIRCUIT_MODEL_LUT: - /* Special case for LUT !!! - * Mapped logical block information is stored in child_pbs of this pb!!! - */ - build_lut_bitstream(bitstream_manager, pb_configurable_block, - device_annotation, - module_manager, circuit_lib, mux_lib, - physical_pb, pb_id, physical_pb_type); - break; - case CIRCUIT_MODEL_FF: - case CIRCUIT_MODEL_HARDLOGIC: - case CIRCUIT_MODEL_IOPAD: - /* For other types of blocks, we can apply a generic therapy */ - build_primitive_bitstream(bitstream_manager, pb_configurable_block, - module_manager, circuit_lib, device_annotation, - physical_pb, pb_id, physical_pb_type); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Unknown circuit model type of pb_type '%s'!\n", - physical_pb_type->name); - exit(1); + case CIRCUIT_MODEL_LUT: + /* Special case for LUT !!! + * Mapped logical block information is stored in child_pbs of this pb!!! + */ + build_lut_bitstream(bitstream_manager, pb_configurable_block, + device_annotation, module_manager, circuit_lib, + mux_lib, physical_pb, pb_id, physical_pb_type); + break; + case CIRCUIT_MODEL_FF: + case CIRCUIT_MODEL_HARDLOGIC: + case CIRCUIT_MODEL_IOPAD: + /* For other types of blocks, we can apply a generic therapy */ + build_primitive_bitstream( + bitstream_manager, pb_configurable_block, module_manager, circuit_lib, + device_annotation, physical_pb, pb_id, physical_pb_type); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Unknown circuit model type of pb_type '%s'!\n", + physical_pb_type->name); + exit(1); } /* Finish for primitive node, return */ return; } /* Generate the bitstream for the interconnection in this physical block */ - build_physical_block_interc_bitstream(bitstream_manager, pb_configurable_block, - module_manager, circuit_lib, mux_lib, - atom_ctx, - device_annotation, bitstream_annotation, - physical_pb_graph_node, physical_pb, - physical_mode); + build_physical_block_interc_bitstream( + bitstream_manager, pb_configurable_block, module_manager, circuit_lib, + mux_lib, atom_ctx, device_annotation, bitstream_annotation, + physical_pb_graph_node, physical_pb, physical_mode); } /******************************************************************** @@ -661,72 +725,75 @@ void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager, * Note that each grid may contain a number of physical blocks, * this function will iterate over them *******************************************************************/ -static -void build_physical_block_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& top_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, - const VprClusteringAnnotation& cluster_annotation, - const VprPlacementAnnotation& place_annotation, - const VprBitstreamAnnotation& bitstream_annotation, - const DeviceGrid& grids, - const vtr::Point& grid_coord, - const e_side& border_side) { +static void build_physical_block_bitstream( + BitstreamManager& bitstream_manager, const ConfigBlockId& top_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, const AtomContext& atom_ctx, + const VprDeviceAnnotation& device_annotation, + const VprClusteringAnnotation& cluster_annotation, + const VprPlacementAnnotation& place_annotation, + const VprBitstreamAnnotation& bitstream_annotation, const DeviceGrid& grids, + const vtr::Point& grid_coord, const e_side& border_side) { /* Create a block for the grid in bitstream manager */ - t_physical_tile_type_ptr grid_type = grids[grid_coord.x()][grid_coord.y()].type; + t_physical_tile_type_ptr grid_type = + grids[grid_coord.x()][grid_coord.y()].type; std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); /* Early exit if this parent module has no configurable child modules */ - std::string grid_module_name = generate_grid_block_module_name(grid_module_name_prefix, std::string(grid_type->name), - is_io_type(grid_type), border_side); + std::string grid_module_name = generate_grid_block_module_name( + grid_module_name_prefix, std::string(grid_type->name), + is_io_type(grid_type), border_side); ModuleId grid_module = module_manager.find_module(grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); - + /* Skip module with no configurable children */ if (0 == module_manager.configurable_children(grid_module).size()) { return; } - std::string grid_block_name = generate_grid_block_instance_name(grid_module_name_prefix, std::string(grid_type->name), - is_io_type(grid_type), border_side, grid_coord); - ConfigBlockId grid_configurable_block = bitstream_manager.add_block(grid_block_name); + std::string grid_block_name = generate_grid_block_instance_name( + grid_module_name_prefix, std::string(grid_type->name), + is_io_type(grid_type), border_side, grid_coord); + ConfigBlockId grid_configurable_block = + bitstream_manager.add_block(grid_block_name); bitstream_manager.add_child_block(top_block, grid_configurable_block); /* Reserve child blocks for new created block */ - bitstream_manager.reserve_child_blocks(grid_configurable_block, - count_module_manager_module_configurable_children(module_manager, grid_module)); + bitstream_manager.reserve_child_blocks( + grid_configurable_block, count_module_manager_module_configurable_children( + module_manager, grid_module)); /* Iterate over the capacity of the grid * Now each physical tile may have a number of logical blocks * OpenFPGA only considers the physical implementation of the tiles. - * So, we do not allow multiple equivalent sites to be defined - * under a physical tile type. - * If you need different equivalent sites, you can always define + * So, we do not allow multiple equivalent sites to be defined + * under a physical tile type. + * If you need different equivalent sites, you can always define * it as a mode under a */ for (size_t z = 0; z < place_annotation.grid_blocks(grid_coord).size(); ++z) { - int sub_tile_index = device_annotation.physical_tile_z_to_subtile_index(grid_type, z); - VTR_ASSERT(1 == grid_type->sub_tiles[sub_tile_index].equivalent_sites.size()); - for (t_logical_block_type_ptr lb_type : grid_type->sub_tiles[sub_tile_index].equivalent_sites) { + int sub_tile_index = + device_annotation.physical_tile_z_to_subtile_index(grid_type, z); + VTR_ASSERT(1 == + grid_type->sub_tiles[sub_tile_index].equivalent_sites.size()); + for (t_logical_block_type_ptr lb_type : + grid_type->sub_tiles[sub_tile_index].equivalent_sites) { /* Bypass empty pb_graph */ if (nullptr == lb_type->pb_graph_head) { continue; } - if (ClusterBlockId::INVALID() == place_annotation.grid_blocks(grid_coord)[z]) { + if (ClusterBlockId::INVALID() == + place_annotation.grid_blocks(grid_coord)[z]) { /* Recursively traverse the pb_graph and generate bitstream */ - rec_build_physical_block_bitstream(bitstream_manager, grid_configurable_block, - module_manager, circuit_lib, mux_lib, - atom_ctx, - device_annotation, bitstream_annotation, - border_side, - PhysicalPb(), PhysicalPbId::INVALID(), - lb_type->pb_graph_head, z); + rec_build_physical_block_bitstream( + bitstream_manager, grid_configurable_block, module_manager, + circuit_lib, mux_lib, atom_ctx, device_annotation, + bitstream_annotation, border_side, PhysicalPb(), + PhysicalPbId::INVALID(), lb_type->pb_graph_head, z); } else { - const PhysicalPb& phy_pb = cluster_annotation.physical_pb(place_annotation.grid_blocks(grid_coord)[z]); + const PhysicalPb& phy_pb = cluster_annotation.physical_pb( + place_annotation.grid_blocks(grid_coord)[z]); /* Get the top-level node of the pb_graph */ t_pb_graph_node* pb_graph_head = lb_type->pb_graph_head; @@ -734,37 +801,30 @@ void build_physical_block_bitstream(BitstreamManager& bitstream_manager, const PhysicalPbId& top_pb_id = phy_pb.find_pb(pb_graph_head); /* Recursively traverse the pb_graph and generate bitstream */ - rec_build_physical_block_bitstream(bitstream_manager, grid_configurable_block, - module_manager, circuit_lib, mux_lib, - atom_ctx, - device_annotation, bitstream_annotation, - border_side, - phy_pb, top_pb_id, pb_graph_head, z); + rec_build_physical_block_bitstream( + bitstream_manager, grid_configurable_block, module_manager, + circuit_lib, mux_lib, atom_ctx, device_annotation, + bitstream_annotation, border_side, phy_pb, top_pb_id, pb_graph_head, + z); } } - } + } } - /******************************************************************** - * Top-level function of this file: - * Generate bitstreams for all the grids, including + * Top-level function of this file: + * Generate bitstreams for all the grids, including * 1. core grids that sit in the center of the fabric * 2. side grids (I/O grids) that sit in the borders for the fabric *******************************************************************/ -void build_grid_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& top_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const DeviceGrid& grids, - const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, - const VprClusteringAnnotation& cluster_annotation, - const VprPlacementAnnotation& place_annotation, - const VprBitstreamAnnotation& bitstream_annotation, - const bool& verbose) { - +void build_grid_bitstream( + BitstreamManager& bitstream_manager, const ConfigBlockId& top_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, const DeviceGrid& grids, + const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, + const VprClusteringAnnotation& cluster_annotation, + const VprPlacementAnnotation& place_annotation, + const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose) { VTR_LOGV(verbose, "Generating bitstream for core grids..."); /* Generate bitstream for the core logic block one by one */ @@ -773,20 +833,18 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager, /* Bypass EMPTY grid */ if (true == is_empty_type(grids[ix][iy].type)) { continue; - } + } /* Skip width > 1 or height > 1 tiles (mostly heterogeneous blocks) */ - if ( (0 < grids[ix][iy].width_offset) - || (0 < grids[ix][iy].height_offset) ) { + if ((0 < grids[ix][iy].width_offset) || + (0 < grids[ix][iy].height_offset)) { continue; } /* Add a grid module to top_module*/ vtr::Point grid_coord(ix, iy); - build_physical_block_bitstream(bitstream_manager, top_block, module_manager, - circuit_lib, mux_lib, - atom_ctx, - device_annotation, cluster_annotation, - place_annotation, bitstream_annotation, - grids, grid_coord, NUM_SIDES); + build_physical_block_bitstream( + bitstream_manager, top_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, cluster_annotation, place_annotation, + bitstream_annotation, grids, grid_coord, NUM_SIDES); } } VTR_LOGV(verbose, "Done\n"); @@ -794,26 +852,26 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager, VTR_LOGV(verbose, "Generating bitstream for I/O grids..."); /* Create the coordinate range for each side of FPGA fabric */ - std::map>> io_coordinates = generate_perimeter_grid_coordinates( grids); + std::map>> io_coordinates = + generate_perimeter_grid_coordinates(grids); /* Add instances of I/O grids to top_module */ 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 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) ) { + if (true == + is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) { continue; } - build_physical_block_bitstream(bitstream_manager, top_block, module_manager, - circuit_lib, mux_lib, - atom_ctx, - device_annotation, cluster_annotation, - place_annotation, bitstream_annotation, - grids, io_coordinate, io_side); + /* Skip 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; + } + build_physical_block_bitstream( + bitstream_manager, top_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, cluster_annotation, place_annotation, + bitstream_annotation, grids, io_coordinate, io_side); } } VTR_LOGV(verbose, "Done\n"); diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.h b/openfpga/src/fpga_bitstream/build_grid_bitstream.h index 9d2c3d010..36597918a 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.h @@ -5,16 +5,17 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "vpr_context.h" -#include "device_grid.h" + #include "bitstream_manager.h" -#include "module_manager.h" #include "circuit_library.h" +#include "device_grid.h" +#include "module_manager.h" #include "mux_library.h" -#include "vpr_device_annotation.h" -#include "vpr_clustering_annotation.h" -#include "vpr_placement_annotation.h" #include "vpr_bitstream_annotation.h" +#include "vpr_clustering_annotation.h" +#include "vpr_context.h" +#include "vpr_device_annotation.h" +#include "vpr_placement_annotation.h" /******************************************************************** * Function declaration @@ -23,18 +24,14 @@ /* begin namespace openfpga */ namespace openfpga { -void build_grid_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& top_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const DeviceGrid& grids, - const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, - const VprClusteringAnnotation& cluster_annotation, - const VprPlacementAnnotation& place_annotation, - const VprBitstreamAnnotation& bitstream_annotation, - const bool& verbose); +void build_grid_bitstream( + BitstreamManager& bitstream_manager, const ConfigBlockId& top_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, const DeviceGrid& grids, + const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, + const VprClusteringAnnotation& cluster_annotation, + const VprPlacementAnnotation& place_annotation, + const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_io_mapping_info.cpp b/openfpga/src/fpga_bitstream/build_io_mapping_info.cpp index 6b68d85b3..77c7b3e8a 100644 --- a/openfpga/src/fpga_bitstream/build_io_mapping_info.cpp +++ b/openfpga/src/fpga_bitstream/build_io_mapping_info.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * This file includes functions that build io mapping information + * This file includes functions that build io mapping information *******************************************************************/ #include #include @@ -11,42 +11,44 @@ #include "vtr_time.h" /* Headers from archopenfpga library */ -#include "openfpga_naming.h" - -#include "module_manager_utils.h" #include "build_io_mapping_info.h" +#include "module_manager_utils.h" +#include "openfpga_naming.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * This function + * This function * - builds the net-to-I/O mapping * - identifies each I/O directionality * - return a database containing the above information * - * TODO: This function duplicates codes from - * function: print_verilog_testbench_connect_fpga_ios() in + * TODO: This function duplicates codes from + * function: print_verilog_testbench_connect_fpga_ios() in * source file: verilog_testbench_utils.cpp - * Should consider how to merge the codes and share same builder function + * Should consider how to merge the codes and share same builder function *******************************************************************/ -IoMap build_fpga_io_mapping_info(const ModuleManager& module_manager, - const ModuleId& top_module, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const IoLocationMap& io_location_map, - const VprNetlistAnnotation& netlist_annotation, - const std::string& io_input_port_name_postfix, - const std::string& io_output_port_name_postfix, - const std::vector& output_port_prefix_to_remove) { +IoMap build_fpga_io_mapping_info( + const ModuleManager& module_manager, const ModuleId& top_module, + const AtomContext& atom_ctx, const PlacementContext& place_ctx, + const IoLocationMap& io_location_map, + const VprNetlistAnnotation& netlist_annotation, + const std::string& io_input_port_name_postfix, + const std::string& io_output_port_name_postfix, + const std::vector& output_port_prefix_to_remove) { IoMap io_map; /* Only mappable i/o ports can be considered */ std::vector module_io_ports; - for (const ModuleManager::e_module_port_type& module_io_port_type : MODULE_IO_PORT_TYPES) { - for (const ModulePortId& gpio_port_id : module_manager.module_port_ids_by_type(top_module, module_io_port_type)) { + for (const ModuleManager::e_module_port_type& module_io_port_type : + MODULE_IO_PORT_TYPES) { + for (const ModulePortId& gpio_port_id : + module_manager.module_port_ids_by_type(top_module, + module_io_port_type)) { /* Only care mappable I/O */ - if (false == module_manager.port_is_mappable_io(top_module, gpio_port_id)) { + if (false == + module_manager.port_is_mappable_io(top_module, gpio_port_id)) { continue; } module_io_ports.push_back(gpio_port_id); @@ -54,35 +56,44 @@ IoMap build_fpga_io_mapping_info(const ModuleManager& module_manager, } /* Type mapping between VPR block and Module port */ - std::map atom_block_type_to_module_port_type; - atom_block_type_to_module_port_type[AtomBlockType::INPAD] = ModuleManager::MODULE_GPIN_PORT; - atom_block_type_to_module_port_type[AtomBlockType::OUTPAD] = ModuleManager::MODULE_GPOUT_PORT; + std::map + atom_block_type_to_module_port_type; + atom_block_type_to_module_port_type[AtomBlockType::INPAD] = + ModuleManager::MODULE_GPIN_PORT; + atom_block_type_to_module_port_type[AtomBlockType::OUTPAD] = + ModuleManager::MODULE_GPOUT_PORT; /* Type mapping between VPR block and io mapping direction */ - std::map atom_block_type_to_io_map_direction; - atom_block_type_to_io_map_direction[AtomBlockType::INPAD] = IoMap::IO_MAP_DIR_INPUT; - atom_block_type_to_io_map_direction[AtomBlockType::OUTPAD] = IoMap::IO_MAP_DIR_OUTPUT; + std::map + atom_block_type_to_io_map_direction; + atom_block_type_to_io_map_direction[AtomBlockType::INPAD] = + IoMap::IO_MAP_DIR_INPUT; + atom_block_type_to_io_map_direction[AtomBlockType::OUTPAD] = + IoMap::IO_MAP_DIR_OUTPUT; for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) { /* Bypass non-I/O atom blocks ! */ - if ( (AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) - && (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)) ) { + if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) && + (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk))) { continue; } - + /* If there is a GPIO port, use it directly * Otherwise, should find a GPIN for INPAD * or should find a GPOUT for OUTPAD - */ - std::pair mapped_module_io_info = std::make_pair(ModulePortId::INVALID(), -1); + */ + std::pair mapped_module_io_info = + std::make_pair(ModulePortId::INVALID(), -1); for (const ModulePortId& module_io_port_id : module_io_ports) { - const BasicPort& module_io_port = module_manager.module_port(top_module, module_io_port_id); + const BasicPort& module_io_port = + module_manager.module_port(top_module, module_io_port_id); /* Find the index of the mapped GPIO in top-level FPGA fabric */ - size_t temp_io_index = io_location_map.io_index(place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.x, - place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.y, - place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.sub_tile, - module_io_port.get_name()); + size_t temp_io_index = io_location_map.io_index( + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.x, + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.y, + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.sub_tile, + module_io_port.get_name()); /* Bypass invalid index (not mapped to this GPIO port) */ if (size_t(-1) == temp_io_index) { @@ -90,43 +101,53 @@ IoMap build_fpga_io_mapping_info(const ModuleManager& module_manager, } /* If the port is an GPIO port, just use it */ - if (ModuleManager::MODULE_GPIO_PORT == module_manager.port_type(top_module, module_io_port_id)) { - mapped_module_io_info = std::make_pair(module_io_port_id, temp_io_index); + if (ModuleManager::MODULE_GPIO_PORT == + module_manager.port_type(top_module, module_io_port_id)) { + mapped_module_io_info = + std::make_pair(module_io_port_id, temp_io_index); break; } /* If this is an INPAD, we can use an GPIN port (if available) */ - if (atom_block_type_to_module_port_type[atom_ctx.nlist.block_type(atom_blk)] == module_manager.port_type(top_module, module_io_port_id)) { - mapped_module_io_info = std::make_pair(module_io_port_id, temp_io_index); + if (atom_block_type_to_module_port_type[atom_ctx.nlist.block_type( + atom_blk)] == + module_manager.port_type(top_module, module_io_port_id)) { + mapped_module_io_info = + std::make_pair(module_io_port_id, temp_io_index); break; } } /* We must find a valid one */ - VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, mapped_module_io_info.first)); + VTR_ASSERT(true == module_manager.valid_module_port_id( + top_module, mapped_module_io_info.first)); VTR_ASSERT(size_t(-1) != mapped_module_io_info.second); /* Ensure that IO index is in range */ - BasicPort module_mapped_io_port = module_manager.module_port(top_module, mapped_module_io_info.first); + BasicPort module_mapped_io_port = + module_manager.module_port(top_module, mapped_module_io_info.first); size_t io_index = mapped_module_io_info.second; - /* Set the port pin index */ + /* Set the port pin index */ VTR_ASSERT(io_index < module_mapped_io_port.get_width()); module_mapped_io_port.set_width(io_index, io_index); - /* The block may be renamed as it contains special characters which violate Verilog syntax */ + /* The block may be renamed as it contains special characters which violate + * Verilog syntax */ std::string block_name = atom_ctx.nlist.block_name(atom_blk); if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); - } + } - /* Create the port for benchmark I/O, due to BLIF benchmark, each I/O always has a size of 1 - * In addition, the input and output ports may have different postfix in naming - * due to verification context! Here, we give full customization on naming + /* Create the port for benchmark I/O, due to BLIF benchmark, each I/O always + * has a size of 1 In addition, the input and output ports may have + * different postfix in naming due to verification context! Here, we give + * full customization on naming */ BasicPort benchmark_io_port; if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) { - benchmark_io_port.set_name(std::string(block_name + io_input_port_name_postfix)); + benchmark_io_port.set_name( + std::string(block_name + io_input_port_name_postfix)); benchmark_io_port.set_width(1); } else { VTR_ASSERT(AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)); @@ -141,15 +162,16 @@ IoMap build_fpga_io_mapping_info(const ModuleManager& module_manager, } } - benchmark_io_port.set_name(std::string(output_block_name + io_output_port_name_postfix)); + benchmark_io_port.set_name( + std::string(output_block_name + io_output_port_name_postfix)); benchmark_io_port.set_width(1); } - io_map.create_io_mapping(module_mapped_io_port, - benchmark_io_port, - atom_block_type_to_io_map_direction[atom_ctx.nlist.block_type(atom_blk)]); + io_map.create_io_mapping( + module_mapped_io_port, benchmark_io_port, + atom_block_type_to_io_map_direction[atom_ctx.nlist.block_type(atom_blk)]); } - + return io_map; } diff --git a/openfpga/src/fpga_bitstream/build_io_mapping_info.h b/openfpga/src/fpga_bitstream/build_io_mapping_info.h index 01f4b1d61..b215e22ac 100644 --- a/openfpga/src/fpga_bitstream/build_io_mapping_info.h +++ b/openfpga/src/fpga_bitstream/build_io_mapping_info.h @@ -6,10 +6,11 @@ *******************************************************************/ #include #include -#include "module_manager.h" -#include "vpr_context.h" + #include "io_location_map.h" #include "io_map.h" +#include "module_manager.h" +#include "vpr_context.h" #include "vpr_netlist_annotation.h" /******************************************************************** @@ -19,15 +20,14 @@ /* begin namespace openfpga */ namespace openfpga { -IoMap build_fpga_io_mapping_info(const ModuleManager& module_manager, - const ModuleId& top_module, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const IoLocationMap& io_location_map, - const VprNetlistAnnotation& netlist_annotation, - const std::string& io_input_port_name_postfix, - const std::string& io_output_port_name_postfix, - const std::vector& output_port_prefix_to_remove); +IoMap build_fpga_io_mapping_info( + const ModuleManager& module_manager, const ModuleId& top_module, + const AtomContext& atom_ctx, const PlacementContext& place_ctx, + const IoLocationMap& io_location_map, + const VprNetlistAnnotation& netlist_annotation, + const std::string& io_input_port_name_postfix, + const std::string& io_output_port_name_postfix, + const std::vector& output_port_prefix_to_remove); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_mux_bitstream.cpp b/openfpga/src/fpga_bitstream/build_mux_bitstream.cpp index 5de0e3d0e..fca568ea5 100644 --- a/openfpga/src/fpga_bitstream/build_mux_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_mux_bitstream.cpp @@ -3,18 +3,16 @@ * which are based on different technology *******************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_vector.h" /* Headers from openfpgautil library */ -#include "openfpga_decode.h" - -#include "mux_utils.h" -#include "decoder_library_utils.h" - -#include "mux_bitstream_constants.h" #include "build_mux_bitstream.h" +#include "decoder_library_utils.h" +#include "mux_bitstream_constants.h" +#include "mux_utils.h" +#include "openfpga_decode.h" /* begin namespace openfpga */ namespace openfpga { @@ -22,11 +20,11 @@ namespace openfpga { /******************************************************************** * Find the default path id of a MUX * This is applied when the path id specified is DEFAULT_PATH_ID, - * which is not correlated to the MUX implementation + * which is not correlated to the MUX implementation * This function is binding the default path id to the implemented structure - * 1. If the MUX has a constant input, the default path id will be + * 1. If the MUX has a constant input, the default path id will be * directed to the last input of the MUX, which is the constant input - * 2. If the MUX does not have a constant input, the default path id + * 2. If the MUX does not have a constant input, the default path id * will the first input of the MUX. * * Restriction: @@ -39,17 +37,19 @@ size_t find_mux_default_path_id(const CircuitLibrary& circuit_lib, size_t default_path_id; if (true == circuit_lib.mux_add_const_input(mux_model)) { - default_path_id = mux_size - 1; /* When there is a constant input, use the last path */ + default_path_id = + mux_size - 1; /* When there is a constant input, use the last path */ } else { - default_path_id = DEFAULT_MUX_PATH_ID; /* When there is no constant input, use the default one */ + default_path_id = DEFAULT_MUX_PATH_ID; /* When there is no constant input, + use the default one */ } - return default_path_id; + return default_path_id; } /******************************************************************** * This function generates bitstream for a CMOS routing multiplexer - * Thanks to MuxGraph object has already describe the internal multiplexing + * Thanks to MuxGraph object has already describe the internal multiplexing * structure, bitstream generation is simply done by routing the signal * to from a given input to the output * All the memory bits can be generated by an API of MuxGraph @@ -57,17 +57,15 @@ size_t find_mux_default_path_id(const CircuitLibrary& circuit_lib, * To be generic, this function only returns a vector bit values * without touching an bitstream-relate data structure *******************************************************************/ -static -std::vector build_cmos_mux_bitstream(const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const MuxLibrary& mux_lib, - const size_t& mux_size, - const int& path_id) { - /* Note that the size of implemented mux could be different than the mux size we see here, - * due to the constant inputs - * We will find the input size of implemented MUX and fetch the graph-based representation in MUX library +static std::vector build_cmos_mux_bitstream( + const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, + const MuxLibrary& mux_lib, const size_t& mux_size, const int& path_id) { + /* Note that the size of implemented mux could be different than the mux size + * we see here, due to the constant inputs We will find the input size of + * implemented MUX and fetch the graph-based representation in MUX library */ - size_t implemented_mux_size = find_mux_implementation_num_inputs(circuit_lib, mux_model, mux_size); + size_t implemented_mux_size = + 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); const MuxGraph mux_graph = mux_lib.mux_graph(mux_graph_id); @@ -76,9 +74,10 @@ std::vector build_cmos_mux_bitstream(const CircuitLibrary& circuit_lib, /* Find the path_id related to the implementation */ if (DEFAULT_PATH_ID == path_id) { - datapath_id = find_mux_default_path_id(circuit_lib, mux_model, implemented_mux_size); - } else { - VTR_ASSERT( datapath_id < mux_size); + datapath_id = + find_mux_default_path_id(circuit_lib, mux_model, implemented_mux_size); + } else { + VTR_ASSERT(datapath_id < mux_size); } /* Path id should makes sense */ VTR_ASSERT(datapath_id < mux_graph.inputs().size()); @@ -86,7 +85,8 @@ std::vector build_cmos_mux_bitstream(const CircuitLibrary& circuit_lib, VTR_ASSERT(1 == mux_graph.outputs().size()); /* Generate the memory bits */ - vtr::vector raw_bitstream = mux_graph.decode_memory_bits(MuxInputId(datapath_id), mux_graph.output_id(mux_graph.outputs()[0])); + vtr::vector raw_bitstream = mux_graph.decode_memory_bits( + MuxInputId(datapath_id), mux_graph.output_id(mux_graph.outputs()[0])); std::vector mux_bitstream; for (const bool& bit : raw_bitstream) { @@ -102,50 +102,58 @@ std::vector build_cmos_mux_bitstream(const CircuitLibrary& circuit_lib, mux_bitstream.clear(); /* Encode the memory bits level by level, - * One local encoder is used for each level of multiplexers + * One local encoder is used for each level of multiplexers */ for (const size_t& level : mux_graph.levels()) { - /* The encoder will convert the path_id to a binary number - * For example: when path_id=3 (use the 4th input), using a 2-input encoder + /* The encoder will convert the path_id to a binary number + * For example: when path_id=3 (use the 4th input), using a 2-input encoder * the sram_bits will be the 2-digit binary number of 3: 10 */ std::vector encoder_data; - /* Exception: there is only 1 memory at this level, bitstream will not be changed!!! */ + /* Exception: there is only 1 memory at this level, bitstream will not be + * changed!!! */ if (1 == mux_graph.memories_at_level(level).size()) { - mux_bitstream.push_back(raw_bitstream[mux_graph.memories_at_level(level)[0]]); + mux_bitstream.push_back( + raw_bitstream[mux_graph.memories_at_level(level)[0]]); continue; } /* Otherwise: we follow a regular recipe */ - for (size_t mem_index = 0; mem_index < mux_graph.memories_at_level(level).size(); ++mem_index) { + for (size_t mem_index = 0; + mem_index < mux_graph.memories_at_level(level).size(); ++mem_index) { /* Conversion rule: true = 1, false = 0 */ - if (true == raw_bitstream[mux_graph.memories_at_level(level)[mem_index]]) { + if (true == + raw_bitstream[mux_graph.memories_at_level(level)[mem_index]]) { encoder_data.push_back(mem_index); - } + } } /* There should be at most one '1' */ - VTR_ASSERT( (0 == encoder_data.size()) || (1 == encoder_data.size())); + VTR_ASSERT((0 == encoder_data.size()) || (1 == encoder_data.size())); /* Convert to encoded bits */ std::vector encoder_addr; - if (0 == encoder_data.size()) { - encoder_addr = itobin_vec(0, find_mux_local_decoder_addr_size(mux_graph.memories_at_level(level).size())); + if (0 == encoder_data.size()) { + encoder_addr = + itobin_vec(0, find_mux_local_decoder_addr_size( + mux_graph.memories_at_level(level).size())); } else { VTR_ASSERT(1 == encoder_data.size()); - encoder_addr = itobin_vec(encoder_data[0], find_mux_local_decoder_addr_size(mux_graph.memories_at_level(level).size())); + encoder_addr = itobin_vec(encoder_data[0], + find_mux_local_decoder_addr_size( + mux_graph.memories_at_level(level).size())); } /* Build final mux bitstream */ for (const size_t& bit : encoder_addr) { mux_bitstream.push_back(1 == bit); } - } + } return mux_bitstream; } /******************************************************************** * This function generates bitstream for a routing multiplexer - * supporting both CMOS and ReRAM multiplexer designs + * supporting both CMOS and ReRAM multiplexer designs *******************************************************************/ std::vector build_mux_bitstream(const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, @@ -155,17 +163,18 @@ std::vector build_mux_bitstream(const CircuitLibrary& circuit_lib, std::vector mux_bitstream; switch (circuit_lib.design_tech_type(mux_model)) { - case CIRCUIT_MODEL_DESIGN_CMOS: - mux_bitstream = build_cmos_mux_bitstream(circuit_lib, mux_model, mux_lib, mux_size, path_id); - break; - case CIRCUIT_MODEL_DESIGN_RRAM: - /* TODO: ReRAM MUX needs a different bitstream generation strategy */ - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid design technology for circuit model '%s'!\n", - circuit_lib.model_name(mux_model).c_str()); - exit(1); + case CIRCUIT_MODEL_DESIGN_CMOS: + mux_bitstream = build_cmos_mux_bitstream(circuit_lib, mux_model, mux_lib, + mux_size, path_id); + break; + case CIRCUIT_MODEL_DESIGN_RRAM: + /* TODO: ReRAM MUX needs a different bitstream generation strategy */ + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid design technology for circuit model '%s'!\n", + circuit_lib.model_name(mux_model).c_str()); + exit(1); } return mux_bitstream; } diff --git a/openfpga/src/fpga_bitstream/build_mux_bitstream.h b/openfpga/src/fpga_bitstream/build_mux_bitstream.h index 639e086bc..5dffde1d5 100644 --- a/openfpga/src/fpga_bitstream/build_mux_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_mux_bitstream.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "circuit_library.h" #include "mux_library.h" diff --git a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp index 13a9c455e..7af606194 100644 --- a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp @@ -1,7 +1,7 @@ /******************************************************************** * This file includes functions to build bitstream from global routing * architecture of a mapped FPGA fabric - * We decode the bitstream from configuration of routing multiplexers + * We decode the bitstream from configuration of routing multiplexers * which locate in global routing architecture *******************************************************************/ #include @@ -11,18 +11,16 @@ #include "vtr_log.h" /* Headers from openfpgautil library */ -#include "openfpga_side_manager.h" - -#include "mux_utils.h" -#include "rr_gsb_utils.h" -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" -#include "openfpga_rr_graph_utils.h" -#include "module_manager_utils.h" - -#include "mux_bitstream_constants.h" #include "build_mux_bitstream.h" #include "build_routing_bitstream.h" +#include "module_manager_utils.h" +#include "mux_bitstream_constants.h" +#include "mux_utils.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "openfpga_rr_graph_utils.h" +#include "openfpga_side_manager.h" +#include "rr_gsb_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -33,22 +31,17 @@ namespace openfpga { * If not a routing multiplexer, no bitstream is needed here * If yes, we will generate the bitstream for the routing multiplexer *******************************************************************/ -static -void build_switch_block_mux_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& mux_mem_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const RRGraphView& rr_graph, - const RRNodeId& cur_rr_node, - const std::vector& drive_rr_nodes, - const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, - const VprRoutingAnnotation& routing_annotation) { +static void build_switch_block_mux_bitstream( + BitstreamManager& bitstream_manager, const ConfigBlockId& mux_mem_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, const RRGraphView& rr_graph, + const RRNodeId& cur_rr_node, const std::vector& drive_rr_nodes, + const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, + const VprRoutingAnnotation& routing_annotation) { /* Check current rr_node is CHANX or CHANY*/ - VTR_ASSERT( (CHANX == rr_graph.node_type(cur_rr_node)) - || (CHANY == rr_graph.node_type(cur_rr_node))); - + VTR_ASSERT((CHANX == rr_graph.node_type(cur_rr_node)) || + (CHANY == rr_graph.node_type(cur_rr_node))); + /* Find the input size of the implementation of a routing multiplexer */ size_t datapath_mux_size = drive_rr_nodes.size(); @@ -60,18 +53,20 @@ void build_switch_block_mux_bitstream(BitstreamManager& bitstream_manager, } VTR_ASSERT(input_nets.size() == drive_rr_nodes.size()); - /* Find out which routing path is used in this MUX + /* Find out which routing path is used in this MUX * Two conditions to be considered: * - There is no net mapped to cur_rr_node: we use default path id * - There is a net mapped to cur_rr_node: we find the path id */ int path_id = DEFAULT_PATH_ID; if (ClusterNetId::INVALID() != output_net) { - /* We must have a valid previous node that is supposed to drive the source node! */ + /* We must have a valid previous node that is supposed to drive the source + * node! */ VTR_ASSERT(routing_annotation.rr_node_prev_node(cur_rr_node)); for (size_t inode = 0; inode < drive_rr_nodes.size(); ++inode) { - if ( (input_nets[inode] == output_net) - && (drive_rr_nodes[inode] == routing_annotation.rr_node_prev_node(cur_rr_node)) ) { + if ((input_nets[inode] == output_net) && + (drive_rr_nodes[inode] == + routing_annotation.rr_node_prev_node(cur_rr_node))) { path_id = (int)inode; break; } @@ -79,24 +74,33 @@ void build_switch_block_mux_bitstream(BitstreamManager& bitstream_manager, } /* Ensure that our path id makes sense! */ - VTR_ASSERT( (DEFAULT_PATH_ID == path_id) - || ( (DEFAULT_PATH_ID < path_id) && (path_id < (int)datapath_mux_size) ) - ); + VTR_ASSERT( + (DEFAULT_PATH_ID == path_id) || + ((DEFAULT_PATH_ID < path_id) && (path_id < (int)datapath_mux_size))); - /* Find the circuit model id of the mux, we need its design technology which matters the bitstream generation */ - std::vector driver_switches = get_rr_graph_driver_switches(rr_graph, cur_rr_node); + /* Find the circuit model id of the mux, we need its design technology which + * matters the bitstream generation */ + std::vector driver_switches = + get_rr_graph_driver_switches(rr_graph, cur_rr_node); VTR_ASSERT(1 == driver_switches.size()); - CircuitModelId mux_model = device_annotation.rr_switch_circuit_model(driver_switches[0]); + CircuitModelId mux_model = + device_annotation.rr_switch_circuit_model(driver_switches[0]); /* Generate bitstream depend on both technology and structure of this MUX */ - std::vector mux_bitstream = build_mux_bitstream(circuit_lib, mux_model, mux_lib, datapath_mux_size, path_id); + std::vector mux_bitstream = build_mux_bitstream( + circuit_lib, mux_model, mux_lib, datapath_mux_size, path_id); /* Find the module in module manager and ensure the bitstream size matches! */ - std::string mem_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string(MEMORY_MODULE_POSTFIX)); - ModuleId mux_mem_module = module_manager.find_module(mem_module_name); - VTR_ASSERT (true == module_manager.valid_module_id(mux_mem_module)); - ModulePortId mux_mem_out_port_id = module_manager.find_module_port(mux_mem_module, generate_configurable_memory_data_out_name()); - VTR_ASSERT(mux_bitstream.size() == module_manager.module_port(mux_mem_module, mux_mem_out_port_id).get_width()); + std::string mem_module_name = + generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, + std::string(MEMORY_MODULE_POSTFIX)); + ModuleId mux_mem_module = module_manager.find_module(mem_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(mux_mem_module)); + ModulePortId mux_mem_out_port_id = module_manager.find_module_port( + mux_mem_module, generate_configurable_memory_data_out_name()); + VTR_ASSERT(mux_bitstream.size() == + module_manager.module_port(mux_mem_module, mux_mem_out_port_id) + .get_width()); /* Add the bistream to the bitstream manager */ bitstream_manager.add_block_bits(mux_mem_block, mux_bitstream); @@ -133,55 +137,54 @@ void build_switch_block_mux_bitstream(BitstreamManager& bitstream_manager, } /******************************************************************** - * This function generates bitstream for an interconnection, + * This function generates bitstream for an interconnection, * i.e., a routing multiplexer, in a Switch Block * This function will identify if a node indicates a routing multiplexer * If not a routing multiplexer, no bitstream is needed here * If yes, we will generate the bitstream for the routing multiplexer *******************************************************************/ -static -void build_switch_block_interc_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& sb_configurable_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const RRGraphView& rr_graph, - const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, - const VprRoutingAnnotation& routing_annotation, - const RRGSB& rr_gsb, - const e_side& chan_side, - const size_t& chan_node_id) { - +static void build_switch_block_interc_bitstream( + BitstreamManager& bitstream_manager, + const ConfigBlockId& sb_configurable_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, const RRGraphView& rr_graph, + const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, + const VprRoutingAnnotation& routing_annotation, const RRGSB& rr_gsb, + const e_side& chan_side, const size_t& chan_node_id) { std::vector driver_rr_nodes; /* Get the node */ const RRNodeId& cur_rr_node = rr_gsb.get_chan_node(chan_side, chan_node_id); - /* Determine if the interc lies inside a channel wire, that is interc between segments */ - if (false == rr_gsb.is_sb_node_passing_wire(rr_graph, chan_side, chan_node_id)) { - driver_rr_nodes = get_rr_gsb_chan_node_configurable_driver_nodes(rr_graph, rr_gsb, chan_side, chan_node_id); + /* Determine if the interc lies inside a channel wire, that is interc between + * segments */ + if (false == + rr_gsb.is_sb_node_passing_wire(rr_graph, chan_side, chan_node_id)) { + driver_rr_nodes = get_rr_gsb_chan_node_configurable_driver_nodes( + rr_graph, rr_gsb, chan_side, chan_node_id); /* Special: if there are zero-driver nodes. We skip here */ if (0 == driver_rr_nodes.size()) { - return; + return; } } - if ( (0 == driver_rr_nodes.size()) - || (0 == driver_rr_nodes.size()) ) { + if ((0 == driver_rr_nodes.size()) || (0 == driver_rr_nodes.size())) { /* No bitstream generation required by a special direct connection*/ return; } else if (1 < driver_rr_nodes.size()) { - /* Create the block denoting the memory instances that drives this node in Switch Block */ - std::string mem_block_name = generate_sb_memory_instance_name(SWITCH_BLOCK_MEM_INSTANCE_PREFIX, chan_side, chan_node_id, std::string("")); + /* Create the block denoting the memory instances that drives this node in + * Switch Block */ + std::string mem_block_name = generate_sb_memory_instance_name( + SWITCH_BLOCK_MEM_INSTANCE_PREFIX, chan_side, chan_node_id, + std::string("")); ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name); bitstream_manager.add_child_block(sb_configurable_block, mux_mem_block); /* This is a routing multiplexer! Generate bitstream */ - build_switch_block_mux_bitstream(bitstream_manager, mux_mem_block, module_manager, - circuit_lib, mux_lib, rr_graph, - cur_rr_node, driver_rr_nodes, - atom_ctx, device_annotation, routing_annotation); - } /*Nothing should be done else*/ + build_switch_block_mux_bitstream( + bitstream_manager, mux_mem_block, module_manager, circuit_lib, mux_lib, + rr_graph, cur_rr_node, driver_rr_nodes, atom_ctx, device_annotation, + routing_annotation); + } /*Nothing should be done else*/ } /******************************************************************** @@ -189,39 +192,37 @@ void build_switch_block_interc_bitstream(BitstreamManager& bitstream_manager, * and add it to the bitstream manager * This function will spot all the routing multiplexers in a Switch Block * using a simple but effective rule: - * The fan-in of each output node. - * If there are more than 2 fan-in, there is a routing multiplexer + * The fan-in of each output node. + * If there are more than 2 fan-in, there is a routing multiplexer * - * Note that the output nodes typically spread over all the sides of a Switch Block - * So, we will iterate over that. + * Note that the output nodes typically spread over all the sides of a Switch + *Block So, we will iterate over that. *******************************************************************/ -static -void build_switch_block_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& sb_config_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, - const VprRoutingAnnotation& routing_annotation, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb) { - +static void build_switch_block_bitstream( + BitstreamManager& bitstream_manager, const ConfigBlockId& sb_config_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, const AtomContext& atom_ctx, + const VprDeviceAnnotation& device_annotation, + const VprRoutingAnnotation& routing_annotation, const RRGraphView& rr_graph, + const RRGSB& rr_gsb) { /* Iterate over all the multiplexers */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); - for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) { - VTR_ASSERT( (CHANX == rr_graph.node_type(rr_gsb.get_chan_node(side_manager.get_side(), itrack))) - || (CHANY == rr_graph.node_type(rr_gsb.get_chan_node(side_manager.get_side(), itrack))) ); + for (size_t itrack = 0; + itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) { + VTR_ASSERT((CHANX == rr_graph.node_type(rr_gsb.get_chan_node( + side_manager.get_side(), itrack))) || + (CHANY == rr_graph.node_type(rr_gsb.get_chan_node( + side_manager.get_side(), itrack)))); /* Only output port indicates a routing multiplexer */ - if (OUT_PORT != rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) { + if (OUT_PORT != + rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) { continue; } - build_switch_block_interc_bitstream(bitstream_manager, sb_config_block, - module_manager, - circuit_lib, mux_lib, rr_graph, - atom_ctx, device_annotation, routing_annotation, - rr_gsb, side_manager.get_side(), itrack); + build_switch_block_interc_bitstream( + bitstream_manager, sb_config_block, module_manager, circuit_lib, + mux_lib, rr_graph, atom_ctx, device_annotation, routing_annotation, + rr_gsb, side_manager.get_side(), itrack); } } } @@ -233,25 +234,19 @@ void build_switch_block_bitstream(BitstreamManager& bitstream_manager, * If not a routing multiplexer, no bitstream is needed here * If yes, we will generate the bitstream for the routing multiplexer *******************************************************************/ -static -void build_connection_block_mux_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& mux_mem_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - 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) { - +static void build_connection_block_mux_bitstream( + BitstreamManager& bitstream_manager, const ConfigBlockId& mux_mem_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + 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) { 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); + std::vector driver_rr_edges = + rr_gsb.get_ipin_node_in_edges(rr_graph, cb_ipin_side, ipin_index); /* Cache input and output nets */ std::vector input_nets; @@ -273,10 +268,11 @@ void build_connection_block_mux_bitstream(BitstreamManager& bitstream_manager, if (ClusterNetId::INVALID() != output_net) { for (const RREdgeId& edge : driver_rr_edges) { RRNodeId driver_node = rr_graph.edge_src_node(edge); - /* We must have a valid previous node that is supposed to drive the source node! */ + /* We must have a valid previous node that is supposed to drive the source + * node! */ VTR_ASSERT(routing_annotation.rr_node_prev_node(src_rr_node)); - if ( (routing_annotation.rr_node_net(driver_node) == output_net) - && (driver_node == routing_annotation.rr_node_prev_node(src_rr_node)) ) { + if ((routing_annotation.rr_node_net(driver_node) == output_net) && + (driver_node == routing_annotation.rr_node_prev_node(src_rr_node))) { path_id = edge_index; break; } @@ -285,24 +281,33 @@ void build_connection_block_mux_bitstream(BitstreamManager& bitstream_manager, } /* Ensure that our path id makes sense! */ - VTR_ASSERT( (DEFAULT_PATH_ID == path_id) - || ( (DEFAULT_PATH_ID < path_id) && (path_id < (int)datapath_mux_size) ) - ); + VTR_ASSERT( + (DEFAULT_PATH_ID == path_id) || + ((DEFAULT_PATH_ID < path_id) && (path_id < (int)datapath_mux_size))); - /* Find the circuit model id of the mux, we need its design technology which matters the bitstream generation */ - std::vector driver_switches = get_rr_graph_driver_switches(rr_graph, src_rr_node); + /* Find the circuit model id of the mux, we need its design technology which + * matters the bitstream generation */ + std::vector driver_switches = + get_rr_graph_driver_switches(rr_graph, src_rr_node); VTR_ASSERT(1 == driver_switches.size()); - CircuitModelId mux_model = device_annotation.rr_switch_circuit_model(driver_switches[0]); + CircuitModelId mux_model = + device_annotation.rr_switch_circuit_model(driver_switches[0]); /* Generate bitstream depend on both technology and structure of this MUX */ - std::vector mux_bitstream = build_mux_bitstream(circuit_lib, mux_model, mux_lib, datapath_mux_size, path_id); + std::vector mux_bitstream = build_mux_bitstream( + circuit_lib, mux_model, mux_lib, datapath_mux_size, path_id); /* Find the module in module manager and ensure the bitstream size matches! */ - std::string mem_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string(MEMORY_MODULE_POSTFIX)); - ModuleId mux_mem_module = module_manager.find_module(mem_module_name); - VTR_ASSERT (true == module_manager.valid_module_id(mux_mem_module)); - ModulePortId mux_mem_out_port_id = module_manager.find_module_port(mux_mem_module, generate_configurable_memory_data_out_name()); - VTR_ASSERT(mux_bitstream.size() == module_manager.module_port(mux_mem_module, mux_mem_out_port_id).get_width()); + std::string mem_module_name = + generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, + std::string(MEMORY_MODULE_POSTFIX)); + ModuleId mux_mem_module = module_manager.find_module(mem_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(mux_mem_module)); + ModulePortId mux_mem_out_port_id = module_manager.find_module_port( + mux_mem_module, generate_configurable_memory_data_out_name()); + VTR_ASSERT(mux_bitstream.size() == + module_manager.module_port(mux_mem_module, mux_mem_out_port_id) + .get_width()); /* Add the bistream to the bitstream manager */ bitstream_manager.add_block_bits(mux_mem_block, mux_bitstream); @@ -336,34 +341,28 @@ void build_connection_block_mux_bitstream(BitstreamManager& bitstream_manager, output_net_ids += std::string("unmapped"); } bitstream_manager.add_output_net_id_to_block(mux_mem_block, output_net_ids); - } /******************************************************************** - * This function generates bitstream for an interconnection, + * This function generates bitstream for an interconnection, * i.e., a routing multiplexer, in a Connection Block * This function will identify if a node indicates a routing multiplexer * If not a routing multiplexer, no bitstream is needed here * If yes, we will generate the bitstream for the routing multiplexer *******************************************************************/ -static -void build_connection_block_interc_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& cb_configurable_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - 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) { - +static void build_connection_block_interc_bitstream( + BitstreamManager& bitstream_manager, + const ConfigBlockId& cb_configurable_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + 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) { RRNodeId src_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, 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); + std::vector driver_rr_edges = + rr_gsb.get_ipin_node_in_edges(rr_graph, cb_ipin_side, ipin_index); std::vector driver_rr_nodes; for (const RREdgeId curr_edge : driver_rr_edges) { driver_rr_nodes.push_back(rr_graph.edge_src_node(curr_edge)); @@ -372,16 +371,20 @@ void build_connection_block_interc_bitstream(BitstreamManager& bitstream_manager if (1 == driver_rr_nodes.size()) { /* No bitstream generation required by a special direct connection*/ } else if (1 < driver_rr_nodes.size()) { - /* Create the block denoting the memory instances that drives this node in Switch Block */ - std::string mem_block_name = generate_cb_memory_instance_name(CONNECTION_BLOCK_MEM_INSTANCE_PREFIX, get_rr_graph_single_node_side(rr_graph, src_rr_node), ipin_index, std::string("")); + /* Create the block denoting the memory instances that drives this node in + * Switch Block */ + std::string mem_block_name = generate_cb_memory_instance_name( + CONNECTION_BLOCK_MEM_INSTANCE_PREFIX, + get_rr_graph_single_node_side(rr_graph, src_rr_node), ipin_index, + std::string("")); ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name); bitstream_manager.add_child_block(cb_configurable_block, mux_mem_block); /* This is a routing multiplexer! Generate bitstream */ - build_connection_block_mux_bitstream(bitstream_manager, mux_mem_block, - module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, routing_annotation, - rr_graph, rr_gsb, cb_ipin_side, ipin_index); - } /*Nothing should be done else*/ + build_connection_block_mux_bitstream( + bitstream_manager, mux_mem_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, routing_annotation, rr_graph, rr_gsb, + cb_ipin_side, ipin_index); + } /*Nothing should be done else*/ } /******************************************************************** @@ -389,37 +392,33 @@ void build_connection_block_interc_bitstream(BitstreamManager& bitstream_manager * and add it to the bitstream manager * This function will spot all the routing multiplexers in a Connection Block * using a simple but effective rule: - * The fan-in of each output node. - * If there are more than 2 fan-in, there is a routing multiplexer + * The fan-in of each output node. + * If there are more than 2 fan-in, there is a routing multiplexer * * Note that the output nodes are the IPIN rr node in a Connection Block * So, we will iterate over that. *******************************************************************/ -static -void build_connection_block_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& cb_configurable_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - 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) { - - /* Find routing multiplexers on the sides of a Connection block where IPIN nodes locate */ +static void build_connection_block_bitstream( + BitstreamManager& bitstream_manager, + const ConfigBlockId& cb_configurable_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + 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) { + /* 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); for (size_t side = 0; side < cb_sides.size(); ++side) { enum e_side cb_ipin_side = cb_sides[side]; SideManager side_manager(cb_ipin_side); - for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); ++inode) { - 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); + for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); + ++inode) { + 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); } } } @@ -427,95 +426,97 @@ void build_connection_block_bitstream(BitstreamManager& bitstream_manager, /******************************************************************** * Create bitstream for a X-direction or Y-direction Connection Blocks *******************************************************************/ -static -void build_connection_block_bitstreams(BitstreamManager& bitstream_manager, - const ConfigBlockId& top_configurable_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - 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 t_rr_type& cb_type) { - +static void build_connection_block_bitstreams( + BitstreamManager& bitstream_manager, + const ConfigBlockId& top_configurable_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + 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 t_rr_type& cb_type) { vtr::Point cb_range = device_rr_gsb.get_gsb_range(); for (size_t ix = 0; ix < cb_range.x(); ++ix) { for (size_t iy = 0; iy < cb_range.y(); ++iy) { const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); /* Check if the connection block exists in the device! - * Some of them do NOT exist due to heterogeneous blocks (height > 1) + * Some of them do NOT exist due to heterogeneous blocks (height > 1) * We will skip those modules */ if (false == rr_gsb.is_cb_exist(cb_type)) { continue; } /* Skip if the cb does not contain any configuration bits! */ - if (true == connection_block_contain_only_routing_tracks(rr_gsb, cb_type)) { + if (true == + connection_block_contain_only_routing_tracks(rr_gsb, cb_type)) { continue; } /* 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)); - std::string cb_module_name = generate_connection_block_module_name(cb_type, cb_coord); + vtr::Point cb_coord(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); + std::string cb_module_name = + generate_connection_block_module_name(cb_type, cb_coord); if (true == compact_routing_hierarchy) { vtr::Point unique_cb_coord(ix, iy); /* Note: use GSB coordinate when inquire for unique modules!!! */ - const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(cb_type, unique_cb_coord); - unique_cb_coord.set_x(unique_mirror.get_cb_x(cb_type)); - unique_cb_coord.set_y(unique_mirror.get_cb_y(cb_type)); - cb_module_name = generate_connection_block_module_name(cb_type, unique_cb_coord); - } + const RRGSB& unique_mirror = + device_rr_gsb.get_cb_unique_module(cb_type, unique_cb_coord); + unique_cb_coord.set_x(unique_mirror.get_cb_x(cb_type)); + unique_cb_coord.set_y(unique_mirror.get_cb_y(cb_type)); + cb_module_name = + generate_connection_block_module_name(cb_type, unique_cb_coord); + } ModuleId cb_module = module_manager.find_module(cb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); /* Bypass empty blocks which have none configurable children */ - if (0 == count_module_manager_module_configurable_children(module_manager, cb_module)) { + if (0 == count_module_manager_module_configurable_children(module_manager, + cb_module)) { continue; - } + } - /* Create a block for the bitstream which corresponds to the Switch block */ - ConfigBlockId cb_configurable_block = bitstream_manager.add_block(generate_connection_block_module_name(cb_type, cb_coord)); + /* Create a block for the bitstream which corresponds to the Switch block + */ + ConfigBlockId cb_configurable_block = bitstream_manager.add_block( + generate_connection_block_module_name(cb_type, cb_coord)); /* Set switch block as a child of top block */ - bitstream_manager.add_child_block(top_configurable_block, cb_configurable_block); + bitstream_manager.add_child_block(top_configurable_block, + cb_configurable_block); /* Reserve child blocks for new created block */ - bitstream_manager.reserve_child_blocks(cb_configurable_block, - count_module_manager_module_configurable_children(module_manager, cb_module)); - - 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); + bitstream_manager.reserve_child_blocks( + cb_configurable_block, + count_module_manager_module_configurable_children(module_manager, + cb_module)); + + 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); } } } /******************************************************************** * Top-level function to create bitstream for global routing architecture - * Two major tasks: + * Two major tasks: * 1. Generate bitstreams for Switch Blocks * 2. Generate bitstreams for both X-direction and Y-direction Connection Blocks *******************************************************************/ -void build_routing_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& top_configurable_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - 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) { - +void build_routing_bitstream( + BitstreamManager& bitstream_manager, + const ConfigBlockId& top_configurable_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + 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) { /* 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 managers + * 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 + * managers */ VTR_LOG("Generating bitstream for Switch blocks..."); vtr::Point sb_range = device_rr_gsb.get_gsb_range(); @@ -523,7 +524,7 @@ void build_routing_bitstream(BitstreamManager& bitstream_manager, for (size_t iy = 0; iy < sb_range.y(); ++iy) { const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); /* Check if the switch block exists in the device! - * Some of them do NOT exist due to heterogeneous blocks (width > 1) + * Some of them do NOT exist due to heterogeneous blocks (width > 1) * We will skip those modules */ if (false == rr_gsb.is_sb_exist()) { @@ -536,63 +537,63 @@ void build_routing_bitstream(BitstreamManager& bitstream_manager, std::string sb_module_name = generate_switch_block_module_name(sb_coord); if (true == compact_routing_hierarchy) { vtr::Point unique_sb_coord(ix, iy); - const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(sb_coord); - unique_sb_coord.set_x(unique_mirror.get_sb_x()); - unique_sb_coord.set_y(unique_mirror.get_sb_y()); + const RRGSB& unique_mirror = + device_rr_gsb.get_sb_unique_module(sb_coord); + unique_sb_coord.set_x(unique_mirror.get_sb_x()); + unique_sb_coord.set_y(unique_mirror.get_sb_y()); sb_module_name = generate_switch_block_module_name(unique_sb_coord); - } + } ModuleId sb_module = module_manager.find_module(sb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); /* Bypass empty blocks which have none configurable children */ - if (0 == count_module_manager_module_configurable_children(module_manager, sb_module)) { + if (0 == count_module_manager_module_configurable_children(module_manager, + sb_module)) { continue; - } + } - /* Create a block for the bitstream which corresponds to the Switch block */ - ConfigBlockId sb_configurable_block = bitstream_manager.add_block(generate_switch_block_module_name(sb_coord)); + /* Create a block for the bitstream which corresponds to the Switch block + */ + ConfigBlockId sb_configurable_block = bitstream_manager.add_block( + generate_switch_block_module_name(sb_coord)); /* Set switch block as a child of top block */ - bitstream_manager.add_child_block(top_configurable_block, sb_configurable_block); + bitstream_manager.add_child_block(top_configurable_block, + sb_configurable_block); /* Reserve child blocks for new created block */ - bitstream_manager.reserve_child_blocks(sb_configurable_block, - count_module_manager_module_configurable_children(module_manager, sb_module)); + bitstream_manager.reserve_child_blocks( + sb_configurable_block, + count_module_manager_module_configurable_children(module_manager, + sb_module)); - build_switch_block_bitstream(bitstream_manager, sb_configurable_block, module_manager, - circuit_lib, mux_lib, - atom_ctx, device_annotation, routing_annotation, - rr_graph, - rr_gsb); + build_switch_block_bitstream(bitstream_manager, sb_configurable_block, + module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, + routing_annotation, rr_graph, rr_gsb); } } VTR_LOG("Done\n"); /* Generate bitstream for each connection blocks - * To organize the bitstream in blocks, we create a block for each connection block - * and give names which are same as they are in top-level module managers + * To organize the bitstream in blocks, we create a block for each connection + * block and give names which are same as they are in top-level module + * managers */ VTR_LOG("Generating bitstream for X-direction Connection blocks ..."); - 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); + 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); VTR_LOG("Done\n"); VTR_LOG("Generating bitstream for Y-direction Connection blocks ..."); - 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); + 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); VTR_LOG("Done\n"); - } } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_routing_bitstream.h b/openfpga/src/fpga_bitstream/build_routing_bitstream.h index 763f615d2..ea955dbe1 100644 --- a/openfpga/src/fpga_bitstream/build_routing_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_routing_bitstream.h @@ -8,12 +8,13 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "bitstream_manager.h" -#include "vpr_context.h" -#include "module_manager.h" #include "circuit_library.h" -#include "mux_library.h" #include "device_rr_gsb.h" +#include "module_manager.h" +#include "mux_library.h" +#include "vpr_context.h" #include "vpr_device_annotation.h" #include "vpr_routing_annotation.h" @@ -24,17 +25,14 @@ /* begin namespace openfpga */ namespace openfpga { -void build_routing_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& top_configurable_block, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - 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); +void build_routing_bitstream( + BitstreamManager& bitstream_manager, + const ConfigBlockId& top_configurable_block, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + 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); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp index f622f3fbc..5649388b8 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp @@ -1,11 +1,12 @@ /****************************************************************************** * This file includes member functions for data structure FabricBitstream ******************************************************************************/ +#include "fabric_bitstream.h" + #include -#include "vtr_assert.h" #include "openfpga_decode.h" -#include "fabric_bitstream.h" +#include "vtr_assert.h" /* begin namespace openfpga */ namespace openfpga { @@ -29,27 +30,27 @@ FabricBitstream::FabricBitstream() { /************************************************** * Public Accessors : Aggregates *************************************************/ -size_t FabricBitstream::num_bits() const { - return num_bits_; -} +size_t FabricBitstream::num_bits() const { return num_bits_; } /* Find all the configuration bits */ FabricBitstream::fabric_bit_range FabricBitstream::bits() const { - return vtr::make_range(fabric_bit_iterator(FabricBitId(0), invalid_bit_ids_), - fabric_bit_iterator(FabricBitId(num_bits_), invalid_bit_ids_)); + return vtr::make_range( + fabric_bit_iterator(FabricBitId(0), invalid_bit_ids_), + fabric_bit_iterator(FabricBitId(num_bits_), invalid_bit_ids_)); } -size_t FabricBitstream::num_regions() const { - return num_regions_; -} +size_t FabricBitstream::num_regions() const { return num_regions_; } /* Find all the configuration bits */ FabricBitstream::fabric_bit_region_range FabricBitstream::regions() const { - return vtr::make_range(fabric_bit_region_iterator(FabricBitRegionId(0), invalid_region_ids_), - fabric_bit_region_iterator(FabricBitRegionId(num_regions_), invalid_region_ids_)); + return vtr::make_range( + fabric_bit_region_iterator(FabricBitRegionId(0), invalid_region_ids_), + fabric_bit_region_iterator(FabricBitRegionId(num_regions_), + invalid_region_ids_)); } -std::vector FabricBitstream::region_bits(const FabricBitRegionId& region_id) const { +std::vector FabricBitstream::region_bits( + const FabricBitRegionId& region_id) const { /* Ensure a valid id */ VTR_ASSERT(true == valid_region_id(region_id)); @@ -66,7 +67,8 @@ ConfigBitId FabricBitstream::config_bit(const FabricBitId& bit_id) const { return config_bit_ids_[bit_id]; } -std::vector FabricBitstream::bit_address(const FabricBitId& bit_id) const { +std::vector FabricBitstream::bit_address( + const FabricBitId& bit_id) const { /* Ensure a valid id */ VTR_ASSERT(true == valid_bit_id(bit_id)); VTR_ASSERT(true == use_address_); @@ -74,19 +76,26 @@ std::vector FabricBitstream::bit_address(const FabricBitId& bit_id) const /* Decode address bits */ std::vector addr_bits; addr_bits.reserve(address_length_); - for (size_t curr_idx = 0; curr_idx < bit_address_1bits_[bit_id].size(); curr_idx++) { - size_t curr_addr_len = std::min(size_t(64), address_length_ - curr_idx * 64); - std::vector curr_addr_vec = decode_address_bits(bit_address_1bits_[bit_id][curr_idx], bit_address_xbits_[bit_id][curr_idx], curr_addr_len); - addr_bits.insert(addr_bits.end(), curr_addr_vec.begin(), curr_addr_vec.end()); + for (size_t curr_idx = 0; curr_idx < bit_address_1bits_[bit_id].size(); + curr_idx++) { + size_t curr_addr_len = + std::min(size_t(64), address_length_ - curr_idx * 64); + std::vector curr_addr_vec = + decode_address_bits(bit_address_1bits_[bit_id][curr_idx], + bit_address_xbits_[bit_id][curr_idx], curr_addr_len); + addr_bits.insert(addr_bits.end(), curr_addr_vec.begin(), + curr_addr_vec.end()); } return addr_bits; } -std::vector FabricBitstream::bit_bl_address(const FabricBitId& bit_id) const { +std::vector FabricBitstream::bit_bl_address( + const FabricBitId& bit_id) const { return bit_address(bit_id); } -std::vector FabricBitstream::bit_wl_address(const FabricBitId& bit_id) const { +std::vector FabricBitstream::bit_wl_address( + const FabricBitId& bit_id) const { /* Ensure a valid id */ VTR_ASSERT(true == valid_bit_id(bit_id)); VTR_ASSERT(true == use_address_); @@ -95,10 +104,15 @@ std::vector FabricBitstream::bit_wl_address(const FabricBitId& bit_id) con /* Decode address bits */ std::vector addr_bits; addr_bits.reserve(wl_address_length_); - for (size_t curr_idx = 0; curr_idx < bit_wl_address_1bits_[bit_id].size(); curr_idx++) { - size_t curr_addr_len = std::min(size_t(64), wl_address_length_ - curr_idx * 64); - std::vector curr_addr_vec = decode_address_bits(bit_wl_address_1bits_[bit_id][curr_idx], bit_wl_address_xbits_[bit_id][curr_idx], curr_addr_len); - addr_bits.insert(addr_bits.end(), curr_addr_vec.begin(), curr_addr_vec.end()); + for (size_t curr_idx = 0; curr_idx < bit_wl_address_1bits_[bit_id].size(); + curr_idx++) { + size_t curr_addr_len = + std::min(size_t(64), wl_address_length_ - curr_idx * 64); + std::vector curr_addr_vec = decode_address_bits( + bit_wl_address_1bits_[bit_id][curr_idx], + bit_wl_address_xbits_[bit_id][curr_idx], curr_addr_len); + addr_bits.insert(addr_bits.end(), curr_addr_vec.begin(), + curr_addr_vec.end()); } return addr_bits; } @@ -111,25 +125,21 @@ char FabricBitstream::bit_din(const FabricBitId& bit_id) const { return bit_dins_[bit_id]; } -bool FabricBitstream::use_address() const { - return use_address_; -} +bool FabricBitstream::use_address() const { return use_address_; } -bool FabricBitstream::use_wl_address() const { - return use_wl_address_; -} +bool FabricBitstream::use_wl_address() const { return use_wl_address_; } /****************************************************************************** * Public Mutators ******************************************************************************/ void FabricBitstream::reserve_bits(const size_t& num_bits) { config_bit_ids_.reserve(num_bits); - + if (true == use_address_) { bit_address_1bits_.reserve(num_bits); bit_address_xbits_.reserve(num_bits); bit_dins_.reserve(num_bits); - + if (true == use_wl_address_) { bit_wl_address_1bits_.reserve(num_bits); bit_wl_address_xbits_.reserve(num_bits); @@ -147,14 +157,14 @@ FabricBitId FabricBitstream::add_bit(const ConfigBitId& config_bit_id) { bit_address_1bits_.emplace_back(); bit_address_xbits_.emplace_back(); bit_dins_.emplace_back(); - + if (true == use_wl_address_) { bit_wl_address_1bits_.emplace_back(); bit_wl_address_xbits_.emplace_back(); } } - return bit; + return bit; } void FabricBitstream::set_bit_address(const FabricBitId& bit_id, @@ -168,9 +178,11 @@ void FabricBitstream::set_bit_address(const FabricBitId& bit_id, VTR_ASSERT(address_length_ == address.size()); } /* Split the address into several 64 vectors */ - for (size_t start_idx = 0; start_idx < address.size(); start_idx = start_idx + 64) { + for (size_t start_idx = 0; start_idx < address.size(); + start_idx = start_idx + 64) { size_t curr_end_idx = std::min(address.size(), start_idx + 64); - std::vector curr_addr_vec64(address.begin() + start_idx, address.begin() + curr_end_idx); + std::vector curr_addr_vec64(address.begin() + start_idx, + address.begin() + curr_end_idx); /* Encode bit '1' and bit 'x' into two numbers */ bit_address_1bits_[bit_id].push_back(encode_address_1bits(curr_addr_vec64)); bit_address_xbits_[bit_id].push_back(encode_address_xbits(curr_addr_vec64)); @@ -195,17 +207,20 @@ void FabricBitstream::set_bit_wl_address(const FabricBitId& bit_id, VTR_ASSERT(wl_address_length_ == address.size()); } /* Split the address into several 64 vectors */ - for (size_t start_idx = 0; start_idx < address.size(); start_idx = start_idx + 64) { + for (size_t start_idx = 0; start_idx < address.size(); + start_idx = start_idx + 64) { size_t curr_end_idx = std::min(address.size(), start_idx + 64); - std::vector curr_addr_vec64(address.begin() + start_idx, address.begin() + curr_end_idx); + std::vector curr_addr_vec64(address.begin() + start_idx, + address.begin() + curr_end_idx); /* Encode bit '1' and bit 'x' into two numbers */ - bit_wl_address_1bits_[bit_id].push_back(encode_address_1bits(curr_addr_vec64)); - bit_wl_address_xbits_[bit_id].push_back(encode_address_xbits(curr_addr_vec64)); + bit_wl_address_1bits_[bit_id].push_back( + encode_address_1bits(curr_addr_vec64)); + bit_wl_address_xbits_[bit_id].push_back( + encode_address_xbits(curr_addr_vec64)); } } -void FabricBitstream::set_bit_din(const FabricBitId& bit_id, - const char& din) { +void FabricBitstream::set_bit_din(const FabricBitId& bit_id, const char& din) { VTR_ASSERT(true == valid_bit_id(bit_id)); VTR_ASSERT(true == use_address_); bit_dins_[bit_id] = din; @@ -220,7 +235,7 @@ void FabricBitstream::set_use_address(const bool& enable) { void FabricBitstream::set_address_length(const size_t& length) { if (true == use_address_) { - address_length_ = length; + address_length_ = length; } } @@ -237,7 +252,7 @@ void FabricBitstream::set_use_wl_address(const bool& enable) { void FabricBitstream::set_wl_address_length(const size_t& length) { if (true == use_address_) { - wl_address_length_ = length; + wl_address_length_ = length; } } @@ -251,15 +266,15 @@ FabricBitRegionId FabricBitstream::add_region() { num_regions_++; region_bit_ids_.emplace_back(); - return region; + return region; } void FabricBitstream::add_bit_to_region(const FabricBitRegionId& region_id, const FabricBitId& bit_id) { VTR_ASSERT(true == valid_region_id(region_id)); VTR_ASSERT(true == valid_bit_id(bit_id)); - - region_bit_ids_[region_id].push_back(bit_id); + + region_bit_ids_[region_id].push_back(bit_id); } void FabricBitstream::reverse() { @@ -280,7 +295,8 @@ void FabricBitstream::reverse() { void FabricBitstream::reverse_region_bits(const FabricBitRegionId& region_id) { VTR_ASSERT(true == valid_region_id(region_id)); - std::reverse(region_bit_ids_[region_id].begin(), region_bit_ids_[region_id].end()); + std::reverse(region_bit_ids_[region_id].begin(), + region_bit_ids_[region_id].end()); } /****************************************************************************** @@ -290,11 +306,13 @@ bool FabricBitstream::valid_bit_id(const FabricBitId& bit_id) const { return (size_t(bit_id) < num_bits_); } -bool FabricBitstream::valid_region_id(const FabricBitRegionId& region_id) const { +bool FabricBitstream::valid_region_id( + const FabricBitRegionId& region_id) const { return (size_t(region_id) < num_regions_); } -uint64_t FabricBitstream::encode_address_1bits(const std::vector& address) const { +uint64_t FabricBitstream::encode_address_1bits( + const std::vector& address) const { /* Convert all the 'x' bit into 0 */ std::vector binary_address = address; for (char& bit : binary_address) { @@ -306,7 +324,8 @@ uint64_t FabricBitstream::encode_address_1bits(const std::vector& address) return (uint64_t)bintoi_charvec(binary_address); } -uint64_t FabricBitstream::encode_address_xbits(const std::vector& address) const { +uint64_t FabricBitstream::encode_address_xbits( + const std::vector& address) const { /* Convert all the '1' bit into 0 and Convert all the 'x' bit into 1 */ std::vector binary_address = address; for (char& bit : binary_address) { @@ -321,11 +340,12 @@ uint64_t FabricBitstream::encode_address_xbits(const std::vector& address) return (uint64_t)bintoi_charvec(binary_address); } -std::vector FabricBitstream::decode_address_bits(const size_t& bit1, const size_t& bitx, const size_t& addr_len) const { +std::vector FabricBitstream::decode_address_bits( + const size_t& bit1, const size_t& bitx, const size_t& addr_len) const { /* Decode the bit1 number to a binary vector */ - std::vector ret_vec = itobin_charvec(bit1, addr_len); + std::vector ret_vec = itobin_charvec(bit1, addr_len); /* Decode the bitx number to a binary vector */ - std::vector bitx_vec = itobin_charvec(bitx, addr_len); + std::vector bitx_vec = itobin_charvec(bitx, addr_len); /* Combine the two vectors: 'x' overwrite any bit '0' and '1' */ for (size_t ibit = 0; ibit < ret_vec.size(); ++ibit) { if (bitx_vec[ibit] == '1') { diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.h b/openfpga/src/fpga_bitstream/fabric_bitstream.h index 12f2f9e03..68a972636 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.h @@ -1,237 +1,255 @@ /****************************************************************************** - * This file introduces a data structure to store fabric-dependent bitstream information + * This file introduces a data structure to store fabric-dependent bitstream + *information * * General concept * --------------- - * The idea is to create a unified data structure that stores the sequence of configuration - * bit in the architecture bitstream database - * as well as the information (such as address of each bit) required by a specific - * configuration protocol + * The idea is to create a unified data structure that stores the sequence of + *configuration bit in the architecture bitstream database as well as the + *information (such as address of each bit) required by a specific configuration + *protocol * - * Cross-reference + * Cross-reference * --------------- - * By using the link between ArchBitstreamManager and FabricBitstream, - * we can build a sequence of configuration bits to fit different configuration protocols. + * By using the link between ArchBitstreamManager and FabricBitstream, + * we can build a sequence of configuration bits to fit different configuration + *protocols. * * +----------------------+ +-------------------+ * | | ConfigBitId | | * | ArchBitstreamManager |---------------->| FabricBitstream | - * | | | | - * +----------------------+ +-------------------+ + * | | | | + * +----------------------+ +-------------------+ * * Restrictions: - * 1. Each block inside BitstreamManager should have only 1 parent block + * 1. Each block inside BitstreamManager should have only 1 parent block * and multiple child block - * 2. Each bit inside BitstreamManager should have only 1 parent block - * + * 2. Each bit inside BitstreamManager should have only 1 parent block + * ******************************************************************************/ #ifndef FABRIC_BITSTREAM_H #define FABRIC_BITSTREAM_H -#include -#include #include -#include "vtr_vector.h" +#include +#include #include "bitstream_manager_fwd.h" #include "fabric_bitstream_fwd.h" +#include "vtr_vector.h" /* begin namespace openfpga */ namespace openfpga { class FabricBitstream { - public: /* Type implementations */ - /* - * This class (forward delcared above) is a template used to represent a lazily calculated - * iterator of the specified ID type. The key assumption made is that the ID space is - * contiguous and can be walked by incrementing the underlying ID value. To account for - * invalid IDs, it keeps a reference to the invalid ID set and returns ID::INVALID() for - * ID values in the set. - * - * It is used to lazily create an iteration range (e.g. as returned by RRGraph::edges() RRGraph::nodes()) - * just based on the count of allocated elements (i.e. RRGraph::num_nodes_ or RRGraph::num_edges_), - * and the set of any invalid IDs (i.e. RRGraph::invalid_node_ids_, RRGraph::invalid_edge_ids_). - */ - template - class lazy_id_iterator : public std::iterator { - public: - //Since we pass ID as a template to std::iterator we need to use an explicit 'typename' - //to bring the value_type and iterator names into scope - typedef typename std::iterator::value_type value_type; - typedef typename std::iterator::iterator iterator; + public: /* Type implementations */ + /* + * This class (forward delcared above) is a template used to represent a + * lazily calculated iterator of the specified ID type. The key assumption + * made is that the ID space is contiguous and can be walked by incrementing + * the underlying ID value. To account for invalid IDs, it keeps a reference + * to the invalid ID set and returns ID::INVALID() for ID values in the set. + * + * It is used to lazily create an iteration range (e.g. as returned by + * RRGraph::edges() RRGraph::nodes()) just based on the count of allocated + * elements (i.e. RRGraph::num_nodes_ or RRGraph::num_edges_), and the set of + * any invalid IDs (i.e. RRGraph::invalid_node_ids_, + * RRGraph::invalid_edge_ids_). + */ + template + class lazy_id_iterator + : public std::iterator { + public: + // Since we pass ID as a template to std::iterator we need to use an + // explicit 'typename' to bring the value_type and iterator names into scope + typedef + typename std::iterator::value_type + value_type; + typedef + typename std::iterator::iterator + iterator; - lazy_id_iterator(value_type init, const std::unordered_set& invalid_ids) - : value_(init) - , invalid_ids_(invalid_ids) {} + lazy_id_iterator(value_type init, const std::unordered_set& invalid_ids) + : value_(init), invalid_ids_(invalid_ids) {} - //Advance to the next ID value - iterator operator++() { - value_ = ID(size_t(value_) + 1); - return *this; - } + // Advance to the next ID value + iterator operator++() { + value_ = ID(size_t(value_) + 1); + return *this; + } - //Advance to the previous ID value - iterator operator--() { - value_ = ID(size_t(value_) - 1); - return *this; - } + // Advance to the previous ID value + iterator operator--() { + value_ = ID(size_t(value_) - 1); + return *this; + } - //Dereference the iterator - value_type operator*() const { return (invalid_ids_.count(value_)) ? ID::INVALID() : value_; } + // Dereference the iterator + value_type operator*() const { + return (invalid_ids_.count(value_)) ? ID::INVALID() : value_; + } - friend bool operator==(const lazy_id_iterator lhs, const lazy_id_iterator rhs) { return lhs.value_ == rhs.value_; } - friend bool operator!=(const lazy_id_iterator lhs, const lazy_id_iterator rhs) { return !(lhs == rhs); } + friend bool operator==(const lazy_id_iterator lhs, + const lazy_id_iterator rhs) { + return lhs.value_ == rhs.value_; + } + friend bool operator!=(const lazy_id_iterator lhs, + const lazy_id_iterator rhs) { + return !(lhs == rhs); + } - private: - value_type value_; - const std::unordered_set& invalid_ids_; - }; + private: + value_type value_; + const std::unordered_set& invalid_ids_; + }; - public: /* Types and ranges */ - //Lazy iterator utility forward declaration - template - class lazy_id_iterator; + public: /* Types and ranges */ + // Lazy iterator utility forward declaration + template + class lazy_id_iterator; - typedef lazy_id_iterator fabric_bit_iterator; - typedef lazy_id_iterator fabric_bit_region_iterator; + typedef lazy_id_iterator fabric_bit_iterator; + typedef lazy_id_iterator fabric_bit_region_iterator; - typedef vtr::Range fabric_bit_range; - typedef vtr::Range fabric_bit_region_range; + typedef vtr::Range fabric_bit_range; + typedef vtr::Range fabric_bit_region_range; - public: /* Public constructor */ - FabricBitstream(); + public: /* Public constructor */ + FabricBitstream(); - public: /* Public aggregators */ - /* Find all the configuration bits */ - size_t num_bits() const; - fabric_bit_range bits() const; + public: /* Public aggregators */ + /* Find all the configuration bits */ + size_t num_bits() const; + fabric_bit_range bits() const; - /* Find all the configuration regions */ - size_t num_regions() const; - fabric_bit_region_range regions() const; - std::vector region_bits(const FabricBitRegionId& region_id) const; + /* Find all the configuration regions */ + size_t num_regions() const; + fabric_bit_region_range regions() const; + std::vector region_bits( + const FabricBitRegionId& region_id) const; - public: /* Public Accessors */ - /* Find the configuration bit id in architecture bitstream database */ - ConfigBitId config_bit(const FabricBitId& bit_id) const; + public: /* Public Accessors */ + /* Find the configuration bit id in architecture bitstream database */ + ConfigBitId config_bit(const FabricBitId& bit_id) const; - /* Find the address of bitstream */ - std::vector bit_address(const FabricBitId& bit_id) const; - std::vector bit_bl_address(const FabricBitId& bit_id) const; - std::vector bit_wl_address(const FabricBitId& bit_id) const; + /* Find the address of bitstream */ + std::vector bit_address(const FabricBitId& bit_id) const; + std::vector bit_bl_address(const FabricBitId& bit_id) const; + std::vector bit_wl_address(const FabricBitId& bit_id) const; - /* Find the data-in of bitstream */ - char bit_din(const FabricBitId& bit_id) const; + /* Find the data-in of bitstream */ + char bit_din(const FabricBitId& bit_id) const; - /* Check if address data is accessible or not*/ - bool use_address() const; - bool use_wl_address() const; + /* Check if address data is accessible or not*/ + bool use_address() const; + bool use_wl_address() const; - public: /* Public Mutators */ - /* Reserve config bits */ - void reserve_bits(const size_t& num_bits); + public: /* Public Mutators */ + /* Reserve config bits */ + void reserve_bits(const size_t& num_bits); - /* Add a new configuration bit to the bitstream manager */ - FabricBitId add_bit(const ConfigBitId& config_bit_id); + /* Add a new configuration bit to the bitstream manager */ + FabricBitId add_bit(const ConfigBitId& config_bit_id); - void set_bit_address(const FabricBitId& bit_id, - const std::vector& address, - const bool& tolerant_short_address = false); + void set_bit_address(const FabricBitId& bit_id, + const std::vector& address, + const bool& tolerant_short_address = false); - void set_bit_bl_address(const FabricBitId& bit_id, - const std::vector& address, - const bool& tolerant_short_address = false); + void set_bit_bl_address(const FabricBitId& bit_id, + const std::vector& address, + const bool& tolerant_short_address = false); - void set_bit_wl_address(const FabricBitId& bit_id, - const std::vector& address, - const bool& tolerant_short_address = false); + void set_bit_wl_address(const FabricBitId& bit_id, + const std::vector& address, + const bool& tolerant_short_address = false); - void set_bit_din(const FabricBitId& bit_id, - const char& din); + void set_bit_din(const FabricBitId& bit_id, const char& din); - /* Reserve regions */ - void reserve_regions(const size_t& num_regions); + /* Reserve regions */ + void reserve_regions(const size_t& num_regions); - /* Add a new configuration region */ - FabricBitRegionId add_region(); + /* Add a new configuration region */ + FabricBitRegionId add_region(); - void add_bit_to_region(const FabricBitRegionId& region_id, - const FabricBitId& bit_id); + void add_bit_to_region(const FabricBitRegionId& region_id, + const FabricBitId& bit_id); - /* Reserve bits by region */ - void reverse_region_bits(const FabricBitRegionId& region_id); + /* Reserve bits by region */ + void reverse_region_bits(const FabricBitRegionId& region_id); - /* Reverse bit sequence of the fabric bitstream - * This is required by configuration chain protocol - */ - void reverse(); + /* Reverse bit sequence of the fabric bitstream + * This is required by configuration chain protocol + */ + void reverse(); - /* Enable the use of address-related data - * When this is enabled, data allocation will be applied to these data - * and users can access/modify the data - * Otherwise, it will NOT be allocated and accessible. - * - * This function is only applicable before any bits are added - */ - void set_use_address(const bool& enable); - void set_address_length(const size_t& length); - void set_bl_address_length(const size_t& length); + /* Enable the use of address-related data + * When this is enabled, data allocation will be applied to these data + * and users can access/modify the data + * Otherwise, it will NOT be allocated and accessible. + * + * This function is only applicable before any bits are added + */ + void set_use_address(const bool& enable); + void set_address_length(const size_t& length); + void set_bl_address_length(const size_t& length); - /* Enable the use of WL-address related data - * Same priniciple as the set_use_address() - */ - void set_use_wl_address(const bool& enable); - void set_wl_address_length(const size_t& length); + /* Enable the use of WL-address related data + * Same priniciple as the set_use_address() + */ + void set_use_wl_address(const bool& enable); + void set_wl_address_length(const size_t& length); - public: /* Public Validators */ - bool valid_bit_id(const FabricBitId& bit_id) const; - bool valid_region_id(const FabricBitRegionId& bit_id) const; + public: /* Public Validators */ + bool valid_bit_id(const FabricBitId& bit_id) const; + bool valid_region_id(const FabricBitRegionId& bit_id) const; - private: /* Private APIs */ - uint64_t encode_address_1bits(const std::vector& address) const; - uint64_t encode_address_xbits(const std::vector& address) const; - std::vector decode_address_bits(const size_t& bit1, const size_t& bitx, const size_t& addr_len) const; + private: /* Private APIs */ + uint64_t encode_address_1bits(const std::vector& address) const; + uint64_t encode_address_xbits(const std::vector& address) const; + std::vector decode_address_bits(const size_t& bit1, const size_t& bitx, + const size_t& addr_len) const; - private: /* Internal data */ - /* Unique id of a region in the Bitstream */ - size_t num_regions_; - std::unordered_set invalid_region_ids_; - vtr::vector> region_bit_ids_; + private: /* Internal data */ + /* Unique id of a region in the Bitstream */ + size_t num_regions_; + std::unordered_set invalid_region_ids_; + vtr::vector> region_bit_ids_; - /* Unique id of a bit in the Bitstream */ - size_t num_bits_; - std::unordered_set invalid_bit_ids_; - vtr::vector config_bit_ids_; + /* Unique id of a bit in the Bitstream */ + size_t num_bits_; + std::unordered_set invalid_bit_ids_; + vtr::vector config_bit_ids_; - /* Flags to indicate if the addresses and din should be enabled */ - bool use_address_; - bool use_wl_address_; + /* Flags to indicate if the addresses and din should be enabled */ + bool use_address_; + bool use_wl_address_; - size_t address_length_; - size_t wl_address_length_; + size_t address_length_; + size_t wl_address_length_; - /* Address bits: this is designed for memory decoders - * Here we store the encoded format of the address, and decoded to binary format which can be loaded - * to the configuration protocol directly - * - * Encoding strategy is as follows: - * - An address bit which may contain '0', '1', 'x'. For example - * 101x1 - * - The string can be encoded into two integer numbers: - * - bit-one number: which encodes the '0' and '1' bits into a number. For example, - * 101x1 -> 10101 -> 21 - * - bit-x number: which encodes the 'x' bits into a number. For example, - * 101x1 -> 00010 -> 2 - * - * Note that when the length of address vector is more than 64, we use multiple 64-bit data to store the encoded values - */ - vtr::vector> bit_address_1bits_; - vtr::vector> bit_address_xbits_; - vtr::vector> bit_wl_address_1bits_; - vtr::vector> bit_wl_address_xbits_; + /* Address bits: this is designed for memory decoders + * Here we store the encoded format of the address, and decoded to binary + * format which can be loaded to the configuration protocol directly + * + * Encoding strategy is as follows: + * - An address bit which may contain '0', '1', 'x'. For example + * 101x1 + * - The string can be encoded into two integer numbers: + * - bit-one number: which encodes the '0' and '1' bits into a number. For + * example, 101x1 -> 10101 -> 21 + * - bit-x number: which encodes the 'x' bits into a number. For example, + * 101x1 -> 00010 -> 2 + * + * Note that when the length of address vector is more than 64, we use + * multiple 64-bit data to store the encoded values + */ + vtr::vector> bit_address_1bits_; + vtr::vector> bit_address_xbits_; + vtr::vector> bit_wl_address_1bits_; + vtr::vector> bit_wl_address_xbits_; - /* Data input (Din) bits: this is designed for memory decoders */ - vtr::vector bit_dins_; + /* Data input (Din) bits: this is designed for memory decoders */ + vtr::vector bit_dins_; }; } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream_fwd.h b/openfpga/src/fpga_bitstream/fabric_bitstream_fwd.h index bc0a87beb..cec77f6d9 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream_fwd.h +++ b/openfpga/src/fpga_bitstream/fabric_bitstream_fwd.h @@ -1,5 +1,5 @@ /************************************************** - * This file includes only declarations for + * This file includes only declarations for * the data structures for fabric-dependent bitstream database * Please refer to fabric_bitstream.h for more details *************************************************/ @@ -22,4 +22,4 @@ class FabricBitstream; } /* end namespace openfpga */ -#endif +#endif diff --git a/openfpga/src/fpga_bitstream/fast_configuration.cpp b/openfpga/src/fpga_bitstream/fast_configuration.cpp index 112fac5c3..4c4100ae2 100644 --- a/openfpga/src/fpga_bitstream/fast_configuration.cpp +++ b/openfpga/src/fpga_bitstream/fast_configuration.cpp @@ -5,11 +5,10 @@ #include /* Headers from vtrutil library */ -#include "vtr_log.h" -#include "vtr_assert.h" - #include "fabric_global_port_info_utils.h" #include "fast_configuration.h" +#include "vtr_assert.h" +#include "vtr_log.h" /* begin namespace openfpga */ namespace openfpga { @@ -18,14 +17,19 @@ namespace openfpga { * Identify if fast configuration is applicable base on the availability * of programming reset and programming set ports of the FPGA fabric *******************************************************************/ -bool is_fast_configuration_applicable(const FabricGlobalPortInfo& global_ports) { +bool is_fast_configuration_applicable( + const FabricGlobalPortInfo& global_ports) { /* Preparation: find all the reset/set ports for programming usage */ - std::vector global_prog_reset_ports = find_fabric_global_programming_reset_ports(global_ports); - std::vector global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports); + std::vector global_prog_reset_ports = + find_fabric_global_programming_reset_ports(global_ports); + std::vector global_prog_set_ports = + find_fabric_global_programming_set_ports(global_ports); /* Identify if we can apply fast configuration */ if (global_prog_set_ports.empty() && global_prog_reset_ports.empty()) { - VTR_LOG_WARN("None of global reset and set ports are defined for programming purpose. Fast configuration is not applicable\n"); + VTR_LOG_WARN( + "None of global reset and set ports are defined for programming purpose. " + "Fast configuration is not applicable\n"); return false; } @@ -35,84 +39,98 @@ bool is_fast_configuration_applicable(const FabricGlobalPortInfo& global_ports) /******************************************************************** * Decide if we should use reset or set signal to acheive fast configuration * - If only one type signal is specified, we use that type - * For example, only reset signal is defined, we will use reset + * For example, only reset signal is defined, we will use reset * - If both are defined, pick the one that will bring bigger reduction * i.e., larger number of configuration bits can be skipped *******************************************************************/ -bool find_bit_value_to_skip_for_fast_configuration(const e_config_protocol_type& config_protocol_type, - const FabricGlobalPortInfo& global_ports, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream) { +bool find_bit_value_to_skip_for_fast_configuration( + const e_config_protocol_type& config_protocol_type, + const FabricGlobalPortInfo& global_ports, + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream) { /* Preparation: find all the reset/set ports for programming usage */ - std::vector global_prog_reset_ports = find_fabric_global_programming_reset_ports(global_ports); - std::vector global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports); + std::vector global_prog_reset_ports = + find_fabric_global_programming_reset_ports(global_ports); + std::vector global_prog_set_ports = + find_fabric_global_programming_set_ports(global_ports); /* Early exit conditions */ if (!global_prog_reset_ports.empty() && global_prog_set_ports.empty()) { - return false; - } else if (!global_prog_set_ports.empty() && global_prog_reset_ports.empty()) { - return true; + return false; + } else if (!global_prog_set_ports.empty() && + global_prog_reset_ports.empty()) { + return true; } - /* If both types of ports are not defined, the fast configuration is not applicable */ - VTR_ASSERT(!global_prog_set_ports.empty() && !global_prog_reset_ports.empty()); + /* If both types of ports are not defined, the fast configuration is not + * applicable */ + VTR_ASSERT(!global_prog_set_ports.empty() && + !global_prog_reset_ports.empty()); bool bit_value_to_skip = false; - VTR_LOG("Both reset and set ports are defined for programming controls, selecting the best-fit one...\n"); + VTR_LOG( + "Both reset and set ports are defined for programming controls, selecting " + "the best-fit one...\n"); size_t num_ones_to_skip = 0; size_t num_zeros_to_skip = 0; /* Branch on the type of configuration protocol */ switch (config_protocol_type) { - case CONFIG_MEM_STANDALONE: - break; - case CONFIG_MEM_SCAN_CHAIN: { - /* We can only skip the ones/zeros at the beginning of the bitstream */ - /* Count how many logic '1' bits we can skip */ - for (const FabricBitId& bit_id : fabric_bitstream.bits()) { - if (false == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) { - break; - } - VTR_ASSERT(true == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))); - num_ones_to_skip++; - } - /* Count how many logic '0' bits we can skip */ - for (const FabricBitId& bit_id : fabric_bitstream.bits()) { - if (true == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) { - break; - } - VTR_ASSERT(false == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))); - num_zeros_to_skip++; - } - break; - } - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: - case CONFIG_MEM_FRAME_BASED: { - /* Count how many logic '1' and logic '0' bits we can skip */ - for (const FabricBitId& bit_id : fabric_bitstream.bits()) { - if (false == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) { - num_zeros_to_skip++; - } else { - VTR_ASSERT(true == bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))); + case CONFIG_MEM_STANDALONE: + break; + case CONFIG_MEM_SCAN_CHAIN: { + /* We can only skip the ones/zeros at the beginning of the bitstream */ + /* Count how many logic '1' bits we can skip */ + for (const FabricBitId& bit_id : fabric_bitstream.bits()) { + if (false == + bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) { + break; + } + VTR_ASSERT(true == bitstream_manager.bit_value( + fabric_bitstream.config_bit(bit_id))); num_ones_to_skip++; } + /* Count how many logic '0' bits we can skip */ + for (const FabricBitId& bit_id : fabric_bitstream.bits()) { + if (true == + bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) { + break; + } + VTR_ASSERT(false == bitstream_manager.bit_value( + fabric_bitstream.config_bit(bit_id))); + num_zeros_to_skip++; + } + break; } - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid configuration protocol type!\n"); - exit(1); + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: + case CONFIG_MEM_FRAME_BASED: { + /* Count how many logic '1' and logic '0' bits we can skip */ + for (const FabricBitId& bit_id : fabric_bitstream.bits()) { + if (false == + bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) { + num_zeros_to_skip++; + } else { + VTR_ASSERT(true == bitstream_manager.bit_value( + fabric_bitstream.config_bit(bit_id))); + num_ones_to_skip++; + } + } + break; + } + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid configuration protocol type!\n"); + exit(1); } VTR_LOG("Using reset will skip %g% (%lu/%lu) of configuration bitstream.\n", - 100. * (float) num_zeros_to_skip / (float) fabric_bitstream.num_bits(), + 100. * (float)num_zeros_to_skip / (float)fabric_bitstream.num_bits(), num_zeros_to_skip, fabric_bitstream.num_bits()); VTR_LOG("Using set will skip %g% (%lu/%lu) of configuration bitstream.\n", - 100. * (float) num_ones_to_skip / (float) fabric_bitstream.num_bits(), + 100. * (float)num_ones_to_skip / (float)fabric_bitstream.num_bits(), num_ones_to_skip, fabric_bitstream.num_bits()); /* By default, we prefer to skip zeros (when the numbers are the same */ diff --git a/openfpga/src/fpga_bitstream/fast_configuration.h b/openfpga/src/fpga_bitstream/fast_configuration.h index eb161d1b2..48bc28398 100644 --- a/openfpga/src/fpga_bitstream/fast_configuration.h +++ b/openfpga/src/fpga_bitstream/fast_configuration.h @@ -6,10 +6,11 @@ *******************************************************************/ #include #include -#include "fabric_global_port_info.h" -#include "config_protocol.h" + #include "bitstream_manager.h" +#include "config_protocol.h" #include "fabric_bitstream.h" +#include "fabric_global_port_info.h" /******************************************************************** * Function declaration @@ -20,10 +21,11 @@ namespace openfpga { bool is_fast_configuration_applicable(const FabricGlobalPortInfo& global_ports); -bool find_bit_value_to_skip_for_fast_configuration(const e_config_protocol_type& config_protocol_type, - const FabricGlobalPortInfo& global_ports, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream); +bool find_bit_value_to_skip_for_fast_configuration( + const e_config_protocol_type& config_protocol_type, + const FabricGlobalPortInfo& global_ports, + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.cpp index 110732b3d..da9a390a9 100644 --- a/openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.cpp @@ -8,32 +8,34 @@ size_t MemoryBankFlattenFabricBitstream::size() const { } size_t MemoryBankFlattenFabricBitstream::bl_vector_size() const { - /* The address sizes and data input sizes are the same across any element, + /* The address sizes and data input sizes are the same across any element, * just get it from the 1st element to save runtime */ size_t bl_vec_size = 0; for (const auto& bl_vec : bitstream_.begin()->second) { bl_vec_size += bl_vec.size(); - } + } return bl_vec_size; } size_t MemoryBankFlattenFabricBitstream::wl_vector_size() const { - /* The address sizes and data input sizes are the same across any element, + /* The address sizes and data input sizes are the same across any element, * just get it from the 1st element to save runtime */ size_t wl_vec_size = 0; for (const auto& wl_vec : bitstream_.begin()->first) { wl_vec_size += wl_vec.size(); - } + } return wl_vec_size; } -std::vector MemoryBankFlattenFabricBitstream::bl_vector(const std::vector& wl_vec) const { +std::vector MemoryBankFlattenFabricBitstream::bl_vector( + const std::vector& wl_vec) const { return bitstream_.at(wl_vec); } -std::vector> MemoryBankFlattenFabricBitstream::wl_vectors() const { +std::vector> +MemoryBankFlattenFabricBitstream::wl_vectors() const { std::vector> wl_vecs; for (const auto& pair : bitstream_) { wl_vecs.push_back(pair.first); @@ -41,8 +43,9 @@ std::vector> MemoryBankFlattenFabricBitstream::wl_vecto return wl_vecs; } -void MemoryBankFlattenFabricBitstream::add_blwl_vectors(const std::vector& bl_vec, - const std::vector& wl_vec) { +void MemoryBankFlattenFabricBitstream::add_blwl_vectors( + const std::vector& bl_vec, + const std::vector& wl_vec) { /* TODO: Add sanity check. Give a warning if the wl vector is already there */ bitstream_[wl_vec] = bl_vec; } diff --git a/openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.h b/openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.h index 4c5cf27a9..2495b7dea 100644 --- a/openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.h @@ -1,47 +1,52 @@ #ifndef MEMORY_BANK_FLATTEN_FABRIC_BITSTREAM_H #define MEMORY_BANK_FLATTEN_FABRIC_BITSTREAM_H -#include #include +#include #include + #include "vtr_vector.h" /* begin namespace openfpga */ namespace openfpga { /****************************************************************************** - * This files includes data structures that stores a downloadable format of fabric bitstream - * which is compatible with memory bank configuration protocol using flatten BL/WL buses - * @note This data structure is mainly used to output bitstream file for compatible protocols + * This files includes data structures that stores a downloadable format of + *fabric bitstream which is compatible with memory bank configuration protocol + *using flatten BL/WL buses + * @note This data structure is mainly used to output bitstream file for + *compatible protocols ******************************************************************************/ class MemoryBankFlattenFabricBitstream { - public: /* Accessors */ - /* @brief Return the length of bitstream */ - size_t size() const; + public: /* Accessors */ + /* @brief Return the length of bitstream */ + size_t size() const; - /* @brief Return the BL address size */ - size_t bl_vector_size() const; + /* @brief Return the BL address size */ + size_t bl_vector_size() const; - /* @brief Return the WL address size */ - size_t wl_vector_size() const; + /* @brief Return the WL address size */ + size_t wl_vector_size() const; - /* @brief Return the BL vectors with a given WL key */ - std::vector bl_vector(const std::vector& wl_vec) const; + /* @brief Return the BL vectors with a given WL key */ + std::vector bl_vector( + const std::vector& wl_vec) const; - /* @brief Return all the WL vectors in a downloaded sequence */ - std::vector> wl_vectors() const; + /* @brief Return all the WL vectors in a downloaded sequence */ + std::vector> wl_vectors() const; - public: /* Mutators */ - /* @brief add a pair of BL/WL vectors to the bitstream database */ - void add_blwl_vectors(const std::vector& bl_vec, - const std::vector& wl_vec); - public: /* Validators */ - private: /* Internal data */ - /* [(wl_bank0, wl_bank1, ...)] = [(bl_bank0, bl_bank1, ...)] - * Must use (WL, BL) as pairs in the map!!! - * This is because BL data may not be unique while WL must be unique - */ - std::map, std::vector> bitstream_; + public: /* Mutators */ + /* @brief add a pair of BL/WL vectors to the bitstream database */ + void add_blwl_vectors(const std::vector& bl_vec, + const std::vector& wl_vec); + + public: /* Validators */ + private: /* Internal data */ + /* [(wl_bank0, wl_bank1, ...)] = [(bl_bank0, bl_bank1, ...)] + * Must use (WL, BL) as pairs in the map!!! + * This is because BL data may not be unique while WL must be unique + */ + std::map, std::vector> bitstream_; }; } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp index d758a9141..ba0bd26ab 100644 --- a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp @@ -1,11 +1,14 @@ -#include "vtr_assert.h" #include "memory_bank_shift_register_fabric_bitstream.h" +#include "vtr_assert.h" + /* begin namespace openfpga */ namespace openfpga { -MemoryBankShiftRegisterFabricBitstream::word_range MemoryBankShiftRegisterFabricBitstream::words() const { - return vtr::make_range(bitstream_word_ids_.begin(), bitstream_word_ids_.end()); +MemoryBankShiftRegisterFabricBitstream::word_range +MemoryBankShiftRegisterFabricBitstream::words() const { + return vtr::make_range(bitstream_word_ids_.begin(), + bitstream_word_ids_.end()); } size_t MemoryBankShiftRegisterFabricBitstream::num_words() const { @@ -40,22 +43,26 @@ size_t MemoryBankShiftRegisterFabricBitstream::wl_width() const { return bitstream_word_wls_[bitstream_word_ids_.back()].back().size(); } -std::vector MemoryBankShiftRegisterFabricBitstream::bl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const { +std::vector MemoryBankShiftRegisterFabricBitstream::bl_vectors( + const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const { VTR_ASSERT(valid_word_id(word_id)); return bitstream_word_bls_[word_id]; } -std::vector MemoryBankShiftRegisterFabricBitstream::wl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const { +std::vector MemoryBankShiftRegisterFabricBitstream::wl_vectors( + const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const { VTR_ASSERT(valid_word_id(word_id)); return bitstream_word_wls_[word_id]; } -MemoryBankShiftRegisterFabricBitstreamWordId MemoryBankShiftRegisterFabricBitstream::create_word() { +MemoryBankShiftRegisterFabricBitstreamWordId +MemoryBankShiftRegisterFabricBitstream::create_word() { /* Create a new id*/ - MemoryBankShiftRegisterFabricBitstreamWordId word_id = MemoryBankShiftRegisterFabricBitstreamWordId(bitstream_word_ids_.size()); + MemoryBankShiftRegisterFabricBitstreamWordId word_id = + MemoryBankShiftRegisterFabricBitstreamWordId(bitstream_word_ids_.size()); /* Update the id list */ bitstream_word_ids_.push_back(word_id); - + /* Initialize other attributes */ bitstream_word_bls_.emplace_back(); bitstream_word_wls_.emplace_back(); @@ -63,20 +70,24 @@ MemoryBankShiftRegisterFabricBitstreamWordId MemoryBankShiftRegisterFabricBitstr return word_id; } -void MemoryBankShiftRegisterFabricBitstream::add_bl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id, - const std::string& bl_vec) { +void MemoryBankShiftRegisterFabricBitstream::add_bl_vectors( + const MemoryBankShiftRegisterFabricBitstreamWordId& word_id, + const std::string& bl_vec) { VTR_ASSERT(valid_word_id(word_id)); return bitstream_word_bls_[word_id].push_back(bl_vec); } -void MemoryBankShiftRegisterFabricBitstream::add_wl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id, - const std::string& wl_vec) { +void MemoryBankShiftRegisterFabricBitstream::add_wl_vectors( + const MemoryBankShiftRegisterFabricBitstreamWordId& word_id, + const std::string& wl_vec) { VTR_ASSERT(valid_word_id(word_id)); return bitstream_word_wls_[word_id].push_back(wl_vec); } -bool MemoryBankShiftRegisterFabricBitstream::valid_word_id(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const { - return ( size_t(word_id) < bitstream_word_ids_.size() ) && ( word_id == bitstream_word_ids_[word_id] ); +bool MemoryBankShiftRegisterFabricBitstream::valid_word_id( + const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const { + return (size_t(word_id) < bitstream_word_ids_.size()) && + (word_id == bitstream_word_ids_[word_id]); } } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h index 6016da15e..53d1ec586 100644 --- a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h @@ -1,94 +1,114 @@ #ifndef MEMORY_BANK_SHIFT_REGISTER_FABRIC_BITSTREAM_H #define MEMORY_BANK_SHIFT_REGISTER_FABRIC_BITSTREAM_H -#include #include +#include #include -#include "vtr_vector.h" + #include "memory_bank_shift_register_fabric_bitstream_fwd.h" +#include "vtr_vector.h" /* begin namespace openfpga */ namespace openfpga { /****************************************************************************** - * This files includes data structures that stores a downloadable format of fabric bitstream - * which is compatible with memory bank configuration protocol using shift register to control BL/WLs - * @note This data structure is mainly used to output bitstream file for compatible protocols + * This files includes data structures that stores a downloadable format of + *fabric bitstream which is compatible with memory bank configuration protocol + *using shift register to control BL/WLs + * @note This data structure is mainly used to output bitstream file for + *compatible protocols ******************************************************************************/ class MemoryBankShiftRegisterFabricBitstream { - public: /* Types */ - typedef vtr::vector::const_iterator word_iterator; - /* Create range */ - typedef vtr::Range word_range; + public: /* Types */ + typedef vtr::vector< + MemoryBankShiftRegisterFabricBitstreamWordId, + MemoryBankShiftRegisterFabricBitstreamWordId>::const_iterator word_iterator; + /* Create range */ + typedef vtr::Range word_range; - public: /* Accessors: aggregates */ - word_range words() const; + public: /* Accessors: aggregates */ + word_range words() const; - public: /* Accessors */ - /* @brief Return the length of bitstream */ - size_t num_words() const; + public: /* Accessors */ + /* @brief Return the length of bitstream */ + size_t num_words() const; - /* @brief Return the length of BL part of each word. All the word should have a uniform size */ - size_t bl_word_size() const; + /* @brief Return the length of BL part of each word. All the word should have + * a uniform size */ + size_t bl_word_size() const; - /* @brief Return the length of WL part of each word. All the word should have a uniform size */ - size_t wl_word_size() const; + /* @brief Return the length of WL part of each word. All the word should have + * a uniform size */ + size_t wl_word_size() const; - /* @brief Return the width of each BL word, which is the number of heads through which a BL word can be loaded in parallel */ - size_t bl_width() const; + /* @brief Return the width of each BL word, which is the number of heads + * through which a BL word can be loaded in parallel */ + size_t bl_width() const; - /* @brief Return the width of each WL word, which is the number of heads through which a WL word can be loaded in parallel */ - size_t wl_width() const; + /* @brief Return the width of each WL word, which is the number of heads + * through which a WL word can be loaded in parallel */ + size_t wl_width() const; - /* @brief Return the BL vectors with a given word id*/ - std::vector bl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const; + /* @brief Return the BL vectors with a given word id*/ + std::vector bl_vectors( + const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const; - /* @brief Return the WL vectors in a given word id */ - std::vector wl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const; + /* @brief Return the WL vectors in a given word id */ + std::vector wl_vectors( + const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const; - public: /* Mutators */ - /* @brief Create a new word */ - MemoryBankShiftRegisterFabricBitstreamWordId create_word(); + public: /* Mutators */ + /* @brief Create a new word */ + MemoryBankShiftRegisterFabricBitstreamWordId create_word(); - /* @brief Add BLs to a given word */ - void add_bl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id, - const std::string& bl_vec); + /* @brief Add BLs to a given word */ + void add_bl_vectors( + const MemoryBankShiftRegisterFabricBitstreamWordId& word_id, + const std::string& bl_vec); - /* @brief Add WLs to a given word */ - void add_wl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id, - const std::string& wl_vec); + /* @brief Add WLs to a given word */ + void add_wl_vectors( + const MemoryBankShiftRegisterFabricBitstreamWordId& word_id, + const std::string& wl_vec); - public: /* Validators */ - bool valid_word_id(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const; + public: /* Validators */ + bool valid_word_id( + const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const; - private: /* Internal data */ - /* Organization of the bitstream - * - * ============= Begin of Word 1 ============== - * |<--No of -->|<-- No of -->| - * | BL heads | WL heads | - * 010101 .. 101 101110 .. 001 ---- - * ... ... ^ - * | - * max. shift register length per word - * | - * v - * 110001 .. 111 100100 .. 110 ---- - * ============= End of Word 1 ============== - * ============= Begin of Word 2 ============== - * 010101 .. 101 101110 .. 001 ---- - * ... ... ^ - * | - * max. shift register length per word - * | - * v - * 110001 .. 111 100100 .. 110 ---- - * ============= End of Word 2 ============== - * .... more words - */ - vtr::vector bitstream_word_ids_; - vtr::vector> bitstream_word_bls_; - vtr::vector> bitstream_word_wls_; + private: /* Internal data */ + /* Organization of the bitstream + * + * ============= Begin of Word 1 ============== + * |<--No of -->|<-- No of -->| + * | BL heads | WL heads | + * 010101 .. 101 101110 .. 001 ---- + * ... ... ^ + * | + * max. shift register length per word + * | + * v + * 110001 .. 111 100100 .. 110 ---- + * ============= End of Word 1 ============== + * ============= Begin of Word 2 ============== + * 010101 .. 101 101110 .. 001 ---- + * ... ... ^ + * | + * max. shift register length per word + * | + * v + * 110001 .. 111 100100 .. 110 ---- + * ============= End of Word 2 ============== + * .... more words + */ + vtr::vector + bitstream_word_ids_; + vtr::vector> + bitstream_word_bls_; + vtr::vector> + bitstream_word_wls_; }; } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream_fwd.h b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream_fwd.h index 87c1ebad2..1ec2ed3a0 100644 --- a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream_fwd.h +++ b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream_fwd.h @@ -1,7 +1,8 @@ /************************************************** - * This file includes only declarations for + * This file includes only declarations for * the data structures for MemoryBankShiftRegisterFabricBitstream - * Please refer to memory_bank_shift_register_fabric_bitstream.h for more details + * Please refer to memory_bank_shift_register_fabric_bitstream.h for more + *details *************************************************/ #ifndef MEMORY_BANK_SHIFT_REGISTER_FABRIC_BITSTREAM_FWD_H #define MEMORY_BANK_SHIFT_REGISTER_FABRIC_BITSTREAM_FWD_H @@ -14,10 +15,11 @@ namespace openfpga { /* Strong Ids for ModuleManager */ struct memory_bank_shift_register_fabric_bitstream_word_id_tag; -typedef vtr::StrongId MemoryBankShiftRegisterFabricBitstreamWordId; +typedef vtr::StrongId + MemoryBankShiftRegisterFabricBitstreamWordId; class MemoryBankShiftRegisterFabricBitstream; } /* end namespace openfpga */ -#endif +#endif diff --git a/openfpga/src/fpga_bitstream/report_bitstream_distribution.cpp b/openfpga/src/fpga_bitstream/report_bitstream_distribution.cpp index 3b3b14998..32ad025ee 100644 --- a/openfpga/src/fpga_bitstream/report_bitstream_distribution.cpp +++ b/openfpga/src/fpga_bitstream/report_bitstream_distribution.cpp @@ -12,35 +12,33 @@ /* Headers from openfpgautil library */ #include "openfpga_digest.h" +#include "openfpga_reserved_words.h" #include "openfpga_tokenizer.h" #include "openfpga_version.h" - -#include "openfpga_reserved_words.h" - #include "report_arch_bitstream_distribution.h" -#include "report_fabric_bitstream_distribution.h" #include "report_bitstream_distribution.h" +#include "report_fabric_bitstream_distribution.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * This function write header information for an XML file of bitstream distribution + * This function write header information for an XML file of bitstream + *distribution *******************************************************************/ -static -void report_bitstream_distribution_xml_file_head(std::fstream& fp, - const bool& include_time_stamp) { +static void report_bitstream_distribution_xml_file_head( + std::fstream& fp, const bool& include_time_stamp) { valid_file_stream(fp); - + fp << " " << std::endl; @@ -49,7 +47,7 @@ void report_bitstream_distribution_xml_file_head(std::fstream& fp, /******************************************************************** * Report the distribution of bitstream at architecture-level and fabric-level - * This function can generate a report to a file + * This function can generate a report to a file *******************************************************************/ int report_bitstream_distribution(const std::string& fname, const BitstreamManager& bitstream_manager, @@ -58,11 +56,15 @@ int report_bitstream_distribution(const std::string& fname, const size_t& max_hierarchy_level) { /* Ensure that we have a valid file name */ if (true == fname.empty()) { - VTR_LOG_ERROR("Received empty file name to report bitstream!\n\tPlease specify a valid file name.\n"); + VTR_LOG_ERROR( + "Received empty file name to report bitstream!\n\tPlease specify a valid " + "file name.\n"); return 1; } - std::string timer_message = std::string("Report bitstream distribution into XML file '") + fname + std::string("'"); + std::string timer_message = + std::string("Report bitstream distribution into XML file '") + fname + + std::string("'"); vtr::ScopedStartFinishTimer timer(timer_message); /* Create the file stream */ @@ -76,16 +78,18 @@ int report_bitstream_distribution(const std::string& fname, int curr_level = 0; write_tab_to_file(fp, curr_level); - fp << "" <" << std::endl; int status = 0; - status = report_fabric_bitstream_distribution(fp, fabric_bitstream, curr_level + 1); + status = + report_fabric_bitstream_distribution(fp, fabric_bitstream, curr_level + 1); if (status == 1) { return status; } - status = report_architecture_bitstream_distribution(fp, bitstream_manager, max_hierarchy_level, curr_level + 1); + status = report_architecture_bitstream_distribution( + fp, bitstream_manager, max_hierarchy_level, curr_level + 1); - fp << "" <" << std::endl; /* Close file handler */ fp.close(); diff --git a/openfpga/src/fpga_bitstream/report_bitstream_distribution.h b/openfpga/src/fpga_bitstream/report_bitstream_distribution.h index 1b175a05b..15f7cdc10 100644 --- a/openfpga/src/fpga_bitstream/report_bitstream_distribution.h +++ b/openfpga/src/fpga_bitstream/report_bitstream_distribution.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "fabric_bitstream.h" /******************************************************************** diff --git a/openfpga/src/fpga_bitstream/report_fabric_bitstream_distribution.cpp b/openfpga/src/fpga_bitstream/report_fabric_bitstream_distribution.cpp index 87f81df10..53c54a6e2 100644 --- a/openfpga/src/fpga_bitstream/report_fabric_bitstream_distribution.cpp +++ b/openfpga/src/fpga_bitstream/report_fabric_bitstream_distribution.cpp @@ -11,13 +11,11 @@ #include "vtr_time.h" /* Headers from openfpgautil library */ +#include "bitstream_manager_utils.h" #include "openfpga_digest.h" +#include "openfpga_reserved_words.h" #include "openfpga_tokenizer.h" #include "openfpga_version.h" - -#include "openfpga_reserved_words.h" - -#include "bitstream_manager_utils.h" #include "report_fabric_bitstream_distribution.h" /* begin namespace openfpga */ @@ -26,37 +24,37 @@ namespace openfpga { /******************************************************************** * Recursively report the bitstream distribution of a block to a file * This function will use a Depth-First Search in outputting bitstream - * for each block + * for each block * For block with child blocks, we visit each child recursively - * The reporting can be stopped at a given maximum hierarchy level + * The reporting can be stopped at a given maximum hierarchy level * which is used to limit the length of the report *******************************************************************/ -static -void report_region_bitstream_distribution_to_xml_file(std::fstream& fp, - const FabricBitstream& fabric_bitstream, - const FabricBitRegionId& region, - const int& hierarchy_level) { +static void report_region_bitstream_distribution_to_xml_file( + std::fstream& fp, const FabricBitstream& fabric_bitstream, + const FabricBitRegionId& region, const int& hierarchy_level) { valid_file_stream(fp); /* Write the bitstream distribution of this block */ write_tab_to_file(fp, hierarchy_level); fp << "" << std::endl; write_tab_to_file(fp, hierarchy_level); - fp << "" <" << std::endl; } /******************************************************************** * Report the distribution of bitstream by regions - * This function can generate a report to a file + * This function can generate a report to a file *******************************************************************/ -int report_fabric_bitstream_distribution(std::fstream& fp, - const FabricBitstream& fabric_bitstream, - const int& hierarchy_level) { - std::string timer_message = std::string("Report fabric bitstream distribution"); +int report_fabric_bitstream_distribution( + std::fstream& fp, const FabricBitstream& fabric_bitstream, + const int& hierarchy_level) { + std::string timer_message = + std::string("Report fabric bitstream distribution"); vtr::ScopedStartFinishTimer timer(timer_message); valid_file_stream(fp); @@ -65,11 +63,11 @@ int report_fabric_bitstream_distribution(std::fstream& fp, int curr_level = hierarchy_level; for (const FabricBitRegionId& region : fabric_bitstream.regions()) { write_tab_to_file(fp, curr_level); - fp << "" <" << std::endl; + report_region_bitstream_distribution_to_xml_file(fp, fabric_bitstream, + region, curr_level + 1); write_tab_to_file(fp, curr_level); - fp << "" <" << std::endl; } return 0; diff --git a/openfpga/src/fpga_bitstream/report_fabric_bitstream_distribution.h b/openfpga/src/fpga_bitstream/report_fabric_bitstream_distribution.h index 2ff5ed081..701bba6e9 100644 --- a/openfpga/src/fpga_bitstream/report_fabric_bitstream_distribution.h +++ b/openfpga/src/fpga_bitstream/report_fabric_bitstream_distribution.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "fabric_bitstream.h" /******************************************************************** @@ -14,9 +15,9 @@ /* begin namespace openfpga */ namespace openfpga { -int report_fabric_bitstream_distribution(std::fstream& fp, - const FabricBitstream& fabric_bitstream, - const int& hierarchy_level); +int report_fabric_bitstream_distribution( + std::fstream& fp, const FabricBitstream& fabric_bitstream, + const int& hierarchy_level); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 8a710a994..9cb2a3f9c 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * This file includes functions that output a fabric-dependent + * This file includes functions that output a fabric-dependent * bitstream database to files in plain text *******************************************************************/ #include @@ -12,15 +12,13 @@ #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_decode.h" -#include "openfpga_digest.h" -#include "openfpga_version.h" - -#include "openfpga_naming.h" - -#include "fast_configuration.h" #include "bitstream_manager_utils.h" #include "fabric_bitstream_utils.h" +#include "fast_configuration.h" +#include "openfpga_decode.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_version.h" #include "write_text_fabric_bitstream.h" /* begin namespace openfpga */ @@ -29,15 +27,14 @@ namespace openfpga { /******************************************************************** * This function write header information to a bitstream file *******************************************************************/ -static -void write_fabric_bitstream_text_file_head(std::fstream& fp, - const bool& include_time_stamp) { +static void write_fabric_bitstream_text_file_head( + std::fstream& fp, const bool& include_time_stamp) { valid_file_stream(fp); - + fp << "// Fabric bitstream" << std::endl; if (include_time_stamp) { - auto end = std::chrono::system_clock::now(); + auto end = std::chrono::system_clock::now(); std::time_t end_time = std::chrono::system_clock::to_time_t(end); /* Note that version is also a type of time stamp */ fp << "// Version: " << openfpga::VERSION << std::endl; @@ -46,16 +43,15 @@ void write_fabric_bitstream_text_file_head(std::fstream& fp, } /******************************************************************** - * Write the flatten fabric bitstream to a plain text file + * Write the flatten fabric bitstream to a plain text file * * Return: * - 0 if succeed * - 1 if critical errors occured *******************************************************************/ -static -int write_flatten_fabric_bitstream_to_text_file(std::fstream& fp, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream) { +static int write_flatten_fabric_bitstream_to_text_file( + std::fstream& fp, const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream) { if (false == valid_file_stream(fp)) { return 1; } @@ -73,39 +69,47 @@ int write_flatten_fabric_bitstream_to_text_file(std::fstream& fp, /******************************************************************** * Write the fabric bitstream fitting a configuration chain protocol - * to a plain text file + * to a plain text file * * Return: * - 0 if succeed * - 1 if critical errors occured *******************************************************************/ -static -int write_config_chain_fabric_bitstream_to_text_file(std::fstream& fp, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream) { +static int write_config_chain_fabric_bitstream_to_text_file( + std::fstream& fp, const bool& fast_configuration, + const bool& bit_value_to_skip, const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream) { int status = 0; - size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream); - ConfigChainFabricBitstream regional_bitstreams = build_config_chain_fabric_bitstream_by_region(bitstream_manager, fabric_bitstream); + size_t regional_bitstream_max_size = + find_fabric_regional_bitstream_max_size(fabric_bitstream); + ConfigChainFabricBitstream regional_bitstreams = + build_config_chain_fabric_bitstream_by_region(bitstream_manager, + fabric_bitstream); /* For fast configuration, the bitstream size counts from the first bit '1' */ size_t num_bits_to_skip = 0; if (true == fast_configuration) { - num_bits_to_skip = find_configuration_chain_fabric_bitstream_size_to_be_skipped(fabric_bitstream, bitstream_manager, bit_value_to_skip); + num_bits_to_skip = + find_configuration_chain_fabric_bitstream_size_to_be_skipped( + fabric_bitstream, bitstream_manager, bit_value_to_skip); VTR_ASSERT(num_bits_to_skip < regional_bitstream_max_size); - VTR_LOG("Fast configuration will skip %g% (%lu/%lu) of configuration bitstream.\n", - 100. * (float) num_bits_to_skip / (float) regional_bitstream_max_size, - num_bits_to_skip, regional_bitstream_max_size); + VTR_LOG( + "Fast configuration will skip %g% (%lu/%lu) of configuration " + "bitstream.\n", + 100. * (float)num_bits_to_skip / (float)regional_bitstream_max_size, + num_bits_to_skip, regional_bitstream_max_size); } /* Output bitstream size information */ - fp << "// Bitstream length: " << regional_bitstream_max_size - num_bits_to_skip << std::endl; - fp << "// Bitstream width (LSB -> MSB): " << fabric_bitstream.num_regions() << std::endl; + fp << "// Bitstream length: " + << regional_bitstream_max_size - num_bits_to_skip << std::endl; + fp << "// Bitstream width (LSB -> MSB): " << fabric_bitstream.num_regions() + << std::endl; /* Output bitstream data */ - for (size_t ibit = num_bits_to_skip; ibit < regional_bitstream_max_size; ++ibit) { + for (size_t ibit = num_bits_to_skip; ibit < regional_bitstream_max_size; + ++ibit) { for (const auto& region_bitstream : regional_bitstreams) { fp << region_bitstream[ibit]; } @@ -118,41 +122,46 @@ int write_config_chain_fabric_bitstream_to_text_file(std::fstream& fp, } /******************************************************************** - * Write the fabric bitstream fitting a memory bank protocol - * to a plain text file + * Write the fabric bitstream fitting a memory bank protocol + * to a plain text file * * Return: * - 0 if succeed * - 1 if critical errors occured *******************************************************************/ -static -int write_memory_bank_fabric_bitstream_to_text_file(std::fstream& fp, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const FabricBitstream& fabric_bitstream) { +static int write_memory_bank_fabric_bitstream_to_text_file( + std::fstream& fp, const bool& fast_configuration, + const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream) { int status = 0; - MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); + MemoryBankFabricBitstream fabric_bits_by_addr = + build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); - /* The address sizes and data input sizes are the same across any element, + /* The address sizes and data input sizes are the same across any element, * just get it from the 1st element to save runtime */ - size_t bl_addr_size = fabric_bits_by_addr.begin()->first.first.size(); - size_t wl_addr_size = fabric_bits_by_addr.begin()->first.second.size(); - size_t din_size = fabric_bits_by_addr.begin()->second.size(); + size_t bl_addr_size = fabric_bits_by_addr.begin()->first.first.size(); + size_t wl_addr_size = fabric_bits_by_addr.begin()->first.second.size(); + size_t din_size = fabric_bits_by_addr.begin()->second.size(); /* Identify and output bitstream size information */ size_t num_bits_to_skip = 0; if (true == fast_configuration) { - num_bits_to_skip = fabric_bits_by_addr.size() - find_memory_bank_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); + num_bits_to_skip = + fabric_bits_by_addr.size() - + find_memory_bank_fast_configuration_fabric_bitstream_size( + fabric_bitstream, bit_value_to_skip); VTR_ASSERT(num_bits_to_skip < fabric_bits_by_addr.size()); - VTR_LOG("Fast configuration will skip %g% (%lu/%lu) of configuration bitstream.\n", - 100. * (float) num_bits_to_skip / (float) fabric_bits_by_addr.size(), - num_bits_to_skip, fabric_bits_by_addr.size()); + VTR_LOG( + "Fast configuration will skip %g% (%lu/%lu) of configuration " + "bitstream.\n", + 100. * (float)num_bits_to_skip / (float)fabric_bits_by_addr.size(), + num_bits_to_skip, fabric_bits_by_addr.size()); } /* Output information about how to intepret the bitstream */ - fp << "// Bitstream length: " << fabric_bits_by_addr.size() - num_bits_to_skip << std::endl; + fp << "// Bitstream length: " << fabric_bits_by_addr.size() - num_bits_to_skip + << std::endl; fp << "// Bitstream width (LSB -> MSB): "; fp << ""; fp << ""; @@ -161,12 +170,13 @@ int write_memory_bank_fabric_bitstream_to_text_file(std::fstream& fp, for (const auto& addr_din_pair : fabric_bits_by_addr) { /* When fast configuration is enabled, - * the rule to skip any configuration bit should consider the whole data input values. - * Only all the bits in the din port match the value to be skipped, - * the programming cycle can be skipped! + * the rule to skip any configuration bit should consider the whole data + * input values. Only all the bits in the din port match the value to be + * skipped, the programming cycle can be skipped! */ if (true == fast_configuration) { - if (addr_din_pair.second == std::vector(addr_din_pair.second.size(), bit_value_to_skip)) { + if (addr_din_pair.second == + std::vector(addr_din_pair.second.size(), bit_value_to_skip)) { continue; } } @@ -186,28 +196,28 @@ int write_memory_bank_fabric_bitstream_to_text_file(std::fstream& fp, } /******************************************************************** - * Write the fabric bitstream fitting a memory bank protocol - * to a plain text file + * Write the fabric bitstream fitting a memory bank protocol + * to a plain text file * * Return: * - 0 if succeed * - 1 if critical errors occured *******************************************************************/ -static -int write_memory_bank_flatten_fabric_bitstream_to_text_file(std::fstream& fp, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const FabricBitstream& fabric_bitstream, - const bool& keep_dont_care_bits) { +static int write_memory_bank_flatten_fabric_bitstream_to_text_file( + std::fstream& fp, const bool& fast_configuration, + const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream, + const bool& keep_dont_care_bits) { int status = 0; char dont_care_bit = '0'; if (keep_dont_care_bits) { - dont_care_bit = DONT_CARE_CHAR; + dont_care_bit = DONT_CARE_CHAR; } - MemoryBankFlattenFabricBitstream fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip, dont_care_bit); + MemoryBankFlattenFabricBitstream fabric_bits = + build_memory_bank_flatten_fabric_bitstream( + fabric_bitstream, fast_configuration, bit_value_to_skip, dont_care_bit); - /* The address sizes and data input sizes are the same across any element, + /* The address sizes and data input sizes are the same across any element, * just get it from the 1st element to save runtime */ size_t bl_addr_size = fabric_bits.bl_vector_size(); @@ -236,38 +246,41 @@ int write_memory_bank_flatten_fabric_bitstream_to_text_file(std::fstream& fp, } /******************************************************************** - * Write the fabric bitstream fitting a memory bank protocol - * to a plain text file + * Write the fabric bitstream fitting a memory bank protocol + * to a plain text file * * Return: * - 0 if succeed * - 1 if critical errors occured *******************************************************************/ -static -int write_memory_bank_shift_register_fabric_bitstream_to_text_file(std::fstream& fp, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const FabricBitstream& fabric_bitstream, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const bool& keep_dont_care_bits) { +static int write_memory_bank_shift_register_fabric_bitstream_to_text_file( + std::fstream& fp, const bool& fast_configuration, + const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const bool& keep_dont_care_bits) { int status = 0; char dont_care_bit = '0'; if (keep_dont_care_bits) { - dont_care_bit = DONT_CARE_CHAR; + dont_care_bit = DONT_CARE_CHAR; } - MemoryBankShiftRegisterFabricBitstream fabric_bits = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, blwl_sr_banks, fast_configuration, bit_value_to_skip, dont_care_bit); + MemoryBankShiftRegisterFabricBitstream fabric_bits = + build_memory_bank_shift_register_fabric_bitstream( + fabric_bitstream, blwl_sr_banks, fast_configuration, bit_value_to_skip, + dont_care_bit); /* Output information about how to intepret the bitstream */ fp << "// Bitstream word count: " << fabric_bits.num_words() << std::endl; - fp << "// Bitstream bl word size: " << fabric_bits.bl_word_size() << std::endl; - fp << "// Bitstream wl word size: " << fabric_bits.wl_word_size() << std::endl; + fp << "// Bitstream bl word size: " << fabric_bits.bl_word_size() + << std::endl; + fp << "// Bitstream wl word size: " << fabric_bits.wl_word_size() + << std::endl; fp << "// Bitstream width (LSB -> MSB): "; fp << ""; fp << ""; fp << std::endl; - size_t word_cnt = 0; + size_t word_cnt = 0; for (const auto& word : fabric_bits.words()) { fp << "// Word " << word_cnt << std::endl; @@ -293,50 +306,57 @@ int write_memory_bank_shift_register_fabric_bitstream_to_text_file(std::fstream& } /******************************************************************** - * Write the fabric bitstream fitting a frame-based protocol - * to a plain text file + * Write the fabric bitstream fitting a frame-based protocol + * to a plain text file * * Return: * - 0 if succeed * - 1 if critical errors occured *******************************************************************/ -static -int write_frame_based_fabric_bitstream_to_text_file(std::fstream& fp, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const FabricBitstream& fabric_bitstream) { +static int write_frame_based_fabric_bitstream_to_text_file( + std::fstream& fp, const bool& fast_configuration, + const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream) { int status = 0; - FrameFabricBitstream fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream); + FrameFabricBitstream fabric_bits_by_addr = + build_frame_based_fabric_bitstream_by_address(fabric_bitstream); - /* The address sizes and data input sizes are the same across any element, + /* The address sizes and data input sizes are the same across any element, * just get it from the 1st element to save runtime */ - size_t addr_size = fabric_bits_by_addr.begin()->first.size(); - size_t din_size = fabric_bits_by_addr.begin()->second.size(); + size_t addr_size = fabric_bits_by_addr.begin()->first.size(); + size_t din_size = fabric_bits_by_addr.begin()->second.size(); /* Identify and output bitstream size information */ size_t num_bits_to_skip = 0; if (true == fast_configuration) { - num_bits_to_skip = fabric_bits_by_addr.size() - find_frame_based_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); + num_bits_to_skip = + fabric_bits_by_addr.size() - + find_frame_based_fast_configuration_fabric_bitstream_size( + fabric_bitstream, bit_value_to_skip); VTR_ASSERT(num_bits_to_skip < fabric_bits_by_addr.size()); - VTR_LOG("Fast configuration will skip %g% (%lu/%lu) of configuration bitstream.\n", - 100. * (float) num_bits_to_skip / (float) fabric_bits_by_addr.size(), - num_bits_to_skip, fabric_bits_by_addr.size()); + VTR_LOG( + "Fast configuration will skip %g% (%lu/%lu) of configuration " + "bitstream.\n", + 100. * (float)num_bits_to_skip / (float)fabric_bits_by_addr.size(), + num_bits_to_skip, fabric_bits_by_addr.size()); } /* Output information about how to intepret the bitstream */ - fp << "// Bitstream length: " << fabric_bits_by_addr.size() - num_bits_to_skip << std::endl; - fp << "// Bitstream width (LSB -> MSB):
" << std::endl; + fp << "// Bitstream length: " << fabric_bits_by_addr.size() - num_bits_to_skip + << std::endl; + fp << "// Bitstream width (LSB -> MSB):
" << std::endl; for (const auto& addr_din_pair : fabric_bits_by_addr) { /* When fast configuration is enabled, - * the rule to skip any configuration bit should consider the whole data input values. - * Only all the bits in the din port match the value to be skipped, - * the programming cycle can be skipped! + * the rule to skip any configuration bit should consider the whole data + * input values. Only all the bits in the din port match the value to be + * skipped, the programming cycle can be skipped! */ if (true == fast_configuration) { - if (addr_din_pair.second == std::vector(addr_din_pair.second.size(), bit_value_to_skip)) { + if (addr_din_pair.second == + std::vector(addr_din_pair.second.size(), bit_value_to_skip)) { continue; } } @@ -355,33 +375,36 @@ int write_frame_based_fabric_bitstream_to_text_file(std::fstream& fp, } /******************************************************************** - * Write the fabric bitstream to a plain text file - * Notes: + * Write the fabric bitstream to a plain text file + * Notes: * - This is the final bitstream which is loadable to the FPGA fabric * (Verilog netlists etc.) - * - Do NOT include any comments or other characters that the 0|1 bitstream content - * in this file + * - Do NOT include any comments or other characters that the 0|1 bitstream + *content in this file * * Return: * - 0 if succeed * - 1 if critical errors occured *******************************************************************/ -int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const ConfigProtocol& config_protocol, - const FabricGlobalPortInfo& global_ports, - const std::string& fname, - const bool& fast_configuration, - const bool& keep_dont_care_bits, - const bool& include_time_stamp, - const bool& verbose) { +int write_fabric_bitstream_to_text_file( + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const ConfigProtocol& config_protocol, + const FabricGlobalPortInfo& global_ports, const std::string& fname, + const bool& fast_configuration, const bool& keep_dont_care_bits, + const bool& include_time_stamp, const bool& verbose) { /* Ensure that we have a valid file name */ if (true == fname.empty()) { - VTR_LOG_ERROR("Received empty file name to output bitstream!\n\tPlease specify a valid file name.\n"); + VTR_LOG_ERROR( + "Received empty file name to output bitstream!\n\tPlease specify a valid " + "file name.\n"); } - std::string timer_message = std::string("Write ") + std::to_string(fabric_bitstream.num_bits()) + std::string(" fabric bitstream into plain text file '") + fname + std::string("'"); + std::string timer_message = + std::string("Write ") + std::to_string(fabric_bitstream.num_bits()) + + std::string(" fabric bitstream into plain text file '") + fname + + std::string("'"); vtr::ScopedStartFinishTimer timer(timer_message); /* Create the file stream */ @@ -390,17 +413,17 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage check_file_stream(fname.c_str(), fp); - bool apply_fast_configuration = is_fast_configuration_applicable(global_ports) && fast_configuration; + bool apply_fast_configuration = + is_fast_configuration_applicable(global_ports) && fast_configuration; if (fast_configuration && apply_fast_configuration != fast_configuration) { VTR_LOG_WARN("Disable fast configuration even it is enabled by user\n"); } bool bit_value_to_skip = false; if (apply_fast_configuration) { - bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration(config_protocol.type(), - global_ports, - bitstream_manager, - fabric_bitstream); + bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration( + config_protocol.type(), global_ports, bitstream_manager, + fabric_bitstream); } /* Write file head */ @@ -409,78 +432,64 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage /* Output fabric bitstream to the file */ int status = 0; switch (config_protocol.type()) { - case CONFIG_MEM_STANDALONE: - status = write_flatten_fabric_bitstream_to_text_file(fp, - bitstream_manager, - fabric_bitstream); - break; - case CONFIG_MEM_SCAN_CHAIN: - status = write_config_chain_fabric_bitstream_to_text_file(fp, - apply_fast_configuration, - bit_value_to_skip, - bitstream_manager, - fabric_bitstream); - break; - case CONFIG_MEM_QL_MEMORY_BANK: { - /* Bitstream organization depends on the BL/WL protocols - * - If BL uses decoders, we have to config each memory cell one by one. - * - If BL uses flatten, we can configure all the memory cells on the same row by enabling dedicated WL - * In such case, we will merge the BL data under the same WL address - * Fast configuration is applicable when a row of BLs are all zeros/ones while we have a global reset/set for all the memory cells - * - if BL uses shift-register, same as the flatten. - */ - if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { - status = write_memory_bank_fabric_bitstream_to_text_file(fp, - apply_fast_configuration, - bit_value_to_skip, - fabric_bitstream); - } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { - status = write_memory_bank_flatten_fabric_bitstream_to_text_file(fp, - apply_fast_configuration, - bit_value_to_skip, - fabric_bitstream, - keep_dont_care_bits); - } else { - VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); - status = write_memory_bank_shift_register_fabric_bitstream_to_text_file(fp, - apply_fast_configuration, - bit_value_to_skip, + case CONFIG_MEM_STANDALONE: + status = write_flatten_fabric_bitstream_to_text_file( + fp, bitstream_manager, fabric_bitstream); + break; + case CONFIG_MEM_SCAN_CHAIN: + status = write_config_chain_fabric_bitstream_to_text_file( + fp, apply_fast_configuration, bit_value_to_skip, bitstream_manager, + fabric_bitstream); + break; + case CONFIG_MEM_QL_MEMORY_BANK: { + /* Bitstream organization depends on the BL/WL protocols + * - If BL uses decoders, we have to config each memory cell one by one. + * - If BL uses flatten, we can configure all the memory cells on the same + * row by enabling dedicated WL In such case, we will merge the BL data + * under the same WL address Fast configuration is applicable when a row + * of BLs are all zeros/ones while we have a global reset/set for all the + * memory cells + * - if BL uses shift-register, same as the flatten. + */ + if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { + status = write_memory_bank_fabric_bitstream_to_text_file( + fp, apply_fast_configuration, bit_value_to_skip, fabric_bitstream); + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { + status = write_memory_bank_flatten_fabric_bitstream_to_text_file( + fp, apply_fast_configuration, bit_value_to_skip, fabric_bitstream, + keep_dont_care_bits); + } else { + VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == + config_protocol.bl_protocol_type()); + status = write_memory_bank_shift_register_fabric_bitstream_to_text_file( + fp, apply_fast_configuration, bit_value_to_skip, - fabric_bitstream, - blwl_sr_banks, - keep_dont_care_bits); + fabric_bitstream, blwl_sr_banks, keep_dont_care_bits); + } + break; } - break; - } - case CONFIG_MEM_MEMORY_BANK: - status = write_memory_bank_fabric_bitstream_to_text_file(fp, - apply_fast_configuration, - bit_value_to_skip, - fabric_bitstream); - break; - case CONFIG_MEM_FRAME_BASED: - status = write_frame_based_fabric_bitstream_to_text_file(fp, - apply_fast_configuration, - bit_value_to_skip, - fabric_bitstream); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid configuration protocol type!\n"); - status = 1; + case CONFIG_MEM_MEMORY_BANK: + status = write_memory_bank_fabric_bitstream_to_text_file( + fp, apply_fast_configuration, bit_value_to_skip, fabric_bitstream); + break; + case CONFIG_MEM_FRAME_BASED: + status = write_frame_based_fabric_bitstream_to_text_file( + fp, apply_fast_configuration, bit_value_to_skip, fabric_bitstream); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid configuration protocol type!\n"); + status = 1; } - /* Print an end to the file here */ fp << std::endl; /* Close file handler */ fp.close(); - VTR_LOGV(verbose, - "Outputted %lu configuration bits to plain text file: %s\n", - fabric_bitstream.bits().size(), - fname.c_str()); + VTR_LOGV(verbose, "Outputted %lu configuration bits to plain text file: %s\n", + fabric_bitstream.bits().size(), fname.c_str()); return status; } diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h index 78c5b8908..0d8682739 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h @@ -6,11 +6,12 @@ *******************************************************************/ #include #include + #include "bitstream_manager.h" -#include "fabric_bitstream.h" #include "config_protocol.h" -#include "memory_bank_shift_register_banks.h" +#include "fabric_bitstream.h" #include "fabric_global_port_info.h" +#include "memory_bank_shift_register_banks.h" /******************************************************************** * Function declaration @@ -19,16 +20,14 @@ /* begin namespace openfpga */ namespace openfpga { -int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const ConfigProtocol& config_protocol, - const FabricGlobalPortInfo& global_ports, - const std::string& fname, - const bool& fast_configuration, - const bool& keep_dont_care_bits, - const bool& include_time_stamp, - const bool& verbose); +int write_fabric_bitstream_to_text_file( + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const ConfigProtocol& config_protocol, + const FabricGlobalPortInfo& global_ports, const std::string& fname, + const bool& fast_configuration, const bool& keep_dont_care_bits, + const bool& include_time_stamp, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp index b22538bd3..ec8a036fd 100644 --- a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * This file includes functions that output a fabric-dependent + * This file includes functions that output a fabric-dependent * bitstream database to files in XML format *******************************************************************/ #include @@ -16,9 +16,8 @@ /* Headers from archopenfpga library */ -#include "openfpga_naming.h" - #include "bitstream_manager_utils.h" +#include "openfpga_naming.h" #include "write_xml_fabric_bitstream.h" /* begin namespace openfpga */ @@ -27,9 +26,8 @@ namespace openfpga { /******************************************************************** * This function write header information to a bitstream file *******************************************************************/ -static -void write_fabric_bitstream_xml_file_head(std::fstream& fp, - const bool& include_time_stamp) { +static void write_fabric_bitstream_xml_file_head( + std::fstream& fp, const bool& include_time_stamp) { valid_file_stream(fp); fp << "" << std::endl; @@ -60,7 +58,7 @@ void write_fabric_bitstream_xml_file_head(std::fstream& fp, * The format depends on the type of configuration protocol * - Vanilla (standalone): No more information to be included * - Configuration chain: No more information to be included - * - Memory bank : + * - Memory bank : * * * - Frame-based configuration protocol : @@ -70,13 +68,10 @@ void write_fabric_bitstream_xml_file_head(std::fstream& fp, * - 0 if succeed * - 1 if critical errors occured *******************************************************************/ -static -int write_fabric_config_bit_to_xml_file(std::fstream& fp, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const FabricBitId& fabric_bit, - const e_config_protocol_type& config_type, - const int& xml_hierarchy_depth) { +static int write_fabric_config_bit_to_xml_file( + std::fstream& fp, const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream, const FabricBitId& fabric_bit, + const e_config_protocol_type& config_type, const int& xml_hierarchy_depth) { if (false == valid_file_stream(fp)) { return 1; } @@ -89,8 +84,10 @@ int write_fabric_config_bit_to_xml_file(std::fstream& fp, /* Output hierarchy of this parent*/ const ConfigBitId& config_bit = fabric_bitstream.config_bit(fabric_bit); - const ConfigBlockId& config_block = bitstream_manager.bit_parent_block(config_bit); - std::vector block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block); + const ConfigBlockId& config_block = + bitstream_manager.bit_parent_block(config_bit); + std::vector block_hierarchy = + find_bitstream_manager_block_hierarchy(bitstream_manager, config_block); std::string hie_path; for (const ConfigBlockId& temp_block : block_hierarchy) { hie_path += bitstream_manager.block_name(temp_block); @@ -98,46 +95,48 @@ int write_fabric_config_bit_to_xml_file(std::fstream& fp, } hie_path += generate_configurable_memory_data_out_name(); hie_path += std::string("["); - hie_path += std::to_string(find_bitstream_manager_config_bit_index_in_parent_block(bitstream_manager, config_bit)); + hie_path += + std::to_string(find_bitstream_manager_config_bit_index_in_parent_block( + bitstream_manager, config_bit)); hie_path += std::string("]"); fp << " path=\"" << hie_path << "\">\n"; switch (config_type) { - case CONFIG_MEM_STANDALONE: - case CONFIG_MEM_SCAN_CHAIN: - break; - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: { - /* Bit line address */ - write_tab_to_file(fp, xml_hierarchy_depth + 1); - fp << "\n"; + + write_tab_to_file(fp, xml_hierarchy_depth + 1); + fp << "\n"; + break; } - fp << "\"/>\n"; - - write_tab_to_file(fp, xml_hierarchy_depth + 1); - fp << "\n"; + break; } - fp << "\"/>\n"; - break; - } - case CONFIG_MEM_FRAME_BASED: { - write_tab_to_file(fp, xml_hierarchy_depth + 1); - fp << "\n"; - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid configuration protocol type!\n"); - return 1; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid configuration protocol type!\n"); + return 1; } write_tab_to_file(fp, xml_hierarchy_depth); @@ -147,19 +146,17 @@ int write_fabric_config_bit_to_xml_file(std::fstream& fp, } /******************************************************************** - * Write the fabric bitstream in a specific configuration region to an XML file + * Write the fabric bitstream in a specific configuration region to an XML file * * Return: * - 0 if succeed * - 1 if critical errors occured *******************************************************************/ -static -int write_fabric_regional_config_bit_to_xml_file(std::fstream& fp, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const FabricBitRegionId& fabric_region, - const e_config_protocol_type& config_type, - const int& xml_hierarchy_depth) { +static int write_fabric_regional_config_bit_to_xml_file( + std::fstream& fp, const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream, + const FabricBitRegionId& fabric_region, + const e_config_protocol_type& config_type, const int& xml_hierarchy_depth) { if (false == valid_file_stream(fp)) { return 1; } @@ -173,12 +170,11 @@ int write_fabric_regional_config_bit_to_xml_file(std::fstream& fp, fp << "\""; fp << ">\n"; - for (const FabricBitId& fabric_bit : fabric_bitstream.region_bits(fabric_region)) { - status = write_fabric_config_bit_to_xml_file(fp, bitstream_manager, - fabric_bitstream, - fabric_bit, - config_type, - xml_hierarchy_depth + 1); + for (const FabricBitId& fabric_bit : + fabric_bitstream.region_bits(fabric_region)) { + status = write_fabric_config_bit_to_xml_file( + fp, bitstream_manager, fabric_bitstream, fabric_bit, config_type, + xml_hierarchy_depth + 1); if (1 == status) { return status; } @@ -191,8 +187,8 @@ int write_fabric_regional_config_bit_to_xml_file(std::fstream& fp, } /******************************************************************** - * Write the fabric bitstream to an XML file - * Notes: + * Write the fabric bitstream to an XML file + * Notes: * - This file is designed to be reused by testbench generators, e.g., CocoTB * - It can NOT be directly loaded to the FPGA fabric * - It include configurable memory paths in full hierarchy @@ -201,18 +197,21 @@ int write_fabric_regional_config_bit_to_xml_file(std::fstream& fp, * - 0 if succeed * - 1 if critical errors occured *******************************************************************/ -int write_fabric_bitstream_to_xml_file(const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const ConfigProtocol& config_protocol, - const std::string& fname, - const bool& include_time_stamp, - const bool& verbose) { +int write_fabric_bitstream_to_xml_file( + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream, + const ConfigProtocol& config_protocol, const std::string& fname, + const bool& include_time_stamp, const bool& verbose) { /* Ensure that we have a valid file name */ if (true == fname.empty()) { - VTR_LOG_ERROR("Received empty file name to output bitstream!\n\tPlease specify a valid file name.\n"); + VTR_LOG_ERROR( + "Received empty file name to output bitstream!\n\tPlease specify a valid " + "file name.\n"); } - std::string timer_message = std::string("Write ") + std::to_string(fabric_bitstream.num_bits()) + std::string(" fabric bitstream into xml file '") + fname + std::string("'"); + std::string timer_message = + std::string("Write ") + std::to_string(fabric_bitstream.num_bits()) + + std::string(" fabric bitstream into xml file '") + fname + std::string("'"); vtr::ScopedStartFinishTimer timer(timer_message); /* Create the file stream */ @@ -230,11 +229,9 @@ int write_fabric_bitstream_to_xml_file(const BitstreamManager& bitstream_manager /* Output fabric bitstream to the file */ int status = 0; for (const FabricBitRegionId& region : fabric_bitstream.regions()) { - status = write_fabric_regional_config_bit_to_xml_file(fp, bitstream_manager, - fabric_bitstream, - region, - config_protocol.type(), - xml_hierarchy_depth + 1); + status = write_fabric_regional_config_bit_to_xml_file( + fp, bitstream_manager, fabric_bitstream, region, config_protocol.type(), + xml_hierarchy_depth + 1); if (1 == status) { break; } @@ -246,10 +243,8 @@ int write_fabric_bitstream_to_xml_file(const BitstreamManager& bitstream_manager /* Close file handler */ fp.close(); - VTR_LOGV(verbose, - "Outputted %lu configuration bits to XML file: %s\n", - fabric_bitstream.bits().size(), - fname.c_str()); + VTR_LOGV(verbose, "Outputted %lu configuration bits to XML file: %s\n", + fabric_bitstream.bits().size(), fname.c_str()); return status; } diff --git a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.h b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.h index 26673e0c7..ce5b3a384 100644 --- a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.h @@ -6,9 +6,10 @@ *******************************************************************/ #include #include + #include "bitstream_manager.h" -#include "fabric_bitstream.h" #include "config_protocol.h" +#include "fabric_bitstream.h" /******************************************************************** * Function declaration @@ -17,12 +18,11 @@ /* begin namespace openfpga */ namespace openfpga { -int write_fabric_bitstream_to_xml_file(const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const ConfigProtocol& config_protocol, - const std::string& fname, - const bool& include_time_stamp, - const bool& verbose); +int write_fabric_bitstream_to_xml_file( + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream, + const ConfigProtocol& config_protocol, const std::string& fname, + const bool& include_time_stamp, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp b/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp index 1428a6c8d..cedbc9724 100644 --- a/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp +++ b/openfpga/src/fpga_bitstream/write_xml_io_mapping.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * This file includes functions that output io mapping information + * This file includes functions that output io mapping information * to files in XML format *******************************************************************/ #include @@ -15,11 +15,9 @@ #include "openfpga_digest.h" /* Headers from archopenfpga library */ -#include "openfpga_naming.h" - -#include "openfpga_version.h" - #include "build_io_mapping_info.h" +#include "openfpga_naming.h" +#include "openfpga_version.h" #include "write_xml_io_mapping.h" /* begin namespace openfpga */ @@ -28,20 +26,19 @@ namespace openfpga { /******************************************************************** * This function write header information to an I/O mapping file *******************************************************************/ -static -void write_io_mapping_xml_file_head(std::fstream& fp, - const bool& include_time_stamp) { +static void write_io_mapping_xml_file_head(std::fstream& fp, + const bool& include_time_stamp) { valid_file_stream(fp); - + fp << "" << std::endl; @@ -49,17 +46,16 @@ void write_io_mapping_xml_file_head(std::fstream& fp, } /******************************************************************** - * Write an io mapping pair to an XML file + * Write an io mapping pair to an XML file * * Return: * - 0 if succeed * - 1 if critical errors occured *******************************************************************/ -static -int write_io_mapping_pair_to_xml_file(std::fstream& fp, - const IoMap& io_map, - const IoMapId& io_map_id, - int xml_hierarchy_depth) { +static int write_io_mapping_pair_to_xml_file(std::fstream& fp, + const IoMap& io_map, + const IoMapId& io_map_id, + int xml_hierarchy_depth) { if (false == valid_file_stream(fp)) { return 1; } @@ -68,16 +64,22 @@ int write_io_mapping_pair_to_xml_file(std::fstream& fp, BasicPort io_port = io_map.io_port(io_map_id); fp << "\n"; @@ -86,9 +88,9 @@ int write_io_mapping_pair_to_xml_file(std::fstream& fp, } /******************************************************************** - * Write the io mapping information to an XML file - * Notes: - * - This file is designed for users to learn + * Write the io mapping information to an XML file + * Notes: + * - This file is designed for users to learn * - what nets are mapped to each I/O is mapped, io[0] -> netA * - what directionality is applied to each I/O, io[0] -> input * @@ -96,17 +98,19 @@ int write_io_mapping_pair_to_xml_file(std::fstream& fp, * - 0 if succeed * - 1 if critical errors occured *******************************************************************/ -int write_io_mapping_to_xml_file(const IoMap& io_map, - const std::string& fname, +int write_io_mapping_to_xml_file(const IoMap& io_map, const std::string& fname, const bool& include_time_stamp, const bool& verbose) { /* Ensure that we have a valid file name */ if (true == fname.empty()) { - VTR_LOG_ERROR("Received empty file name to output io_mapping!\n\tPlease specify a valid file name.\n"); + VTR_LOG_ERROR( + "Received empty file name to output io_mapping!\n\tPlease specify a " + "valid file name.\n"); return 1; } - std::string timer_message = std::string("Write I/O mapping into xml file '") + fname + std::string("'"); + std::string timer_message = + std::string("Write I/O mapping into xml file '") + fname + std::string("'"); vtr::ScopedStartFinishTimer timer(timer_message); /* Create the file stream */ @@ -125,8 +129,7 @@ int write_io_mapping_to_xml_file(const IoMap& io_map, int status = 0; int io_map_cnt = 0; for (const auto& io_map_id : io_map.io_map()) { - status = write_io_mapping_pair_to_xml_file(fp, - io_map, io_map_id, + status = write_io_mapping_pair_to_xml_file(fp, io_map, io_map_id, xml_hierarchy_depth + 1); io_map_cnt++; if (1 == status) { @@ -137,9 +140,7 @@ int write_io_mapping_to_xml_file(const IoMap& io_map, /* Print an end to the file here */ fp << "\n"; - VTR_LOGV(verbose, - "Outputted %d I/O mapping to file '%s'\n", - io_map_cnt, + VTR_LOGV(verbose, "Outputted %d I/O mapping to file '%s'\n", io_map_cnt, fname.c_str()); /* Close file handler */ diff --git a/openfpga/src/fpga_bitstream/write_xml_io_mapping.h b/openfpga/src/fpga_bitstream/write_xml_io_mapping.h index 1a68cb75a..d6a8eb7ab 100644 --- a/openfpga/src/fpga_bitstream/write_xml_io_mapping.h +++ b/openfpga/src/fpga_bitstream/write_xml_io_mapping.h @@ -6,8 +6,9 @@ *******************************************************************/ #include #include -#include "vpr_context.h" + #include "io_map.h" +#include "vpr_context.h" /******************************************************************** * Function declaration @@ -16,8 +17,7 @@ /* begin namespace openfpga */ namespace openfpga { -int write_io_mapping_to_xml_file(const IoMap& io_map, - const std::string& fname, +int write_io_mapping_to_xml_file(const IoMap& io_map, const std::string& fname, const bool& include_time_stamp, const bool& verbose); diff --git a/openfpga/src/fpga_sdc/analysis_sdc_grid_writer.cpp b/openfpga/src/fpga_sdc/analysis_sdc_grid_writer.cpp index cffa6d4c6..1aeeef090 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_grid_writer.cpp +++ b/openfpga/src/fpga_sdc/analysis_sdc_grid_writer.cpp @@ -10,50 +10,46 @@ #include "openfpga_digest.h" /* Headers from vprutil library */ -#include "vpr_utils.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" - -#include "pb_type_utils.h" +#include "analysis_sdc_grid_writer.h" +#include "analysis_sdc_writer_utils.h" #include "openfpga_device_grid_utils.h" - -#include "sdc_writer_utils.h" -#include "analysis_sdc_writer_utils.h" -#include "analysis_sdc_grid_writer.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "pb_type_utils.h" +#include "sdc_writer_utils.h" +#include "vpr_utils.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * Recursively visit all the pb_types in the hierarchy + * Recursively visit all the pb_types in the hierarchy * and disable all the ports * * Note: it is a must to disable all the ports in all the child pb_types! - * This can prohibit timing analyzer to consider any FF-to-FF path or + * This can prohibit timing analyzer to consider any FF-to-FF path or * combinatinal path inside an unused grid, when finding critical paths!!! *******************************************************************/ -static -void rec_print_analysis_sdc_disable_unused_pb_graph_nodes(std::fstream& fp, - const VprDeviceAnnotation& device_annotation, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const std::string& hierarchy_name, - t_pb_graph_node* physical_pb_graph_node) { +static void rec_print_analysis_sdc_disable_unused_pb_graph_nodes( + std::fstream& fp, const VprDeviceAnnotation& device_annotation, + const ModuleManager& module_manager, const ModuleId& parent_module, + const std::string& hierarchy_name, t_pb_graph_node* physical_pb_graph_node) { t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; /* Validate file stream */ valid_file_stream(fp); - + /* Disable all the ports of current module (parent_module)! - * Hierarchy name already includes the instance name of parent_module + * Hierarchy name already includes the instance name of parent_module */ - fp << "#######################################" << std::endl; - fp << "# Disable all the ports for pb_graph_node " << physical_pb_graph_node->pb_type->name << "[" << physical_pb_graph_node->placement_index << "]" << std::endl; - fp << "#######################################" << std::endl; + fp << "#######################################" << std::endl; + fp << "# Disable all the ports for pb_graph_node " + << physical_pb_graph_node->pb_type->name << "[" + << physical_pb_graph_node->placement_index << "]" << std::endl; + fp << "#######################################" << std::endl; fp << "set_disable_timing "; - fp << hierarchy_name; + fp << hierarchy_name; fp << "*"; fp << std::endl; @@ -65,133 +61,146 @@ void rec_print_analysis_sdc_disable_unused_pb_graph_nodes(std::fstream& fp, /* Go recursively */ t_mode* physical_mode = device_annotation.physical_mode(physical_pb_type); - /* Disable all the ports by iterating over its instance in the parent module */ + /* Disable all the ports by iterating over its instance in the parent module + */ for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { /* Generate the name of the Verilog module for this child */ - std::string child_module_name = generate_physical_block_module_name(&(physical_mode->pb_type_children[ichild])); + std::string child_module_name = generate_physical_block_module_name( + &(physical_mode->pb_type_children[ichild])); ModuleId child_module = module_manager.find_module(child_module_name); VTR_ASSERT(true == module_manager.valid_module_id(child_module)); /* Each child may exist multiple times in the hierarchy*/ - for (int inst = 0; inst < physical_mode->pb_type_children[ichild].num_pb; ++inst) { - std::string child_instance_name = module_manager.instance_name(parent_module, child_module, module_manager.child_module_instances(parent_module, child_module)[inst]); + for (int inst = 0; inst < physical_mode->pb_type_children[ichild].num_pb; + ++inst) { + std::string child_instance_name = + module_manager.instance_name(parent_module, child_module, + module_manager.child_module_instances( + parent_module, child_module)[inst]); /* Must have a valid instance name!!! */ - VTR_ASSERT(false == child_instance_name.empty()); + VTR_ASSERT(false == child_instance_name.empty()); - std::string updated_hierarchy_name = hierarchy_name + child_instance_name + std::string("/"); + std::string updated_hierarchy_name = + hierarchy_name + child_instance_name + std::string("/"); - rec_print_analysis_sdc_disable_unused_pb_graph_nodes(fp, device_annotation, module_manager, child_module, updated_hierarchy_name, - &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ichild][inst])); + rec_print_analysis_sdc_disable_unused_pb_graph_nodes( + fp, device_annotation, module_manager, child_module, + updated_hierarchy_name, + &(physical_pb_graph_node + ->child_pb_graph_nodes[physical_mode->index][ichild][inst])); } } } /******************************************************************** - * Disable an unused pin of a pb_graph_node (parent_module) + * Disable an unused pin of a pb_graph_node (parent_module) *******************************************************************/ -static -void disable_pb_graph_node_unused_pin(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const std::string& hierarchy_name, - const t_pb_graph_pin* pb_graph_pin, - const PhysicalPb& physical_pb, - const PhysicalPbId& pb_id) { +static void disable_pb_graph_node_unused_pin( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& parent_module, const std::string& hierarchy_name, + const t_pb_graph_pin* pb_graph_pin, const PhysicalPb& physical_pb, + const PhysicalPbId& pb_id) { /* Validate file stream */ valid_file_stream(fp); - + /* Identify if the pb_graph_pin has been used or not * TODO: identify if this is a parasitic net - */ - if (AtomNetId::INVALID() != physical_pb.pb_graph_pin_atom_net(pb_id, pb_graph_pin)) { + */ + if (AtomNetId::INVALID() != + physical_pb.pb_graph_pin_atom_net(pb_id, pb_graph_pin)) { /* Used pin; Nothing to do */ return; } - /* Reach here, it means that this pin is not used. Disable timing analysis for the pin */ + /* Reach here, it means that this pin is not used. Disable timing analysis for + * the pin */ /* Find the module port by name */ std::string module_port_name = generate_pb_type_port_name(pb_graph_pin->port); - ModulePortId module_port = module_manager.find_module_port(parent_module, module_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(parent_module, module_port)); - BasicPort port_to_disable = module_manager.module_port(parent_module, module_port); + ModulePortId module_port = + module_manager.find_module_port(parent_module, module_port_name); + VTR_ASSERT(true == + module_manager.valid_module_port_id(parent_module, module_port)); + BasicPort port_to_disable = + module_manager.module_port(parent_module, module_port); port_to_disable.set_width(pb_graph_pin->pin_number, pb_graph_pin->pin_number); fp << "set_disable_timing "; - fp << hierarchy_name; + fp << hierarchy_name; fp << generate_sdc_port(port_to_disable); fp << std::endl; } /******************************************************************** - * Disable unused input ports and output ports of this pb_graph_node (parent_module) - * This function will iterate over all the input pins, output pins - * of the physical_pb_graph_node, and check if they are mapped - * For unused pins, we will find the port in parent_module - * and then print SDC commands to disable them + * Disable unused input ports and output ports of this pb_graph_node + *(parent_module) This function will iterate over all the input pins, output + *pins of the physical_pb_graph_node, and check if they are mapped For unused + *pins, we will find the port in parent_module and then print SDC commands to + *disable them *******************************************************************/ -static -void disable_pb_graph_node_unused_pins(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const std::string& hierarchy_name, - t_pb_graph_node* physical_pb_graph_node, - const PhysicalPb& physical_pb) { +static void disable_pb_graph_node_unused_pins( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& parent_module, const std::string& hierarchy_name, + t_pb_graph_node* physical_pb_graph_node, const PhysicalPb& physical_pb) { const PhysicalPbId& pb_id = physical_pb.find_pb(physical_pb_graph_node); VTR_ASSERT(true == physical_pb.valid_pb_id(pb_id)); - fp << "#######################################" << std::endl; - fp << "# Disable unused pins for pb_graph_node " << physical_pb_graph_node->pb_type->name << "[" << physical_pb_graph_node->placement_index << "]" << std::endl; - fp << "#######################################" << std::endl; + fp << "#######################################" << std::endl; + fp << "# Disable unused pins for pb_graph_node " + << physical_pb_graph_node->pb_type->name << "[" + << physical_pb_graph_node->placement_index << "]" << std::endl; + fp << "#######################################" << std::endl; /* Disable unused input pins */ - for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; ++ipin) { - disable_pb_graph_node_unused_pin(fp, module_manager, parent_module, - hierarchy_name, - &(physical_pb_graph_node->input_pins[iport][ipin]), - physical_pb, pb_id); + for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; + ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; + ++ipin) { + disable_pb_graph_node_unused_pin( + fp, module_manager, parent_module, hierarchy_name, + &(physical_pb_graph_node->input_pins[iport][ipin]), physical_pb, pb_id); } } /* Disable unused output pins */ - for (int iport = 0; iport < physical_pb_graph_node->num_output_ports; ++iport) { - for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; ++ipin) { - disable_pb_graph_node_unused_pin(fp, module_manager, parent_module, - hierarchy_name, - &(physical_pb_graph_node->output_pins[iport][ipin]), - physical_pb, pb_id); + for (int iport = 0; iport < physical_pb_graph_node->num_output_ports; + ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; + ++ipin) { + disable_pb_graph_node_unused_pin( + fp, module_manager, parent_module, hierarchy_name, + &(physical_pb_graph_node->output_pins[iport][ipin]), physical_pb, + pb_id); } } /* Disable unused clock pins */ - for (int iport = 0; iport < physical_pb_graph_node->num_clock_ports; ++iport) { - for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; ++ipin) { - disable_pb_graph_node_unused_pin(fp, module_manager, parent_module, - hierarchy_name, - &(physical_pb_graph_node->clock_pins[iport][ipin]), - physical_pb, pb_id); + for (int iport = 0; iport < physical_pb_graph_node->num_clock_ports; + ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; + ++ipin) { + disable_pb_graph_node_unused_pin( + fp, module_manager, parent_module, hierarchy_name, + &(physical_pb_graph_node->clock_pins[iport][ipin]), physical_pb, pb_id); } } } /******************************************************************** - * Disable unused inputs of routing multiplexers of this pb_graph_node - * This function will first cache the nets for each input and output pins + * Disable unused inputs of routing multiplexers of this pb_graph_node + * This function will first cache the nets for each input and output pins * and store the results in a mux_name-to-net mapping *******************************************************************/ -static -void disable_pb_graph_node_unused_mux_inputs(std::fstream& fp, - const VprDeviceAnnotation& device_annotation, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const std::string& hierarchy_name, - t_pb_graph_node* physical_pb_graph_node, - const PhysicalPb& physical_pb) { - - fp << "#######################################" << std::endl; - fp << "# Disable unused mux_inputs for pb_graph_node " << physical_pb_graph_node->pb_type->name << "[" << physical_pb_graph_node->placement_index << "]" << std::endl; - fp << "#######################################" << std::endl; +static void disable_pb_graph_node_unused_mux_inputs( + std::fstream& fp, const VprDeviceAnnotation& device_annotation, + const ModuleManager& module_manager, const ModuleId& parent_module, + const std::string& hierarchy_name, t_pb_graph_node* physical_pb_graph_node, + const PhysicalPb& physical_pb) { + fp << "#######################################" << std::endl; + fp << "# Disable unused mux_inputs for pb_graph_node " + << physical_pb_graph_node->pb_type->name << "[" + << physical_pb_graph_node->placement_index << "]" << std::endl; + fp << "#######################################" << std::endl; t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; @@ -201,133 +210,178 @@ void disable_pb_graph_node_unused_mux_inputs(std::fstream& fp, /* Cache the nets for each input pins of each child pb_graph_node */ for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { - for (int inst = 0; inst < physical_mode->pb_type_children[ichild].num_pb; ++inst) { - - t_pb_graph_node* child_pb_graph_node = &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ichild][inst]); + for (int inst = 0; inst < physical_mode->pb_type_children[ichild].num_pb; + ++inst) { + t_pb_graph_node* child_pb_graph_node = + &(physical_pb_graph_node + ->child_pb_graph_nodes[physical_mode->index][ichild][inst]); /* Cache the nets for input pins of the child pb_graph_node */ - for (int iport = 0; iport < child_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < child_pb_graph_node->num_input_pins[iport]; ++ipin) { - const PhysicalPbId& pb_id = physical_pb.find_pb(child_pb_graph_node); + for (int iport = 0; iport < child_pb_graph_node->num_input_ports; + ++iport) { + for (int ipin = 0; ipin < child_pb_graph_node->num_input_pins[iport]; + ++ipin) { + const PhysicalPbId& pb_id = physical_pb.find_pb(child_pb_graph_node); VTR_ASSERT(true == physical_pb.valid_pb_id(pb_id)); - /* Generate the mux name */ - std::string mux_instance_name = generate_pb_mux_instance_name(GRID_MUX_INSTANCE_PREFIX, &(child_pb_graph_node->input_pins[iport][ipin]), std::string("")); + /* Generate the mux name */ + std::string mux_instance_name = generate_pb_mux_instance_name( + GRID_MUX_INSTANCE_PREFIX, + &(child_pb_graph_node->input_pins[iport][ipin]), std::string("")); /* Cache the net */ - mux_instance_to_net_map[mux_instance_name] = physical_pb.pb_graph_pin_atom_net(pb_id, &(child_pb_graph_node->input_pins[iport][ipin])); + mux_instance_to_net_map[mux_instance_name] = + physical_pb.pb_graph_pin_atom_net( + pb_id, &(child_pb_graph_node->input_pins[iport][ipin])); } } /* Cache the nets for clock pins of the child pb_graph_node */ - for (int iport = 0; iport < child_pb_graph_node->num_clock_ports; ++iport) { - for (int ipin = 0; ipin < child_pb_graph_node->num_clock_pins[iport]; ++ipin) { - const PhysicalPbId& pb_id = physical_pb.find_pb(child_pb_graph_node); - /* Generate the mux name */ - std::string mux_instance_name = generate_pb_mux_instance_name(GRID_MUX_INSTANCE_PREFIX, &(child_pb_graph_node->clock_pins[iport][ipin]), std::string("")); + for (int iport = 0; iport < child_pb_graph_node->num_clock_ports; + ++iport) { + for (int ipin = 0; ipin < child_pb_graph_node->num_clock_pins[iport]; + ++ipin) { + const PhysicalPbId& pb_id = physical_pb.find_pb(child_pb_graph_node); + /* Generate the mux name */ + std::string mux_instance_name = generate_pb_mux_instance_name( + GRID_MUX_INSTANCE_PREFIX, + &(child_pb_graph_node->clock_pins[iport][ipin]), std::string("")); /* Cache the net */ - mux_instance_to_net_map[mux_instance_name] = physical_pb.pb_graph_pin_atom_net(pb_id, &(child_pb_graph_node->clock_pins[iport][ipin])); + mux_instance_to_net_map[mux_instance_name] = + physical_pb.pb_graph_pin_atom_net( + pb_id, &(child_pb_graph_node->clock_pins[iport][ipin])); } } - } } /* Cache the nets for each output pins of this pb_graph_node */ - for (int iport = 0; iport < physical_pb_graph_node->num_output_ports; ++iport) { - for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; ++ipin) { - const PhysicalPbId& pb_id = physical_pb.find_pb(physical_pb_graph_node); - /* Generate the mux name */ - std::string mux_instance_name = generate_pb_mux_instance_name(GRID_MUX_INSTANCE_PREFIX, &(physical_pb_graph_node->output_pins[iport][ipin]), std::string("")); + for (int iport = 0; iport < physical_pb_graph_node->num_output_ports; + ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; + ++ipin) { + const PhysicalPbId& pb_id = physical_pb.find_pb(physical_pb_graph_node); + /* Generate the mux name */ + std::string mux_instance_name = generate_pb_mux_instance_name( + GRID_MUX_INSTANCE_PREFIX, + &(physical_pb_graph_node->output_pins[iport][ipin]), std::string("")); /* Cache the net */ - mux_instance_to_net_map[mux_instance_name] = physical_pb.pb_graph_pin_atom_net(pb_id, &(physical_pb_graph_node->output_pins[iport][ipin])); + mux_instance_to_net_map[mux_instance_name] = + physical_pb.pb_graph_pin_atom_net( + pb_id, &(physical_pb_graph_node->output_pins[iport][ipin])); } } - /* Now disable unused inputs of routing multiplexers, by tracing from input pins of the parent_module */ - for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; ++ipin) { + /* Now disable unused inputs of routing multiplexers, by tracing from input + * pins of the parent_module */ + for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; + ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; + ++ipin) { /* Find the module port by name */ - std::string module_port_name = generate_pb_type_port_name(physical_pb_graph_node->input_pins[iport][ipin].port); - ModulePortId module_port = module_manager.find_module_port(parent_module, module_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(parent_module, module_port)); + std::string module_port_name = generate_pb_type_port_name( + physical_pb_graph_node->input_pins[iport][ipin].port); + ModulePortId module_port = + module_manager.find_module_port(parent_module, module_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(parent_module, + module_port)); - const PhysicalPbId& pb_id = physical_pb.find_pb(physical_pb_graph_node); - const AtomNetId& mapped_net = physical_pb.pb_graph_pin_atom_net(pb_id, &(physical_pb_graph_node->input_pins[iport][ipin])); + const PhysicalPbId& pb_id = physical_pb.find_pb(physical_pb_graph_node); + const AtomNetId& mapped_net = physical_pb.pb_graph_pin_atom_net( + pb_id, &(physical_pb_graph_node->input_pins[iport][ipin])); /* If the pin has not fan-out, we do not need to disable anything */ - if (0 == physical_pb_graph_node->input_pins[iport][ipin].num_output_edges) { - /* Make sure that we do not have any module net associated to this pin */ - ModuleNetId module_net = module_manager.module_instance_port_net(parent_module, parent_module, 0, module_port, ipin); - VTR_ASSERT(false == module_manager.valid_module_net_id(parent_module, module_net)); + if (0 == + physical_pb_graph_node->input_pins[iport][ipin].num_output_edges) { + /* Make sure that we do not have any module net associated to this pin + */ + ModuleNetId module_net = module_manager.module_instance_port_net( + parent_module, parent_module, 0, module_port, ipin); + VTR_ASSERT(false == module_manager.valid_module_net_id(parent_module, + module_net)); continue; } - disable_analysis_module_input_pin_net_sinks(fp, module_manager, parent_module, - hierarchy_name, - module_port, ipin, - mapped_net, - mux_instance_to_net_map); + disable_analysis_module_input_pin_net_sinks( + fp, module_manager, parent_module, hierarchy_name, module_port, ipin, + mapped_net, mux_instance_to_net_map); } } - for (int iport = 0; iport < physical_pb_graph_node->num_clock_ports; ++iport) { - for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; ++ipin) { + for (int iport = 0; iport < physical_pb_graph_node->num_clock_ports; + ++iport) { + for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; + ++ipin) { /* Find the module port by name */ - std::string module_port_name = generate_pb_type_port_name(physical_pb_graph_node->clock_pins[iport][ipin].port); - ModulePortId module_port = module_manager.find_module_port(parent_module, module_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(parent_module, module_port)); + std::string module_port_name = generate_pb_type_port_name( + physical_pb_graph_node->clock_pins[iport][ipin].port); + ModulePortId module_port = + module_manager.find_module_port(parent_module, module_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(parent_module, + module_port)); - const PhysicalPbId& pb_id = physical_pb.find_pb(physical_pb_graph_node); - const AtomNetId& mapped_net = physical_pb.pb_graph_pin_atom_net(pb_id, &(physical_pb_graph_node->clock_pins[iport][ipin])); + const PhysicalPbId& pb_id = physical_pb.find_pb(physical_pb_graph_node); + const AtomNetId& mapped_net = physical_pb.pb_graph_pin_atom_net( + pb_id, &(physical_pb_graph_node->clock_pins[iport][ipin])); /* If the pin has not fan-out, we do not need to disable anything */ - if (0 == physical_pb_graph_node->clock_pins[iport][ipin].num_output_edges) { - /* Make sure that we do not have any module net associated to this pin */ - ModuleNetId module_net = module_manager.module_instance_port_net(parent_module, parent_module, 0, module_port, ipin); - VTR_ASSERT(false == module_manager.valid_module_net_id(parent_module, module_net)); + if (0 == + physical_pb_graph_node->clock_pins[iport][ipin].num_output_edges) { + /* Make sure that we do not have any module net associated to this pin + */ + ModuleNetId module_net = module_manager.module_instance_port_net( + parent_module, parent_module, 0, module_port, ipin); + VTR_ASSERT(false == module_manager.valid_module_net_id(parent_module, + module_net)); continue; } - disable_analysis_module_input_pin_net_sinks(fp, module_manager, parent_module, - hierarchy_name, - module_port, ipin, - mapped_net, - mux_instance_to_net_map); + disable_analysis_module_input_pin_net_sinks( + fp, module_manager, parent_module, hierarchy_name, module_port, ipin, + mapped_net, mux_instance_to_net_map); } } - /* Now disable unused inputs of routing multiplexers, by tracing from output pins of the child_module */ + /* Now disable unused inputs of routing multiplexers, by tracing from output + * pins of the child_module */ for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { /* Generate the name of the Verilog module for this child */ - std::string child_module_name = generate_physical_block_module_name(&(physical_mode->pb_type_children[ichild])); + std::string child_module_name = generate_physical_block_module_name( + &(physical_mode->pb_type_children[ichild])); ModuleId child_module = module_manager.find_module(child_module_name); VTR_ASSERT(true == module_manager.valid_module_id(child_module)); - for (int inst = 0; inst < physical_mode->pb_type_children[ichild].num_pb; ++inst) { + for (int inst = 0; inst < physical_mode->pb_type_children[ichild].num_pb; + ++inst) { + t_pb_graph_node* child_pb_graph_node = + &(physical_pb_graph_node + ->child_pb_graph_nodes[physical_mode->index][ichild][inst]); - t_pb_graph_node* child_pb_graph_node = &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ichild][inst]); - - for (int iport = 0; iport < child_pb_graph_node->num_output_ports; ++iport) { - for (int ipin = 0; ipin < child_pb_graph_node->num_output_pins[iport]; ++ipin) { + for (int iport = 0; iport < child_pb_graph_node->num_output_ports; + ++iport) { + for (int ipin = 0; ipin < child_pb_graph_node->num_output_pins[iport]; + ++ipin) { /* Find the module port by name */ - std::string module_port_name = generate_pb_type_port_name(child_pb_graph_node->output_pins[iport][ipin].port); - ModulePortId module_port = module_manager.find_module_port(child_module, module_port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(child_module, module_port)); + std::string module_port_name = generate_pb_type_port_name( + child_pb_graph_node->output_pins[iport][ipin].port); + ModulePortId module_port = + module_manager.find_module_port(child_module, module_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(child_module, + module_port)); - const PhysicalPbId& pb_id = physical_pb.find_pb(child_pb_graph_node); - const AtomNetId& mapped_net = physical_pb.pb_graph_pin_atom_net(pb_id, &(child_pb_graph_node->output_pins[iport][ipin])); + const PhysicalPbId& pb_id = physical_pb.find_pb(child_pb_graph_node); + const AtomNetId& mapped_net = physical_pb.pb_graph_pin_atom_net( + pb_id, &(child_pb_graph_node->output_pins[iport][ipin])); - /* Corner case: if the pb_graph_pin has no fan-out we will skip this pin */ - if (0 == child_pb_graph_node->output_pins[iport][ipin].num_output_edges) { + /* Corner case: if the pb_graph_pin has no fan-out we will skip this + * pin */ + if (0 == + child_pb_graph_node->output_pins[iport][ipin].num_output_edges) { continue; } - disable_analysis_module_output_pin_net_sinks(fp, module_manager, parent_module, - hierarchy_name, - child_module, inst, - module_port, ipin, - mapped_net, - mux_instance_to_net_map); + disable_analysis_module_output_pin_net_sinks( + fp, module_manager, parent_module, hierarchy_name, child_module, + inst, module_port, ipin, mapped_net, mux_instance_to_net_map); } } } @@ -335,21 +389,21 @@ void disable_pb_graph_node_unused_mux_inputs(std::fstream& fp, } /******************************************************************** - * Recursively visit all the pb_types in the hierarchy + * Recursively visit all the pb_types in the hierarchy * and disable all the unused resources, including: * 1. input ports * 2. output ports * 3. unused inputs of routing multiplexers * - * As this function is executed in a recursive way. + * As this function is executed in a recursive way. * To avoid repeated disable timing for ports, during each run of this function, - * only the unused input ports, output ports of the parent module will be disabled. - * In addition, we will cache all the net ids mapped to the input ports of - * child modules, and the net ids mapped to the output ports of parent module. - * As such, we can trace from - * 1. the input ports of parent module to disable unused inputs of routing multiplexer - * which drives the inputs of child modules - * + * only the unused input ports, output ports of the parent module will be + *disabled. In addition, we will cache all the net ids mapped to the input ports + *of child modules, and the net ids mapped to the output ports of parent module. + * As such, we can trace from + * 1. the input ports of parent module to disable unused inputs of routing + *multiplexer which drives the inputs of child modules + * * Parent_module * +--------------------------------------------- * | MUX child_module @@ -359,10 +413,10 @@ void disable_pb_graph_node_unused_mux_inputs(std::fstream& fp, * | +-------------+ | * | | * - * 2. the output ports of child module to disable unused inputs of routing multiplexer - * which drives the outputs of parent modules + * 2. the output ports of child module to disable unused inputs of routing + *multiplexer which drives the outputs of parent modules * - * Case 1: + * Case 1: * parent_module * --------------------------------------+ * child_module | @@ -372,7 +426,7 @@ void disable_pb_graph_node_unused_mux_inputs(std::fstream& fp, * output_pin1 (netB) |-x->| Multiplexer | netA | * | +-------------+ | * - * Case 2: + * Case 2: * * Parent_module * +--------------------------------------------- @@ -387,60 +441,69 @@ void disable_pb_graph_node_unused_mux_inputs(std::fstream& fp, * * * Note: it is a must to disable all the ports in all the child pb_types! - * This can prohibit timing analyzer to consider any FF-to-FF path or + * This can prohibit timing analyzer to consider any FF-to-FF path or * combinatinal path inside an unused grid, when finding critical paths!!! *******************************************************************/ -static -void rec_print_analysis_sdc_disable_pb_graph_node_unused_resources(std::fstream& fp, - const VprDeviceAnnotation& device_annotation, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const std::string& hierarchy_name, - t_pb_graph_node* physical_pb_graph_node, - const PhysicalPb& physical_pb) { +static void rec_print_analysis_sdc_disable_pb_graph_node_unused_resources( + std::fstream& fp, const VprDeviceAnnotation& device_annotation, + const ModuleManager& module_manager, const ModuleId& parent_module, + const std::string& hierarchy_name, t_pb_graph_node* physical_pb_graph_node, + const PhysicalPb& physical_pb) { t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; - /* Disable unused input ports and output ports of this pb_graph_node (parent_module) */ + /* Disable unused input ports and output ports of this pb_graph_node + * (parent_module) */ disable_pb_graph_node_unused_pins(fp, module_manager, parent_module, - hierarchy_name, physical_pb_graph_node, physical_pb); + hierarchy_name, physical_pb_graph_node, + physical_pb); - /* Return if this is the primitive pb_type - * Note: this must return before we disable any unused inputs of routing multiplexer! - * This is due to that primitive pb_type does NOT contain any routing multiplexers inside!!! + /* Return if this is the primitive pb_type + * Note: this must return before we disable any unused inputs of routing + * multiplexer! This is due to that primitive pb_type does NOT contain any + * routing multiplexers inside!!! */ if (true == is_primitive_pb_type(physical_pb_type)) { return; } /* Disable unused inputs of routing multiplexers of this pb_graph_node */ - disable_pb_graph_node_unused_mux_inputs(fp, device_annotation, - module_manager, parent_module, - hierarchy_name, physical_pb_graph_node, - physical_pb); - + disable_pb_graph_node_unused_mux_inputs(fp, device_annotation, module_manager, + parent_module, hierarchy_name, + physical_pb_graph_node, physical_pb); t_mode* physical_mode = device_annotation.physical_mode(physical_pb_type); - /* Disable all the ports by iterating over its instance in the parent module */ + /* Disable all the ports by iterating over its instance in the parent module + */ for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { /* Generate the name of the Verilog module for this child */ - std::string child_module_name = generate_physical_block_module_name(&(physical_mode->pb_type_children[ichild])); + std::string child_module_name = generate_physical_block_module_name( + &(physical_mode->pb_type_children[ichild])); ModuleId child_module = module_manager.find_module(child_module_name); VTR_ASSERT(true == module_manager.valid_module_id(child_module)); /* Each child may exist multiple times in the hierarchy*/ - for (int inst = 0; inst < physical_pb_type->modes[physical_mode->index].pb_type_children[ichild].num_pb; ++inst) { - std::string child_instance_name = module_manager.instance_name(parent_module, child_module, module_manager.child_module_instances(parent_module, child_module)[inst]); + for (int inst = 0; inst < physical_pb_type->modes[physical_mode->index] + .pb_type_children[ichild] + .num_pb; + ++inst) { + std::string child_instance_name = + module_manager.instance_name(parent_module, child_module, + module_manager.child_module_instances( + parent_module, child_module)[inst]); /* Must have a valid instance name!!! */ - VTR_ASSERT(false == child_instance_name.empty()); + VTR_ASSERT(false == child_instance_name.empty()); - std::string updated_hierarchy_name = hierarchy_name + child_instance_name + std::string("/"); + std::string updated_hierarchy_name = + hierarchy_name + child_instance_name + std::string("/"); - rec_print_analysis_sdc_disable_pb_graph_node_unused_resources(fp, device_annotation, - module_manager, child_module, updated_hierarchy_name, - &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ichild][inst]), - physical_pb); + rec_print_analysis_sdc_disable_pb_graph_node_unused_resources( + fp, device_annotation, module_manager, child_module, + updated_hierarchy_name, + &(physical_pb_graph_node + ->child_pb_graph_nodes[physical_mode->index][ichild][inst]), + physical_pb); } } } @@ -451,71 +514,78 @@ void rec_print_analysis_sdc_disable_pb_graph_node_unused_resources(std::fstream& * --------------------------------- * Disable the timing for only unused resources in a physical block * We have to walk through pb_graph node, port by port and pin by pin. - * Identify which pins have not been used, and then disable the timing - * for these ports. + * Identify which pins have not been used, and then disable the timing + * for these ports. * Plus, for input ports, we will trace the routing multiplexers * and disable the timing for unused inputs. * * 2. For fully unused pb_blocks - * ----------------------------- + * ----------------------------- * Disable the timing for a fully unused grid! * This is very straightforward! * Just walk through each pb_type and disable all the ports using wildcards *******************************************************************/ -static -void print_analysis_sdc_disable_pb_block_unused_resources(std::fstream& fp, - t_physical_tile_type_ptr grid_type, - const vtr::Point& grid_coordinate, - const VprDeviceAnnotation& device_annotation, - const ModuleManager& module_manager, - const std::string& grid_instance_name, - const size_t& grid_z, - const PhysicalPb& physical_pb, - const bool& unused_block) { +static void print_analysis_sdc_disable_pb_block_unused_resources( + std::fstream& fp, t_physical_tile_type_ptr grid_type, + const vtr::Point& grid_coordinate, + const VprDeviceAnnotation& device_annotation, + const ModuleManager& module_manager, const std::string& grid_instance_name, + const size_t& grid_z, const PhysicalPb& physical_pb, + const bool& unused_block) { /* If the block is partially unused, we should have a physical pb */ if (false == unused_block) { VTR_ASSERT(false == physical_pb.empty()); } - int sub_tile_index = device_annotation.physical_tile_z_to_subtile_index(grid_type, grid_z); + int sub_tile_index = + device_annotation.physical_tile_z_to_subtile_index(grid_type, grid_z); VTR_ASSERT(1 == grid_type->sub_tiles[sub_tile_index].equivalent_sites.size()); - t_pb_graph_node* pb_graph_head = grid_type->sub_tiles[sub_tile_index].equivalent_sites[0]->pb_graph_head; + t_pb_graph_node* pb_graph_head = + grid_type->sub_tiles[sub_tile_index].equivalent_sites[0]->pb_graph_head; VTR_ASSERT(nullptr != pb_graph_head); /* Find an unique name to the pb instance in this grid - * Note: this must be consistent with the instance name we used in build_grid_module()!!! + * Note: this must be consistent with the instance name we used in + * build_grid_module()!!! */ /* TODO: validate that the instance name is used in module manager!!! */ - std::string pb_module_name = generate_physical_block_module_name(pb_graph_head->pb_type); - std::string pb_instance_name = generate_physical_block_instance_name(pb_graph_head->pb_type, grid_z); + std::string pb_module_name = + generate_physical_block_module_name(pb_graph_head->pb_type); + std::string pb_instance_name = + generate_physical_block_instance_name(pb_graph_head->pb_type, grid_z); ModuleId pb_module = module_manager.find_module(pb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); /* Print comments */ - fp << "#######################################" << std::endl; - + fp << "#######################################" << std::endl; + if (true == unused_block) { - fp << "# Disable Timing for unused grid[" << grid_coordinate.x() << "][" << grid_coordinate.y() << "][" << grid_z << "]" << std::endl; + fp << "# Disable Timing for unused grid[" << grid_coordinate.x() << "][" + << grid_coordinate.y() << "][" << grid_z << "]" << std::endl; } else { VTR_ASSERT_SAFE(false == unused_block); - fp << "# Disable Timing for unused resources in grid[" << grid_coordinate.x() << "][" << grid_coordinate.y() << "][" << grid_z << "]" << std::endl; + fp << "# Disable Timing for unused resources in grid[" + << grid_coordinate.x() << "][" << grid_coordinate.y() << "][" << grid_z + << "]" << std::endl; } - fp << "#######################################" << std::endl; + fp << "#######################################" << std::endl; - std::string hierarchy_name = grid_instance_name + std::string("/") + pb_instance_name + std::string("/"); + std::string hierarchy_name = + grid_instance_name + std::string("/") + pb_instance_name + std::string("/"); - /* Go recursively through the pb_graph hierarchy, and disable all the ports level by level */ + /* Go recursively through the pb_graph hierarchy, and disable all the ports + * level by level */ if (true == unused_block) { - rec_print_analysis_sdc_disable_unused_pb_graph_nodes(fp, device_annotation, - module_manager, pb_module, hierarchy_name, - pb_graph_head); - } else { + rec_print_analysis_sdc_disable_unused_pb_graph_nodes( + fp, device_annotation, module_manager, pb_module, hierarchy_name, + pb_graph_head); + } else { VTR_ASSERT_SAFE(false == unused_block); - rec_print_analysis_sdc_disable_pb_graph_node_unused_resources(fp, device_annotation, - module_manager, pb_module, hierarchy_name, - pb_graph_head, physical_pb); + rec_print_analysis_sdc_disable_pb_graph_node_unused_resources( + fp, device_annotation, module_manager, pb_module, hierarchy_name, + pb_graph_head, physical_pb); } } @@ -524,77 +594,80 @@ void print_analysis_sdc_disable_pb_block_unused_resources(std::fstream& fp, * This is very straightforward! * Just walk through each pb_type and disable all the ports using wildcards *******************************************************************/ -static -void print_analysis_sdc_disable_unused_grid(std::fstream& fp, - const vtr::Point& grid_coordinate, - const DeviceGrid& grids, - const VprDeviceAnnotation& device_annotation, - const VprClusteringAnnotation& cluster_annotation, - const VprPlacementAnnotation& place_annotation, - const ModuleManager& module_manager, - const e_side& border_side) { +static void print_analysis_sdc_disable_unused_grid( + std::fstream& fp, const vtr::Point& grid_coordinate, + const DeviceGrid& grids, const VprDeviceAnnotation& device_annotation, + const VprClusteringAnnotation& cluster_annotation, + const VprPlacementAnnotation& place_annotation, + const ModuleManager& module_manager, const e_side& border_side) { /* Validate file stream */ valid_file_stream(fp); - t_physical_tile_type_ptr grid_type = grids[grid_coordinate.x()][grid_coordinate.y()].type; - /* Bypass conditions for grids : + t_physical_tile_type_ptr grid_type = + grids[grid_coordinate.x()][grid_coordinate.y()].type; + /* Bypass conditions for grids : * 1. EMPTY type, which is by nature unused * 2. Offset > 0, which has already been processed when offset = 0 */ - if ( (true == is_empty_type(grid_type)) - || (0 < grids[grid_coordinate.x()][grid_coordinate.y()].width_offset) - || (0 < grids[grid_coordinate.x()][grid_coordinate.y()].height_offset) ) { + if ((true == is_empty_type(grid_type)) || + (0 < grids[grid_coordinate.x()][grid_coordinate.y()].width_offset) || + (0 < grids[grid_coordinate.x()][grid_coordinate.y()].height_offset)) { return; } /* Find an unique name to the grid instane - * Note: this must be consistent with the instance name we used in build_top_module()!!! + * Note: this must be consistent with the instance name we used in + * build_top_module()!!! */ /* TODO: validate that the instance name is used in module manager!!! */ std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); - std::string grid_module_name = generate_grid_block_module_name(grid_module_name_prefix, std::string(grid_type->name), is_io_type(grid_type), border_side); - std::string grid_instance_name = generate_grid_block_instance_name(grid_module_name_prefix, std::string(grid_type->name), is_io_type(grid_type), border_side, grid_coordinate); + std::string grid_module_name = generate_grid_block_module_name( + grid_module_name_prefix, std::string(grid_type->name), + is_io_type(grid_type), border_side); + std::string grid_instance_name = generate_grid_block_instance_name( + grid_module_name_prefix, std::string(grid_type->name), + is_io_type(grid_type), border_side, grid_coordinate); ModuleId grid_module = module_manager.find_module(grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); /* Print comments */ - fp << "#######################################" << std::endl; - fp << "# Disable Timing for grid[" << grid_coordinate.x() << "][" << grid_coordinate.y() << "]" << std::endl; - fp << "#######################################" << std::endl; + fp << "#######################################" << std::endl; + fp << "# Disable Timing for grid[" << grid_coordinate.x() << "][" + << grid_coordinate.y() << "]" << std::endl; + fp << "#######################################" << std::endl; - /* For used grid, find the unused rr_node in the local rr_graph + /* For used grid, find the unused rr_node in the local rr_graph * and then disable each port which is not used * as well as the unused inputs of routing multiplexers! */ size_t grid_z = 0; - for (const ClusterBlockId& blk_id : place_annotation.grid_blocks(grid_coordinate)) { - if (ClusterBlockId::INVALID() != blk_id) { + for (const ClusterBlockId& blk_id : + place_annotation.grid_blocks(grid_coordinate)) { + if (ClusterBlockId::INVALID() != blk_id) { const PhysicalPb& physical_pb = cluster_annotation.physical_pb(blk_id); - print_analysis_sdc_disable_pb_block_unused_resources(fp, grid_type, grid_coordinate, - device_annotation, - module_manager, grid_instance_name, grid_z, - physical_pb, false); + print_analysis_sdc_disable_pb_block_unused_resources( + fp, grid_type, grid_coordinate, device_annotation, module_manager, + grid_instance_name, grid_z, physical_pb, false); } else { VTR_ASSERT(ClusterBlockId::INVALID() == blk_id); /* For unused grid, disable all the pins in the physical_pb_type */ - print_analysis_sdc_disable_pb_block_unused_resources(fp, grid_type, grid_coordinate, - device_annotation, - module_manager, grid_instance_name, grid_z, - PhysicalPb(), true); + print_analysis_sdc_disable_pb_block_unused_resources( + fp, grid_type, grid_coordinate, device_annotation, module_manager, + grid_instance_name, grid_z, PhysicalPb(), true); } grid_z++; } } /******************************************************************** - * Top-level function writes SDC commands to disable unused ports + * Top-level function writes SDC commands to disable unused ports * of grids, such as Configurable Logic Block (CLBs), heterogeneous blocks, etc. * * This function will iterate over all the grids available in the FPGA fabric * It will disable the timing analysis for * 1. Grids, which are totally not used (no logic has been mapped to) - * 2. Unused part of grids, including the ports, inputs of routing multiplexers + * 2. Unused part of grids, including the ports, inputs of routing multiplexers * * Note that it is a must to disable the unused inputs of routing multiplexers * because it will cause unexpected paths in timing analysis @@ -609,32 +682,32 @@ void print_analysis_sdc_disable_unused_grid(std::fstream& fp, * while the path from inputB to output should NOT be considered!!! * *******************************************************************/ -void print_analysis_sdc_disable_unused_grids(std::fstream& fp, - const DeviceGrid& grids, - const VprDeviceAnnotation& device_annotation, - const VprClusteringAnnotation& cluster_annotation, - const VprPlacementAnnotation& place_annotation, - const ModuleManager& module_manager) { - +void print_analysis_sdc_disable_unused_grids( + std::fstream& fp, const DeviceGrid& grids, + const VprDeviceAnnotation& device_annotation, + const VprClusteringAnnotation& cluster_annotation, + const VprPlacementAnnotation& place_annotation, + const ModuleManager& module_manager) { /* Process unused core grids */ for (size_t ix = 1; ix < grids.width() - 1; ++ix) { for (size_t iy = 1; iy < grids.height() - 1; ++iy) { - print_analysis_sdc_disable_unused_grid(fp, vtr::Point(ix, iy), - grids, device_annotation, cluster_annotation, place_annotation, - module_manager, NUM_SIDES); + print_analysis_sdc_disable_unused_grid( + fp, vtr::Point(ix, iy), grids, device_annotation, + cluster_annotation, place_annotation, module_manager, NUM_SIDES); } } /* Instanciate I/O grids */ /* Create the coordinate range for each side of FPGA fabric */ - std::map>> io_coordinates = generate_perimeter_grid_coordinates( grids); + std::map>> io_coordinates = + generate_perimeter_grid_coordinates(grids); /* Add instances of I/O grids to top_module */ for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { for (const vtr::Point& io_coordinate : io_coordinates[io_side]) { - print_analysis_sdc_disable_unused_grid(fp, io_coordinate, - grids, device_annotation, cluster_annotation, place_annotation, - module_manager, io_side); + print_analysis_sdc_disable_unused_grid( + fp, io_coordinate, grids, device_annotation, cluster_annotation, + place_annotation, module_manager, io_side); } } } diff --git a/openfpga/src/fpga_sdc/analysis_sdc_grid_writer.h b/openfpga/src/fpga_sdc/analysis_sdc_grid_writer.h index be01bbf28..dbd798944 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_grid_writer.h +++ b/openfpga/src/fpga_sdc/analysis_sdc_grid_writer.h @@ -6,10 +6,11 @@ *******************************************************************/ #include #include + #include "device_grid.h" #include "module_manager.h" -#include "vpr_device_annotation.h" #include "vpr_clustering_annotation.h" +#include "vpr_device_annotation.h" #include "vpr_placement_annotation.h" /******************************************************************** @@ -19,12 +20,12 @@ /* begin namespace openfpga */ namespace openfpga { -void print_analysis_sdc_disable_unused_grids(std::fstream& fp, - const DeviceGrid& grids, - const VprDeviceAnnotation& device_annotation, - const VprClusteringAnnotation& cluster_annotation, - const VprPlacementAnnotation& place_annotation, - const ModuleManager& module_manager); +void print_analysis_sdc_disable_unused_grids( + std::fstream& fp, const DeviceGrid& grids, + const VprDeviceAnnotation& device_annotation, + const VprClusteringAnnotation& cluster_annotation, + const VprPlacementAnnotation& place_annotation, + const ModuleManager& module_manager); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/analysis_sdc_option.cpp b/openfpga/src/fpga_sdc/analysis_sdc_option.cpp index 70c9a60cb..bd0aa77bc 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_option.cpp +++ b/openfpga/src/fpga_sdc/analysis_sdc_option.cpp @@ -1,5 +1,6 @@ /******************************************************************** - * Member functions for a data structure which includes all the options for the SDC generator + * Member functions for a data structure which includes all the options for the + *SDC generator ********************************************************************/ #include "analysis_sdc_option.h" @@ -20,21 +21,13 @@ AnalysisSdcOption::AnalysisSdcOption(const std::string& sdc_dir) { /******************************************************************** * Public accessors ********************************************************************/ -std::string AnalysisSdcOption::sdc_dir() const { - return sdc_dir_; -} +std::string AnalysisSdcOption::sdc_dir() const { return sdc_dir_; } -bool AnalysisSdcOption::flatten_names() const { - return flatten_names_; -} +bool AnalysisSdcOption::flatten_names() const { return flatten_names_; } -float AnalysisSdcOption::time_unit() const { - return time_unit_; -} +float AnalysisSdcOption::time_unit() const { return time_unit_; } -bool AnalysisSdcOption::time_stamp() const { - return time_stamp_; -} +bool AnalysisSdcOption::time_stamp() const { return time_stamp_; } bool AnalysisSdcOption::generate_sdc_analysis() const { return generate_sdc_analysis_; @@ -59,7 +52,8 @@ void AnalysisSdcOption::set_time_stamp(const bool& enable) { time_stamp_ = enable; } -void AnalysisSdcOption::set_generate_sdc_analysis(const bool& generate_sdc_analysis) { +void AnalysisSdcOption::set_generate_sdc_analysis( + const bool& generate_sdc_analysis) { generate_sdc_analysis_ = generate_sdc_analysis; } diff --git a/openfpga/src/fpga_sdc/analysis_sdc_option.h b/openfpga/src/fpga_sdc/analysis_sdc_option.h index 654dc46b5..2b7829457 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_option.h +++ b/openfpga/src/fpga_sdc/analysis_sdc_option.h @@ -12,26 +12,29 @@ namespace openfpga { class AnalysisSdcOption { - public: /* Public Constructors */ - AnalysisSdcOption(const std::string& sdc_dir); - public: /* Public accessors */ - std::string sdc_dir() const; - bool flatten_names() const; - float time_unit() const; - bool generate_sdc_analysis() const; - bool time_stamp() const; - public: /* Public mutators */ - void set_sdc_dir(const std::string& sdc_dir); - void set_flatten_names(const bool& flatten_names); - void set_time_stamp(const bool& time_stamp); - void set_time_unit(const float& time_unit); - void set_generate_sdc_analysis(const bool& generate_sdc_analysis); - private: /* Internal data */ - std::string sdc_dir_; - bool generate_sdc_analysis_; - bool flatten_names_; - float time_unit_; - bool time_stamp_; + public: /* Public Constructors */ + AnalysisSdcOption(const std::string& sdc_dir); + + public: /* Public accessors */ + std::string sdc_dir() const; + bool flatten_names() const; + float time_unit() const; + bool generate_sdc_analysis() const; + bool time_stamp() const; + + public: /* Public mutators */ + void set_sdc_dir(const std::string& sdc_dir); + void set_flatten_names(const bool& flatten_names); + void set_time_stamp(const bool& time_stamp); + void set_time_unit(const float& time_unit); + void set_generate_sdc_analysis(const bool& generate_sdc_analysis); + + private: /* Internal data */ + std::string sdc_dir_; + bool generate_sdc_analysis_; + bool flatten_names_; + float time_unit_; + bool time_stamp_; }; } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp b/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp index 040a792aa..b9e4c974b 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp +++ b/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp @@ -1,7 +1,7 @@ /******************************************************************** * This file includes functions that are used to output a SDC file - * that constrain routing modules of a FPGA fabric (P&Red netlist) - * using a benchmark + * that constrain routing modules of a FPGA fabric (P&Red netlist) + * using a benchmark *******************************************************************/ #include @@ -9,85 +9,90 @@ #include "vtr_assert.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" -#include "openfpga_side_manager.h" -#include "openfpga_port.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" -#include "openfpga_rr_graph_utils.h" - -#include "build_routing_module_utils.h" -#include "sdc_writer_utils.h" -#include "analysis_sdc_writer_utils.h" #include "analysis_sdc_routing_writer.h" +#include "analysis_sdc_writer_utils.h" +#include "build_routing_module_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" +#include "openfpga_reserved_words.h" +#include "openfpga_rr_graph_utils.h" +#include "openfpga_side_manager.h" +#include "sdc_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * This function will disable + * This function will disable * 1. all the unused port (unmapped by a benchmark) of a connection block - * 2. all the unused inputs (unmapped by a benchmark) of routing multiplexers + * 2. all the unused inputs (unmapped by a benchmark) of routing multiplexers * in a connection block *******************************************************************/ -static -void print_analysis_sdc_disable_cb_unused_resources(std::fstream& fp, - const AtomContext& atom_ctx, - const ModuleManager& module_manager, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const VprRoutingAnnotation& routing_annotation, - const DeviceRRGSB& device_rr_gsb, - const RRGSB& rr_gsb, - const t_rr_type& cb_type, - const bool& compact_routing_hierarchy) { +static void print_analysis_sdc_disable_cb_unused_resources( + std::fstream& fp, const AtomContext& atom_ctx, + const ModuleManager& module_manager, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const VprRoutingAnnotation& routing_annotation, + const DeviceRRGSB& device_rr_gsb, const RRGSB& rr_gsb, + const t_rr_type& cb_type, const bool& compact_routing_hierarchy) { /* Validate file stream */ valid_file_stream(fp); - vtr::Point gsb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); + vtr::Point gsb_coordinate(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); - std::string cb_instance_name = generate_connection_block_module_name(cb_type, gsb_coordinate); + std::string cb_instance_name = + generate_connection_block_module_name(cb_type, gsb_coordinate); - /* If we use the compact routing hierarchy, we need to find the module name !*/ - vtr::Point cb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); + /* If we use the compact routing hierarchy, we need to find the module name + * !*/ + vtr::Point cb_coordinate(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); if (true == compact_routing_hierarchy) { vtr::Point cb_coord(rr_gsb.get_x(), rr_gsb.get_y()); /* Note: use GSB coordinate when inquire for unique modules!!! */ - const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(cb_type, cb_coord); - cb_coordinate.set_x(unique_mirror.get_cb_x(cb_type)); - cb_coordinate.set_y(unique_mirror.get_cb_y(cb_type)); + const RRGSB& unique_mirror = + device_rr_gsb.get_cb_unique_module(cb_type, cb_coord); + cb_coordinate.set_x(unique_mirror.get_cb_x(cb_type)); + cb_coordinate.set_y(unique_mirror.get_cb_y(cb_type)); } - std::string cb_module_name = generate_connection_block_module_name(cb_type, cb_coordinate); + std::string cb_module_name = + generate_connection_block_module_name(cb_type, cb_coordinate); ModuleId cb_module = module_manager.find_module(cb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); /* Print comments */ - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; fp << "# Disable timing for Connection block " << cb_module_name << std::endl; - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; - /* Disable all the input port (routing tracks), which are not used by benchmark */ - for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); ++itrack) { - const RRNodeId& chan_node = rr_gsb.get_chan_node(rr_gsb.get_cb_chan_side(cb_type), itrack); + /* Disable all the input port (routing tracks), which are not used by + * benchmark */ + for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); + ++itrack) { + const RRNodeId& chan_node = + rr_gsb.get_chan_node(rr_gsb.get_cb_chan_side(cb_type), itrack); /* Check if this node is used by benchmark */ - if (false == is_rr_node_to_be_disable_for_analysis(routing_annotation, chan_node)) { + if (false == + is_rr_node_to_be_disable_for_analysis(routing_annotation, chan_node)) { continue; } /* Disable both input of the routing track if it is not used! */ - std::string port_name = generate_cb_module_track_port_name(cb_type, - IN_PORT, - 0 == itrack % 2); + std::string port_name = + generate_cb_module_track_port_name(cb_type, IN_PORT, 0 == itrack % 2); /* Ensure we have this port in the module! */ - ModulePortId module_port = module_manager.find_module_port(cb_module, port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module, module_port)); - BasicPort chan_port(module_manager.module_port(cb_module, module_port).get_name(), - itrack / 2, itrack / 2); + ModulePortId module_port = + module_manager.find_module_port(cb_module, port_name); + VTR_ASSERT(true == + module_manager.valid_module_port_id(cb_module, module_port)); + BasicPort chan_port( + module_manager.module_port(cb_module, module_port).get_name(), itrack / 2, + itrack / 2); fp << "set_disable_timing "; fp << cb_instance_name << "/"; @@ -95,24 +100,30 @@ void print_analysis_sdc_disable_cb_unused_resources(std::fstream& fp, fp << std::endl; } - /* Disable all the output port (routing tracks), which are not used by benchmark */ - for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); ++itrack) { - const RRNodeId& chan_node = rr_gsb.get_chan_node(rr_gsb.get_cb_chan_side(cb_type), itrack); + /* Disable all the output port (routing tracks), which are not used by + * benchmark */ + for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); + ++itrack) { + const RRNodeId& chan_node = + rr_gsb.get_chan_node(rr_gsb.get_cb_chan_side(cb_type), itrack); /* Check if this node is used by benchmark */ - if (false == is_rr_node_to_be_disable_for_analysis(routing_annotation, chan_node)) { + if (false == + is_rr_node_to_be_disable_for_analysis(routing_annotation, chan_node)) { continue; } /* Disable both input of the routing track if it is not used! */ - std::string port_name = generate_cb_module_track_port_name(cb_type, - OUT_PORT, - 0 == itrack % 2); + std::string port_name = + generate_cb_module_track_port_name(cb_type, OUT_PORT, 0 == itrack % 2); /* Ensure we have this port in the module! */ - ModulePortId module_port = module_manager.find_module_port(cb_module, port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module, module_port)); - BasicPort chan_port(module_manager.module_port(cb_module, module_port).get_name(), - itrack / 2, itrack / 2); + ModulePortId module_port = + module_manager.find_module_port(cb_module, port_name); + VTR_ASSERT(true == + module_manager.valid_module_port_id(cb_module, module_port)); + BasicPort chan_port( + module_manager.module_port(cb_module, module_port).get_name(), itrack / 2, + itrack / 2); fp << "set_disable_timing "; fp << cb_instance_name << "/"; @@ -123,62 +134,71 @@ void print_analysis_sdc_disable_cb_unused_resources(std::fstream& fp, /* Build a map between mux_instance name and net_num */ std::map mux_instance_to_net_map; - /* Disable all the output port (grid input pins), which are not used by benchmark */ + /* Disable all the output port (grid input pins), which are not used by + * benchmark */ std::vector cb_sides = rr_gsb.get_cb_ipin_sides(cb_type); for (size_t side = 0; side < cb_sides.size(); ++side) { enum e_side cb_ipin_side = cb_sides[side]; - for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); ++inode) { + for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); + ++inode) { RRNodeId ipin_node = rr_gsb.get_ipin_node(cb_ipin_side, inode); /* Find the MUX instance that drives the IPIN! */ - std::string mux_instance_name = generate_cb_mux_instance_name(CONNECTION_BLOCK_MUX_INSTANCE_PREFIX, get_rr_graph_single_node_side(rr_graph, ipin_node), inode, std::string("")); - mux_instance_to_net_map[mux_instance_name] = atom_ctx.lookup.atom_net(routing_annotation.rr_node_net(ipin_node)); + std::string mux_instance_name = generate_cb_mux_instance_name( + CONNECTION_BLOCK_MUX_INSTANCE_PREFIX, + get_rr_graph_single_node_side(rr_graph, ipin_node), inode, + std::string("")); + mux_instance_to_net_map[mux_instance_name] = + atom_ctx.lookup.atom_net(routing_annotation.rr_node_net(ipin_node)); - if (false == is_rr_node_to_be_disable_for_analysis(routing_annotation, ipin_node)) { + if (false == is_rr_node_to_be_disable_for_analysis(routing_annotation, + ipin_node)) { continue; } - if (0 == std::distance(rr_graph.node_configurable_in_edges(ipin_node).begin(), rr_graph.node_configurable_in_edges(ipin_node).end())) { + if (0 == + std::distance(rr_graph.node_configurable_in_edges(ipin_node).begin(), + rr_graph.node_configurable_in_edges(ipin_node).end())) { continue; } - std::string port_name = generate_cb_module_grid_port_name(cb_ipin_side, - grids, - device_annotation, - rr_graph, - ipin_node); + std::string port_name = generate_cb_module_grid_port_name( + cb_ipin_side, grids, device_annotation, rr_graph, ipin_node); /* Find the port in unique mirror! */ if (true == compact_routing_hierarchy) { /* Note: use GSB coordinate when inquire for unique modules!!! */ vtr::Point cb_coord(rr_gsb.get_x(), rr_gsb.get_y()); - const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(cb_type, cb_coord); - const RRNodeId& unique_mirror_ipin_node = unique_mirror.get_ipin_node(cb_ipin_side, inode); - port_name = generate_cb_module_grid_port_name(cb_ipin_side, - grids, - device_annotation, - rr_graph, - unique_mirror_ipin_node); + const RRGSB& unique_mirror = + device_rr_gsb.get_cb_unique_module(cb_type, cb_coord); + const RRNodeId& unique_mirror_ipin_node = + unique_mirror.get_ipin_node(cb_ipin_side, inode); + port_name = generate_cb_module_grid_port_name( + cb_ipin_side, grids, device_annotation, rr_graph, + unique_mirror_ipin_node); } /* Ensure we have this port in the module! */ - ModulePortId module_port = module_manager.find_module_port(cb_module, port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module, module_port)); + ModulePortId module_port = + module_manager.find_module_port(cb_module, port_name); + VTR_ASSERT(true == + module_manager.valid_module_port_id(cb_module, module_port)); fp << "set_disable_timing "; fp << cb_instance_name << "/"; - fp << generate_sdc_port(module_manager.module_port(cb_module, module_port)); + fp << generate_sdc_port( + module_manager.module_port(cb_module, module_port)); fp << std::endl; } } - /* Disable all the unused inputs of routing multiplexers, which are not used by benchmark - * Here, we start from each input of the Connection Blocks, and traverse forward to the sink - * port of the module net whose source is the input - * We will find the instance name which is the parent of the sink port, and search the - * net id through the instance_name_to_net_map - * The the net id does not match the net id of this input, we will disable the sink port! + /* Disable all the unused inputs of routing multiplexers, which are not used + * by benchmark Here, we start from each input of the Connection Blocks, and + * traverse forward to the sink port of the module net whose source is the + * input We will find the instance name which is the parent of the sink port, + * and search the net id through the instance_name_to_net_map The the net id + * does not match the net id of this input, we will disable the sink port! * * cb_module * +----------------------- @@ -189,52 +209,49 @@ void print_analysis_sdc_disable_cb_unused_resources(std::fstream& fp, * | | MUX instance B * | | +---------- * | +------>| sink port (do not disable!) - */ - for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); ++itrack) { - const RRNodeId& chan_node = rr_gsb.get_chan_node(rr_gsb.get_cb_chan_side(cb_type), itrack); + */ + for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); + ++itrack) { + const RRNodeId& chan_node = + rr_gsb.get_chan_node(rr_gsb.get_cb_chan_side(cb_type), itrack); /* Disable both input of the routing track if it is not used! */ - std::string port_name = generate_cb_module_track_port_name(cb_type, - OUT_PORT, - 0 == itrack % 2); + std::string port_name = + generate_cb_module_track_port_name(cb_type, OUT_PORT, 0 == itrack % 2); /* Ensure we have this port in the module! */ - ModulePortId module_port = module_manager.find_module_port(cb_module, port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module, module_port)); + ModulePortId module_port = + module_manager.find_module_port(cb_module, port_name); + VTR_ASSERT(true == + module_manager.valid_module_port_id(cb_module, module_port)); - AtomNetId mapped_atom_net = atom_ctx.lookup.atom_net(routing_annotation.rr_node_net(chan_node)); - - disable_analysis_module_input_pin_net_sinks(fp, module_manager, cb_module, - cb_instance_name, - module_port, itrack / 2, - mapped_atom_net, - mux_instance_to_net_map); + AtomNetId mapped_atom_net = + atom_ctx.lookup.atom_net(routing_annotation.rr_node_net(chan_node)); + disable_analysis_module_input_pin_net_sinks( + fp, module_manager, cb_module, cb_instance_name, module_port, itrack / 2, + mapped_atom_net, mux_instance_to_net_map); } } /******************************************************************** * Iterate over all the connection blocks in a device - * and disable unused ports for each of them + * and disable unused ports for each of them *******************************************************************/ -static -void print_analysis_sdc_disable_unused_cb_ports(std::fstream& fp, - const AtomContext& atom_ctx, - const ModuleManager& module_manager, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const VprRoutingAnnotation& routing_annotation, - const DeviceRRGSB& device_rr_gsb, - const t_rr_type& cb_type, - const bool& compact_routing_hierarchy) { +static void print_analysis_sdc_disable_unused_cb_ports( + std::fstream& fp, const AtomContext& atom_ctx, + const ModuleManager& module_manager, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const VprRoutingAnnotation& routing_annotation, + const DeviceRRGSB& device_rr_gsb, const t_rr_type& cb_type, + const bool& compact_routing_hierarchy) { /* Build unique X-direction connection block modules */ vtr::Point cb_range = device_rr_gsb.get_gsb_range(); for (size_t ix = 0; ix < cb_range.x(); ++ix) { for (size_t iy = 0; iy < cb_range.y(); ++iy) { /* Check if the connection block exists in the device! - * Some of them do NOT exist due to heterogeneous blocks (height > 1) + * Some of them do NOT exist due to heterogeneous blocks (height > 1) * We will skip those modules */ const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); @@ -242,86 +259,63 @@ void print_analysis_sdc_disable_unused_cb_ports(std::fstream& fp, continue; } - print_analysis_sdc_disable_cb_unused_resources(fp, - atom_ctx, - module_manager, - device_annotation, - grids, - rr_graph, - routing_annotation, - device_rr_gsb, - rr_gsb, - cb_type, - compact_routing_hierarchy); + print_analysis_sdc_disable_cb_unused_resources( + fp, atom_ctx, module_manager, device_annotation, grids, rr_graph, + routing_annotation, device_rr_gsb, rr_gsb, cb_type, + compact_routing_hierarchy); } } } /******************************************************************** * Iterate over all the connection blocks in a device - * and disable unused ports for each of them + * and disable unused ports for each of them *******************************************************************/ -void print_analysis_sdc_disable_unused_cbs(std::fstream& fp, - const AtomContext& atom_ctx, - const ModuleManager& module_manager, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const VprRoutingAnnotation& routing_annotation, - const DeviceRRGSB& device_rr_gsb, - const bool& compact_routing_hierarchy) { +void print_analysis_sdc_disable_unused_cbs( + std::fstream& fp, const AtomContext& atom_ctx, + const ModuleManager& module_manager, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const VprRoutingAnnotation& routing_annotation, + const DeviceRRGSB& device_rr_gsb, const bool& compact_routing_hierarchy) { + print_analysis_sdc_disable_unused_cb_ports( + fp, atom_ctx, module_manager, device_annotation, grids, rr_graph, + routing_annotation, device_rr_gsb, CHANX, compact_routing_hierarchy); - print_analysis_sdc_disable_unused_cb_ports(fp, atom_ctx, - module_manager, - device_annotation, - grids, - rr_graph, - routing_annotation, - device_rr_gsb, - CHANX, compact_routing_hierarchy); - - print_analysis_sdc_disable_unused_cb_ports(fp, atom_ctx, - module_manager, - device_annotation, - grids, - rr_graph, - routing_annotation, - device_rr_gsb, - CHANY, compact_routing_hierarchy); + print_analysis_sdc_disable_unused_cb_ports( + fp, atom_ctx, module_manager, device_annotation, grids, rr_graph, + routing_annotation, device_rr_gsb, CHANY, compact_routing_hierarchy); } /******************************************************************** - * This function will disable + * This function will disable * 1. all the unused port (unmapped by a benchmark) of a switch block - * 2. all the unused inputs (unmapped by a benchmark) of routing multiplexers + * 2. all the unused inputs (unmapped by a benchmark) of routing multiplexers * in a switch block *******************************************************************/ -static -void print_analysis_sdc_disable_sb_unused_resources(std::fstream& fp, - const AtomContext& atom_ctx, - const ModuleManager& module_manager, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const VprRoutingAnnotation& routing_annotation, - const DeviceRRGSB& device_rr_gsb, - const RRGSB& rr_gsb, - const bool& compact_routing_hierarchy) { +static void print_analysis_sdc_disable_sb_unused_resources( + std::fstream& fp, const AtomContext& atom_ctx, + const ModuleManager& module_manager, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const VprRoutingAnnotation& routing_annotation, + const DeviceRRGSB& device_rr_gsb, const RRGSB& rr_gsb, + const bool& compact_routing_hierarchy) { /* Validate file stream */ valid_file_stream(fp); vtr::Point gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); - std::string sb_instance_name = generate_switch_block_module_name(gsb_coordinate); + std::string sb_instance_name = + generate_switch_block_module_name(gsb_coordinate); - /* If we use the compact routing hierarchy, we need to find the module name !*/ + /* If we use the compact routing hierarchy, we need to find the module name + * !*/ vtr::Point sb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); if (true == compact_routing_hierarchy) { vtr::Point sb_coord(rr_gsb.get_x(), rr_gsb.get_y()); /* Note: use GSB coordinate when inquire for unique modules!!! */ const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(sb_coord); - sb_coordinate.set_x(unique_mirror.get_sb_x()); - sb_coordinate.set_y(unique_mirror.get_sb_y()); + sb_coordinate.set_x(unique_mirror.get_sb_x()); + sb_coordinate.set_y(unique_mirror.get_sb_y()); } std::string sb_module_name = generate_switch_block_module_name(sb_coordinate); @@ -330,51 +324,69 @@ void print_analysis_sdc_disable_sb_unused_resources(std::fstream& fp, VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); /* Print comments */ - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; fp << "# Disable timing for Switch block " << sb_module_name << std::endl; - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; /* Build a map between mux_instance name and net_num */ std::map mux_instance_to_net_map; - /* Disable all the input/output port (routing tracks), which are not used by benchmark */ + /* Disable all the input/output port (routing tracks), which are not used by + * benchmark */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); - for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) { - const RRNodeId& chan_node = rr_gsb.get_chan_node(side_manager.get_side(), itrack); + for (size_t itrack = 0; + itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) { + const RRNodeId& chan_node = + rr_gsb.get_chan_node(side_manager.get_side(), itrack); - std::string port_name = generate_sb_module_track_port_name(rr_graph.node_type(rr_gsb.get_chan_node(side_manager.get_side(), itrack)), - side_manager.get_side(), - rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)); + std::string port_name = generate_sb_module_track_port_name( + rr_graph.node_type( + rr_gsb.get_chan_node(side_manager.get_side(), itrack)), + side_manager.get_side(), + rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)); if (true == compact_routing_hierarchy) { /* Note: use GSB coordinate when inquire for unique modules!!! */ vtr::Point sb_coord(rr_gsb.get_x(), rr_gsb.get_y()); - const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(sb_coord); - port_name = generate_sb_module_track_port_name(rr_graph.node_type(unique_mirror.get_chan_node(side_manager.get_side(), itrack)), - side_manager.get_side(), - unique_mirror.get_chan_node_direction(side_manager.get_side(), itrack)); + const RRGSB& unique_mirror = + device_rr_gsb.get_sb_unique_module(sb_coord); + port_name = generate_sb_module_track_port_name( + rr_graph.node_type( + unique_mirror.get_chan_node(side_manager.get_side(), itrack)), + side_manager.get_side(), + unique_mirror.get_chan_node_direction(side_manager.get_side(), + itrack)); } /* Ensure we have this port in the module! */ - ModulePortId module_port = module_manager.find_module_port(sb_module, port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(sb_module, module_port)); + ModulePortId module_port = + module_manager.find_module_port(sb_module, port_name); + VTR_ASSERT(true == + module_manager.valid_module_port_id(sb_module, module_port)); - /* Cache the net name for routing tracks which are outputs of the switch block */ - if (OUT_PORT == rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) { + /* Cache the net name for routing tracks which are outputs of the switch + * block */ + if (OUT_PORT == + rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) { /* Generate the name of mux instance related to this output node */ - std::string mux_instance_name = generate_sb_memory_instance_name(SWITCH_BLOCK_MUX_INSTANCE_PREFIX, side_manager.get_side(), itrack, std::string("")); - mux_instance_to_net_map[mux_instance_name] = atom_ctx.lookup.atom_net(routing_annotation.rr_node_net(chan_node)); + std::string mux_instance_name = generate_sb_memory_instance_name( + SWITCH_BLOCK_MUX_INSTANCE_PREFIX, side_manager.get_side(), itrack, + std::string("")); + mux_instance_to_net_map[mux_instance_name] = + atom_ctx.lookup.atom_net(routing_annotation.rr_node_net(chan_node)); } /* Check if this node is used by benchmark */ - if (false == is_rr_node_to_be_disable_for_analysis(routing_annotation, chan_node)) { + if (false == is_rr_node_to_be_disable_for_analysis(routing_annotation, + chan_node)) { continue; } - BasicPort sb_port(module_manager.module_port(sb_module, module_port).get_name(), - itrack / 2, itrack / 2); + BasicPort sb_port( + module_manager.module_port(sb_module, module_port).get_name(), + itrack / 2, itrack / 2); fp << "set_disable_timing "; fp << sb_instance_name << "/"; @@ -383,115 +395,118 @@ void print_analysis_sdc_disable_sb_unused_resources(std::fstream& fp, } } - /* Disable all the input port (grid output pins), which are not used by benchmark */ + /* Disable all the input port (grid output pins), which are not used by + * benchmark */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); - for (size_t inode = 0; inode < rr_gsb.get_num_opin_nodes(side_manager.get_side()); ++inode) { - const RRNodeId& opin_node = rr_gsb.get_opin_node(side_manager.get_side(), inode); + for (size_t inode = 0; + inode < rr_gsb.get_num_opin_nodes(side_manager.get_side()); ++inode) { + const RRNodeId& opin_node = + rr_gsb.get_opin_node(side_manager.get_side(), inode); - std::string port_name = generate_sb_module_grid_port_name(side_manager.get_side(), - get_rr_graph_single_node_side(rr_graph, opin_node), - grids, - device_annotation, - rr_graph, - opin_node); + std::string port_name = generate_sb_module_grid_port_name( + side_manager.get_side(), + get_rr_graph_single_node_side(rr_graph, opin_node), grids, + device_annotation, rr_graph, opin_node); if (true == compact_routing_hierarchy) { /* Note: use GSB coordinate when inquire for unique modules!!! */ vtr::Point sb_coord(rr_gsb.get_x(), rr_gsb.get_y()); - const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(sb_coord); - const RRNodeId& unique_mirror_opin_node = unique_mirror.get_opin_node(side_manager.get_side(), inode); + const RRGSB& unique_mirror = + device_rr_gsb.get_sb_unique_module(sb_coord); + const RRNodeId& unique_mirror_opin_node = + unique_mirror.get_opin_node(side_manager.get_side(), inode); - port_name = generate_sb_module_grid_port_name(side_manager.get_side(), - get_rr_graph_single_node_side(rr_graph, unique_mirror_opin_node), - grids, - device_annotation, - rr_graph, - unique_mirror_opin_node); + port_name = generate_sb_module_grid_port_name( + side_manager.get_side(), + get_rr_graph_single_node_side(rr_graph, unique_mirror_opin_node), + grids, device_annotation, rr_graph, unique_mirror_opin_node); } - /* Ensure we have this port in the module! */ - ModulePortId module_port = module_manager.find_module_port(sb_module, port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(sb_module, module_port)); + ModulePortId module_port = + module_manager.find_module_port(sb_module, port_name); + VTR_ASSERT(true == + module_manager.valid_module_port_id(sb_module, module_port)); /* Check if this node is used by benchmark */ - if (false == is_rr_node_to_be_disable_for_analysis(routing_annotation, opin_node)) { + if (false == is_rr_node_to_be_disable_for_analysis(routing_annotation, + opin_node)) { continue; } fp << "set_disable_timing "; fp << sb_instance_name << "/"; - fp << generate_sdc_port(module_manager.module_port(sb_module, module_port)); + fp << generate_sdc_port( + module_manager.module_port(sb_module, module_port)); fp << std::endl; } } - /* Disable all the unused inputs of routing multiplexers, which are not used by benchmark - * Here, we start from each input of the Switch Blocks, and traverse forward to the sink - * port of the module net whose source is the input - * We will find the instance name which is the parent of the sink port, and search the - * net id through the instance_name_to_net_map - * The the net id does not match the net id of this input, we will disable the sink port! + /* Disable all the unused inputs of routing multiplexers, which are not used + * by benchmark Here, we start from each input of the Switch Blocks, and + * traverse forward to the sink port of the module net whose source is the + * input We will find the instance name which is the parent of the sink port, + * and search the net id through the instance_name_to_net_map The the net id + * does not match the net id of this input, we will disable the sink port! * * sb_module * +----------------------- * | MUX instance A * | +----------- - * input_port--->|--+---x-->| sink port (disable! net_id = Y) + * input_port--->|--+---x-->| sink port (disable! net_id = Y) * (net_id = X) | | +---------- * | | MUX instance B * | | +---------- * | +------>| sink port (do not disable! net_id = X) * - * Because the input ports of a SB module come from + * Because the input ports of a SB module come from * 1. Grid output pins * 2. routing tracks * We will walk through these ports and do conditionally disable_timing - */ + */ /* Iterate over input ports coming from grid output pins */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); - for (size_t inode = 0; inode < rr_gsb.get_num_opin_nodes(side_manager.get_side()); ++inode) { - const RRNodeId& opin_node = rr_gsb.get_opin_node(side_manager.get_side(), inode); + for (size_t inode = 0; + inode < rr_gsb.get_num_opin_nodes(side_manager.get_side()); ++inode) { + const RRNodeId& opin_node = + rr_gsb.get_opin_node(side_manager.get_side(), inode); - std::string port_name = generate_sb_module_grid_port_name(side_manager.get_side(), - get_rr_graph_single_node_side(rr_graph, opin_node), - grids, - device_annotation, - rr_graph, - opin_node); + std::string port_name = generate_sb_module_grid_port_name( + side_manager.get_side(), + get_rr_graph_single_node_side(rr_graph, opin_node), grids, + device_annotation, rr_graph, opin_node); if (true == compact_routing_hierarchy) { /* Note: use GSB coordinate when inquire for unique modules!!! */ vtr::Point sb_coord(rr_gsb.get_x(), rr_gsb.get_y()); - const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(sb_coord); - const RRNodeId& unique_mirror_opin_node = unique_mirror.get_opin_node(side_manager.get_side(), inode); + const RRGSB& unique_mirror = + device_rr_gsb.get_sb_unique_module(sb_coord); + const RRNodeId& unique_mirror_opin_node = + unique_mirror.get_opin_node(side_manager.get_side(), inode); - port_name = generate_sb_module_grid_port_name(side_manager.get_side(), - get_rr_graph_single_node_side(rr_graph, unique_mirror_opin_node), - grids, - device_annotation, - rr_graph, - unique_mirror_opin_node); + port_name = generate_sb_module_grid_port_name( + side_manager.get_side(), + get_rr_graph_single_node_side(rr_graph, unique_mirror_opin_node), + grids, device_annotation, rr_graph, unique_mirror_opin_node); } - /* Ensure we have this port in the module! */ - ModulePortId module_port = module_manager.find_module_port(sb_module, port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(sb_module, module_port)); + ModulePortId module_port = + module_manager.find_module_port(sb_module, port_name); + VTR_ASSERT(true == + module_manager.valid_module_port_id(sb_module, module_port)); - AtomNetId mapped_atom_net = atom_ctx.lookup.atom_net(routing_annotation.rr_node_net(opin_node)); + AtomNetId mapped_atom_net = + atom_ctx.lookup.atom_net(routing_annotation.rr_node_net(opin_node)); - disable_analysis_module_input_port_net_sinks(fp, module_manager, - sb_module, - sb_instance_name, - module_port, - mapped_atom_net, - mux_instance_to_net_map); + disable_analysis_module_input_port_net_sinks( + fp, module_manager, sb_module, sb_instance_name, module_port, + mapped_atom_net, mux_instance_to_net_map); } } @@ -499,67 +514,68 @@ void print_analysis_sdc_disable_sb_unused_resources(std::fstream& fp, for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); - for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) { + for (size_t itrack = 0; + itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) { /* Skip output ports, they have already been disabled or not */ - if (OUT_PORT == rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) { + if (OUT_PORT == + rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) { continue; } - const RRNodeId& chan_node = rr_gsb.get_chan_node(side_manager.get_side(), itrack); + const RRNodeId& chan_node = + rr_gsb.get_chan_node(side_manager.get_side(), itrack); - std::string port_name = generate_sb_module_track_port_name(rr_graph.node_type(chan_node), - side_manager.get_side(), - rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)); + std::string port_name = generate_sb_module_track_port_name( + rr_graph.node_type(chan_node), side_manager.get_side(), + rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)); if (true == compact_routing_hierarchy) { /* Note: use GSB coordinate when inquire for unique modules!!! */ vtr::Point sb_coord(rr_gsb.get_x(), rr_gsb.get_y()); - const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(sb_coord); - const RRNodeId& unique_mirror_chan_node = unique_mirror.get_chan_node(side_manager.get_side(), itrack); + const RRGSB& unique_mirror = + device_rr_gsb.get_sb_unique_module(sb_coord); + const RRNodeId& unique_mirror_chan_node = + unique_mirror.get_chan_node(side_manager.get_side(), itrack); - port_name = generate_sb_module_track_port_name(rr_graph.node_type(unique_mirror_chan_node), - side_manager.get_side(), - unique_mirror.get_chan_node_direction(side_manager.get_side(), itrack)); + port_name = generate_sb_module_track_port_name( + rr_graph.node_type(unique_mirror_chan_node), side_manager.get_side(), + unique_mirror.get_chan_node_direction(side_manager.get_side(), + itrack)); } - /* Ensure we have this port in the module! */ - ModulePortId module_port = module_manager.find_module_port(sb_module, port_name); - VTR_ASSERT(true == module_manager.valid_module_port_id(sb_module, module_port)); + ModulePortId module_port = + module_manager.find_module_port(sb_module, port_name); + VTR_ASSERT(true == + module_manager.valid_module_port_id(sb_module, module_port)); - AtomNetId mapped_atom_net = atom_ctx.lookup.atom_net(routing_annotation.rr_node_net(chan_node)); + AtomNetId mapped_atom_net = + atom_ctx.lookup.atom_net(routing_annotation.rr_node_net(chan_node)); - disable_analysis_module_input_pin_net_sinks(fp, module_manager, sb_module, - sb_instance_name, - module_port, itrack / 2, - mapped_atom_net, - mux_instance_to_net_map); + disable_analysis_module_input_pin_net_sinks( + fp, module_manager, sb_module, sb_instance_name, module_port, + itrack / 2, mapped_atom_net, mux_instance_to_net_map); } } } - /******************************************************************** * Iterate over all the connection blocks in a device - * and disable unused ports for each of them + * and disable unused ports for each of them *******************************************************************/ -void print_analysis_sdc_disable_unused_sbs(std::fstream& fp, - const AtomContext& atom_ctx, - const ModuleManager& module_manager, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const VprRoutingAnnotation& routing_annotation, - const DeviceRRGSB& device_rr_gsb, - const bool& compact_routing_hierarchy) { - +void print_analysis_sdc_disable_unused_sbs( + std::fstream& fp, const AtomContext& atom_ctx, + const ModuleManager& module_manager, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const VprRoutingAnnotation& routing_annotation, + const DeviceRRGSB& device_rr_gsb, const bool& compact_routing_hierarchy) { /* Build unique X-direction connection block modules */ vtr::Point sb_range = device_rr_gsb.get_gsb_range(); for (size_t ix = 0; ix < sb_range.x(); ++ix) { for (size_t iy = 0; iy < sb_range.y(); ++iy) { /* Check if the connection block exists in the device! - * Some of them do NOT exist due to heterogeneous blocks (height > 1) + * Some of them do NOT exist due to heterogeneous blocks (height > 1) * We will skip those modules */ const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); @@ -567,16 +583,9 @@ void print_analysis_sdc_disable_unused_sbs(std::fstream& fp, continue; } - print_analysis_sdc_disable_sb_unused_resources(fp, - atom_ctx, - module_manager, - device_annotation, - grids, - rr_graph, - routing_annotation, - device_rr_gsb, - rr_gsb, - compact_routing_hierarchy); + print_analysis_sdc_disable_sb_unused_resources( + fp, atom_ctx, module_manager, device_annotation, grids, rr_graph, + routing_annotation, device_rr_gsb, rr_gsb, compact_routing_hierarchy); } } } diff --git a/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.h b/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.h index 904dd7b23..797289287 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.h +++ b/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.h @@ -6,10 +6,11 @@ *******************************************************************/ #include #include -#include "vpr_context.h" -#include "module_manager.h" + #include "device_grid.h" #include "device_rr_gsb.h" +#include "module_manager.h" +#include "vpr_context.h" #include "vpr_routing_annotation.h" /******************************************************************** @@ -19,25 +20,19 @@ /* begin namespace openfpga */ namespace openfpga { -void print_analysis_sdc_disable_unused_cbs(std::fstream& fp, - const AtomContext& atom_ctx, - const ModuleManager& module_manager, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const VprRoutingAnnotation& routing_annotation, - const DeviceRRGSB& device_rr_gsb, - const bool& compact_routing_hierarchy); +void print_analysis_sdc_disable_unused_cbs( + std::fstream& fp, const AtomContext& atom_ctx, + const ModuleManager& module_manager, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const VprRoutingAnnotation& routing_annotation, + const DeviceRRGSB& device_rr_gsb, const bool& compact_routing_hierarchy); -void print_analysis_sdc_disable_unused_sbs(std::fstream& fp, - const AtomContext& atom_ctx, - const ModuleManager& module_manager, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const VprRoutingAnnotation& routing_annotation, - const DeviceRRGSB& device_rr_gsb, - const bool& compact_routing_hierarchy); +void print_analysis_sdc_disable_unused_sbs( + std::fstream& fp, const AtomContext& atom_ctx, + const ModuleManager& module_manager, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const VprRoutingAnnotation& routing_annotation, + const DeviceRRGSB& device_rr_gsb, const bool& compact_routing_hierarchy); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/analysis_sdc_writer.cpp b/openfpga/src/fpga_sdc/analysis_sdc_writer.cpp index aae71c2a9..00281eebb 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_writer.cpp +++ b/openfpga/src/fpga_sdc/analysis_sdc_writer.cpp @@ -1,6 +1,6 @@ /******************************************************************** * This file includes functions that are used to output a SDC file - * that constrain a FPGA fabric (P&Red netlist) using a benchmark + * that constrain a FPGA fabric (P&Red netlist) using a benchmark *******************************************************************/ #include #include @@ -11,21 +11,17 @@ #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" -#include "openfpga_port.h" - -#include "mux_utils.h" - -#include "openfpga_naming.h" -#include "openfpga_atom_netlist_utils.h" - -#include "sdc_writer_naming.h" -#include "sdc_writer_utils.h" -#include "sdc_memory_utils.h" - #include "analysis_sdc_grid_writer.h" #include "analysis_sdc_routing_writer.h" #include "analysis_sdc_writer.h" +#include "mux_utils.h" +#include "openfpga_atom_netlist_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" +#include "sdc_memory_utils.h" +#include "sdc_writer_naming.h" +#include "sdc_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -33,30 +29,28 @@ namespace openfpga { /******************************************************************** * Generate SDC constaints for inputs and outputs * We consider the top module in formal verification purpose here - * which is easier + * which is easier *******************************************************************/ -static -void print_analysis_sdc_io_delays(std::fstream& fp, - const float& time_unit, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const VprNetlistAnnotation& netlist_annotation, - const IoLocationMap& io_location_map, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricGlobalPortInfo& fabric_global_port_info, - const float& critical_path_delay) { +static void print_analysis_sdc_io_delays( + std::fstream& fp, const float& time_unit, const AtomContext& atom_ctx, + const PlacementContext& place_ctx, + const VprNetlistAnnotation& netlist_annotation, + const IoLocationMap& io_location_map, const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info, + const float& critical_path_delay) { /* Validate the file stream */ valid_file_stream(fp); /* Print comments */ - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; fp << "# Create clock " << std::endl; - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; /* Get clock port from the global port */ std::vector operating_clock_ports; - for (const FabricGlobalPortId& clock_port : fabric_global_port_info.global_ports()) { + for (const FabricGlobalPortId& clock_port : + fabric_global_port_info.global_ports()) { if (false == fabric_global_port_info.global_port_is_clock(clock_port)) { continue; } @@ -64,18 +58,22 @@ void print_analysis_sdc_io_delays(std::fstream& fp, if (true == fabric_global_port_info.global_port_is_prog(clock_port)) { continue; } - + /* Find the module port and Update the operating port list */ - ModulePortId module_port = fabric_global_port_info.global_module_port(clock_port); - operating_clock_ports.push_back(module_manager.module_port(top_module, module_port)); + ModulePortId module_port = + fabric_global_port_info.global_module_port(clock_port); + operating_clock_ports.push_back( + module_manager.module_port(top_module, module_port)); } for (const BasicPort& operating_clock_port : operating_clock_ports) { /* Reach here, it means a clock port and we need print constraints */ fp << "create_clock "; fp << generate_sdc_port(operating_clock_port); - fp << " -period " << std::setprecision(10) << critical_path_delay / time_unit; - fp << " -waveform {0 " << std::setprecision(10) << critical_path_delay / (2 * time_unit) << "}"; + fp << " -period " << std::setprecision(10) + << critical_path_delay / time_unit; + fp << " -waveform {0 " << std::setprecision(10) + << critical_path_delay / (2 * time_unit) << "}"; fp << std::endl; /* Add an empty line as a splitter */ @@ -88,58 +86,69 @@ void print_analysis_sdc_io_delays(std::fstream& fp, VTR_ASSERT(1 == operating_clock_ports.size()); /* In this function, we support only 1 type of I/Os */ - std::vector module_io_ports = module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GPIO_PORT); + std::vector module_io_ports = module_manager.module_ports_by_type( + top_module, ModuleManager::MODULE_GPIO_PORT); for (const BasicPort& module_io_port : module_io_ports) { /* Keep tracking which I/Os have been used */ std::vector io_used(module_io_port.get_width(), false); /* Find clock ports in benchmark */ - std::vector benchmark_clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); + std::vector benchmark_clock_port_names = + find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); /* Print comments */ - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; fp << "# Create input and output delays for used I/Os " << std::endl; - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) { /* Bypass non-I/O atom blocks ! */ - if ( (AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) - && (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)) ) { + if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) && + (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk))) { continue; } - /* clock net or constant generator should be disabled in timing analysis */ - if (benchmark_clock_port_names.end() != std::find(benchmark_clock_port_names.begin(), benchmark_clock_port_names.end(), atom_ctx.nlist.block_name(atom_blk))) { + /* clock net or constant generator should be disabled in timing analysis + */ + if (benchmark_clock_port_names.end() != + std::find(benchmark_clock_port_names.begin(), + benchmark_clock_port_names.end(), + atom_ctx.nlist.block_name(atom_blk))) { continue; } /* Find the index of the mapped GPIO in top-level FPGA fabric */ - size_t io_index = io_location_map.io_index(place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.x, - place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.y, - place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.sub_tile, - module_io_port.get_name()); + size_t io_index = io_location_map.io_index( + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.x, + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.y, + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.sub_tile, + module_io_port.get_name()); if (size_t(-1) == io_index) { continue; } /* Ensure that IO index is in range */ - BasicPort module_mapped_io_port = module_io_port; - /* Set the port pin index */ + BasicPort module_mapped_io_port = module_io_port; + /* Set the port pin index */ VTR_ASSERT(io_index < module_mapped_io_port.get_width()); module_mapped_io_port.set_width(io_index, io_index); - /* For input I/O, we set an input delay constraint correlated to the operating clock - * For output I/O, we set an output delay constraint correlated to the operating clock + /* For input I/O, we set an input delay constraint correlated to the + * operating clock For output I/O, we set an output delay constraint + * correlated to the operating clock */ if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) { print_sdc_set_port_input_delay(fp, module_mapped_io_port, - operating_clock_ports[0], critical_path_delay / time_unit); + operating_clock_ports[0], + critical_path_delay / time_unit); } else { - VTR_ASSERT(AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)); + VTR_ASSERT(AtomBlockType::OUTPAD == + atom_ctx.nlist.block_type(atom_blk)); print_sdc_set_port_output_delay(fp, module_mapped_io_port, - operating_clock_ports[0], critical_path_delay / time_unit); + operating_clock_ports[0], + critical_path_delay / time_unit); } /* Mark this I/O has been used/wired */ @@ -150,9 +159,9 @@ void print_analysis_sdc_io_delays(std::fstream& fp, fp << std::endl; /* Print comments */ - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; fp << "# Disable timing for unused I/Os " << std::endl; - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; /* Wire the unused iopads to a constant */ for (size_t io_index = 0; io_index < io_used.size(); ++io_index) { @@ -162,8 +171,8 @@ void print_analysis_sdc_io_delays(std::fstream& fp, } /* Wire to a contant */ - BasicPort module_unused_io_port = module_io_port; - /* Set the port pin index */ + BasicPort module_unused_io_port = module_io_port; + /* Set the port pin index */ module_unused_io_port.set_width(io_index, io_index); print_sdc_disable_port_timing(fp, module_unused_io_port); } @@ -176,23 +185,23 @@ void print_analysis_sdc_io_delays(std::fstream& fp, /******************************************************************** * Disable the timing for all the global port except the operating clock ports *******************************************************************/ -static -void print_analysis_sdc_disable_global_ports(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricGlobalPortInfo& fabric_global_port_info) { +static void print_analysis_sdc_disable_global_ports( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info) { /* Validate file stream */ valid_file_stream(fp); /* Print comments */ - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; fp << "# Disable timing for global ports " << std::endl; - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; - for (const FabricGlobalPortId& global_port : fabric_global_port_info.global_ports()) { + for (const FabricGlobalPortId& global_port : + fabric_global_port_info.global_ports()) { /* Skip operating clock here! */ - if ( (true == fabric_global_port_info.global_port_is_clock(global_port)) - && (false == fabric_global_port_info.global_port_is_prog(global_port)) ) { + if ((true == fabric_global_port_info.global_port_is_clock(global_port)) && + (false == fabric_global_port_info.global_port_is_prog(global_port))) { continue; } @@ -201,8 +210,10 @@ void print_analysis_sdc_disable_global_ports(std::fstream& fp, continue; } - ModulePortId module_port = fabric_global_port_info.global_module_port(global_port); - BasicPort port_to_disable = module_manager.module_port(top_module, module_port); + ModulePortId module_port = + fabric_global_port_info.global_module_port(global_port); + BasicPort port_to_disable = + module_manager.module_port(top_module, module_port); print_sdc_disable_port_timing(fp, port_to_disable); } @@ -210,19 +221,23 @@ void print_analysis_sdc_disable_global_ports(std::fstream& fp, /******************************************************************** * Top-level function outputs a SDC file - * that constrain a FPGA fabric (P&Red netlist) using a benchmark + * that constrain a FPGA fabric (P&Red netlist) using a benchmark *******************************************************************/ void print_analysis_sdc(const AnalysisSdcOption& option, const float& critical_path_delay, - const VprContext& vpr_ctx, + const VprContext& vpr_ctx, const OpenfpgaContext& openfpga_ctx, const bool& compact_routing_hierarchy) { /* Create the file name for Verilog netlist */ - std::string sdc_fname(option.sdc_dir() + generate_analysis_sdc_file_name(vpr_ctx.atom().nlist.netlist_name(), std::string(SDC_ANALYSIS_FILE_NAME))); + std::string sdc_fname( + option.sdc_dir() + + generate_analysis_sdc_file_name(vpr_ctx.atom().nlist.netlist_name(), + std::string(SDC_ANALYSIS_FILE_NAME))); - std::string timer_message = std::string("Generating SDC for Timing/Power analysis on the mapped FPGA '") - + sdc_fname - + std::string("'"); + std::string timer_message = + std::string( + "Generating SDC for Timing/Power analysis on the mapped FPGA '") + + sdc_fname + std::string("'"); /* Start time count */ vtr::ScopedStartFinishTimer timer(timer_message); @@ -235,65 +250,56 @@ void print_analysis_sdc(const AnalysisSdcOption& option, check_file_stream(sdc_fname.c_str(), fp); /* Generate the descriptions*/ - print_sdc_file_header(fp, - std::string("Constrain for Timing/Power analysis on the mapped FPGA"), - option.time_stamp()); + print_sdc_file_header( + fp, std::string("Constrain for Timing/Power analysis on the mapped FPGA"), + option.time_stamp()); /* Find the top_module */ - ModuleId top_module = openfpga_ctx.module_graph().find_module(generate_fpga_top_module_name()); + ModuleId top_module = + openfpga_ctx.module_graph().find_module(generate_fpga_top_module_name()); VTR_ASSERT(true == openfpga_ctx.module_graph().valid_module_id(top_module)); /* Create clock and set I/O ports with input/output delays - * FIXME: Now different I/Os have different delays due to multiple clock frequency - * We need to consider these impacts and constrain different I/Os with different delays!!! + * FIXME: Now different I/Os have different delays due to multiple clock + * frequency We need to consider these impacts and constrain different I/Os + * with different delays!!! */ - print_analysis_sdc_io_delays(fp, option.time_unit(), - vpr_ctx.atom(), vpr_ctx.placement(), - openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.io_location_map(), - openfpga_ctx.module_graph(), top_module, - openfpga_ctx.fabric_global_port_info(), - critical_path_delay); + print_analysis_sdc_io_delays( + fp, option.time_unit(), vpr_ctx.atom(), vpr_ctx.placement(), + openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.io_location_map(), + openfpga_ctx.module_graph(), top_module, + openfpga_ctx.fabric_global_port_info(), critical_path_delay); /* Disable the timing for global ports */ - print_analysis_sdc_disable_global_ports(fp, - openfpga_ctx.module_graph(), top_module, - openfpga_ctx.fabric_global_port_info()); - - /* Disable the timing for configuration cells */ - rec_print_pnr_sdc_disable_configurable_memory_module_output(fp, option.flatten_names(), - openfpga_ctx.module_graph(), top_module, - format_dir_path(openfpga_ctx.module_graph().module_name(top_module))); + print_analysis_sdc_disable_global_ports( + fp, openfpga_ctx.module_graph(), top_module, + openfpga_ctx.fabric_global_port_info()); + /* Disable the timing for configuration cells */ + rec_print_pnr_sdc_disable_configurable_memory_module_output( + fp, option.flatten_names(), openfpga_ctx.module_graph(), top_module, + format_dir_path(openfpga_ctx.module_graph().module_name(top_module))); /* Disable timing for unused routing resources in connection blocks */ - print_analysis_sdc_disable_unused_cbs(fp, - vpr_ctx.atom(), - openfpga_ctx.module_graph(), - openfpga_ctx.vpr_device_annotation(), - vpr_ctx.device().grid, - vpr_ctx.device().rr_graph, - openfpga_ctx.vpr_routing_annotation(), - openfpga_ctx.device_rr_gsb(), - compact_routing_hierarchy); + print_analysis_sdc_disable_unused_cbs( + fp, vpr_ctx.atom(), openfpga_ctx.module_graph(), + openfpga_ctx.vpr_device_annotation(), vpr_ctx.device().grid, + vpr_ctx.device().rr_graph, openfpga_ctx.vpr_routing_annotation(), + openfpga_ctx.device_rr_gsb(), compact_routing_hierarchy); /* Disable timing for unused routing resources in switch blocks */ - print_analysis_sdc_disable_unused_sbs(fp, - vpr_ctx.atom(), - openfpga_ctx.module_graph(), - openfpga_ctx.vpr_device_annotation(), - vpr_ctx.device().grid, - vpr_ctx.device().rr_graph, - openfpga_ctx.vpr_routing_annotation(), - openfpga_ctx.device_rr_gsb(), - compact_routing_hierarchy); + print_analysis_sdc_disable_unused_sbs( + fp, vpr_ctx.atom(), openfpga_ctx.module_graph(), + openfpga_ctx.vpr_device_annotation(), vpr_ctx.device().grid, + vpr_ctx.device().rr_graph, openfpga_ctx.vpr_routing_annotation(), + openfpga_ctx.device_rr_gsb(), compact_routing_hierarchy); - /* Disable timing for unused routing resources in grids (programmable blocks) */ - print_analysis_sdc_disable_unused_grids(fp, - vpr_ctx.device().grid, - openfpga_ctx.vpr_device_annotation(), - openfpga_ctx.vpr_clustering_annotation(), - openfpga_ctx.vpr_placement_annotation(), - openfpga_ctx.module_graph()); + /* Disable timing for unused routing resources in grids (programmable blocks) + */ + print_analysis_sdc_disable_unused_grids( + fp, vpr_ctx.device().grid, openfpga_ctx.vpr_device_annotation(), + openfpga_ctx.vpr_clustering_annotation(), + openfpga_ctx.vpr_placement_annotation(), openfpga_ctx.module_graph()); /* Close file handler */ fp.close(); diff --git a/openfpga/src/fpga_sdc/analysis_sdc_writer.h b/openfpga/src/fpga_sdc/analysis_sdc_writer.h index 225c2f982..09eac3db0 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_writer.h +++ b/openfpga/src/fpga_sdc/analysis_sdc_writer.h @@ -6,9 +6,10 @@ *******************************************************************/ #include #include -#include "vpr_context.h" -#include "openfpga_context.h" + #include "analysis_sdc_option.h" +#include "openfpga_context.h" +#include "vpr_context.h" /******************************************************************** * Function declaration @@ -19,7 +20,7 @@ namespace openfpga { void print_analysis_sdc(const AnalysisSdcOption& option, const float& critical_path_delay, - const VprContext& vpr_ctx, + const VprContext& vpr_ctx, const OpenfpgaContext& openfpga_ctx, const bool& compact_routing_hierarchy); diff --git a/openfpga/src/fpga_sdc/analysis_sdc_writer_utils.cpp b/openfpga/src/fpga_sdc/analysis_sdc_writer_utils.cpp index 29cd5eae2..d9d093818 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_writer_utils.cpp +++ b/openfpga/src/fpga_sdc/analysis_sdc_writer_utils.cpp @@ -1,17 +1,16 @@ /******************************************************************** - * This file includes most utilized functions + * This file includes most utilized functions * that are used to output a SDC file - * in order to constrain a FPGA fabric (P&Red netlist) mapped to a benchmark + * in order to constrain a FPGA fabric (P&Red netlist) mapped to a benchmark *******************************************************************/ /* Headers from vtrutil library */ #include "vtr_assert.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - -#include "sdc_writer_utils.h" #include "analysis_sdc_writer_utils.h" +#include "openfpga_digest.h" +#include "sdc_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -19,70 +18,76 @@ namespace openfpga { /******************************************************************** * Identify if a node should be disabled during analysis SDC generation *******************************************************************/ -bool is_rr_node_to_be_disable_for_analysis(const VprRoutingAnnotation& routing_annotation, - const RRNodeId& cur_rr_node) { - /* Conditions to enable timing analysis for a node - * 1st condition: it have a valid net_number - * TODO: 2nd condition: it is not an parasitic net +bool is_rr_node_to_be_disable_for_analysis( + const VprRoutingAnnotation& routing_annotation, const RRNodeId& cur_rr_node) { + /* Conditions to enable timing analysis for a node + * 1st condition: it have a valid net_number + * TODO: 2nd condition: it is not an parasitic net */ return ClusterNetId::INVALID() == routing_annotation.rr_node_net(cur_rr_node); } /******************************************************************** - * Disable all the unused inputs of routing multiplexers, which are not used by benchmark - * Here, we start from each input of a routing module, and traverse forward to the sink - * port of the module net whose source is the input - * We will find the instance name which is the parent of the sink port, and search the - * net id through the instance_name_to_net_map - * The the net id does not match the net id of this input, we will disable the sink port! + * Disable all the unused inputs of routing multiplexers, which are not used by + *benchmark Here, we start from each input of a routing module, and traverse + *forward to the sink port of the module net whose source is the input We will + *find the instance name which is the parent of the sink port, and search the + * net id through the instance_name_to_net_map + * The the net id does not match the net id of this input, we will disable the + *sink port! * * parent_module * +----------------------- * | MUX instance A * | +----------- - * input_port--->|--+---x-->| sink port (disable! net_id = Y) + * input_port--->|--+---x-->| sink port (disable! net_id = Y) * (net_id = X) | | +---------- * | | MUX instance B * | | +---------- * | +------>| sink port (do not disable! net_id = X) * *******************************************************************/ -void disable_analysis_module_input_pin_net_sinks(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const std::string& parent_instance_name, - const ModulePortId& module_input_port, - const size_t& module_input_pin, - const AtomNetId& mapped_net, - const std::map mux_instance_to_net_map) { +void disable_analysis_module_input_pin_net_sinks( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& parent_module, const std::string& parent_instance_name, + const ModulePortId& module_input_port, const size_t& module_input_pin, + const AtomNetId& mapped_net, + const std::map mux_instance_to_net_map) { /* Validate file stream */ valid_file_stream(fp); /* Find the module net which sources from this port! */ - ModuleNetId module_net = module_manager.module_instance_port_net(parent_module, parent_module, 0, module_input_port, module_input_pin); + ModuleNetId module_net = module_manager.module_instance_port_net( + parent_module, parent_module, 0, module_input_port, module_input_pin); if (true != module_manager.valid_module_net_id(parent_module, module_net)) - VTR_ASSERT(true == module_manager.valid_module_net_id(parent_module, module_net)); + VTR_ASSERT(true == + module_manager.valid_module_net_id(parent_module, module_net)); /* Touch each sink of the net! */ - for (const ModuleNetSinkId& sink_id : module_manager.module_net_sinks(parent_module, module_net)) { - ModuleId sink_module = module_manager.net_sink_modules(parent_module, module_net)[sink_id]; - size_t sink_instance = module_manager.net_sink_instances(parent_module, module_net)[sink_id]; + for (const ModuleNetSinkId& sink_id : + module_manager.module_net_sinks(parent_module, module_net)) { + ModuleId sink_module = + module_manager.net_sink_modules(parent_module, module_net)[sink_id]; + size_t sink_instance = + module_manager.net_sink_instances(parent_module, module_net)[sink_id]; - /* Skip when sink module is the parent module, - * the output ports of parent modules have been disabled/enabled already! + /* Skip when sink module is the parent module, + * the output ports of parent modules have been disabled/enabled already! */ if (sink_module == parent_module) { continue; } - std::string sink_instance_name = module_manager.instance_name(parent_module, sink_module, sink_instance); + std::string sink_instance_name = + module_manager.instance_name(parent_module, sink_module, sink_instance); bool disable_timing = false; /* Check if this node is used by benchmark */ if (AtomNetId::INVALID() == mapped_net) { /* Disable all the sinks! */ disable_timing = true; } else { - std::map::const_iterator it = mux_instance_to_net_map.find(sink_instance_name); + std::map::const_iterator it = + mux_instance_to_net_map.find(sink_instance_name); if (it != mux_instance_to_net_map.end()) { /* See if the net id matches. If does not match, we should disable! */ if (mapped_net != mux_instance_to_net_map.at(sink_instance_name)) { @@ -96,9 +101,12 @@ void disable_analysis_module_input_pin_net_sinks(std::fstream& fp, continue; } - BasicPort sink_port = module_manager.module_port(sink_module, module_manager.net_sink_ports(parent_module, module_net)[sink_id]); - sink_port.set_width(module_manager.net_sink_pins(parent_module, module_net)[sink_id], - module_manager.net_sink_pins(parent_module, module_net)[sink_id]); + BasicPort sink_port = module_manager.module_port( + sink_module, + module_manager.net_sink_ports(parent_module, module_net)[sink_id]); + sink_port.set_width( + module_manager.net_sink_pins(parent_module, module_net)[sink_id], + module_manager.net_sink_pins(parent_module, module_net)[sink_id]); VTR_ASSERT(!sink_instance_name.empty()); /* Get the input id that is used! Disable the unused inputs! */ @@ -111,51 +119,53 @@ void disable_analysis_module_input_pin_net_sinks(std::fstream& fp, } /******************************************************************** - * Disable all the unused inputs of routing multiplexers, which are not used by benchmark - * Here, we start from each input of a routing module, and traverse forward to the sink - * port of the module net whose source is the input - * We will find the instance name which is the parent of the sink port, and search the - * net id through the instance_name_to_net_map - * The the net id does not match the net id of this input, we will disable the sink port! + * Disable all the unused inputs of routing multiplexers, which are not used by + *benchmark Here, we start from each input of a routing module, and traverse + *forward to the sink port of the module net whose source is the input We will + *find the instance name which is the parent of the sink port, and search the + * net id through the instance_name_to_net_map + * The the net id does not match the net id of this input, we will disable the + *sink port! * * parent_module * +----------------------- * | MUX instance A * | +----------- - * input_port--->|--+---x-->| sink port (disable! net_id = Y) + * input_port--->|--+---x-->| sink port (disable! net_id = Y) * (net_id = X) | | +---------- * | | MUX instance B * | | +---------- * | +------>| sink port (do not disable! net_id = X) * *******************************************************************/ -void disable_analysis_module_input_port_net_sinks(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const std::string& parent_instance_name, - const ModulePortId& module_input_port, - const AtomNetId& mapped_net, - const std::map mux_instance_to_net_map) { +void disable_analysis_module_input_port_net_sinks( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& parent_module, const std::string& parent_instance_name, + const ModulePortId& module_input_port, const AtomNetId& mapped_net, + const std::map mux_instance_to_net_map) { /* Validate file stream */ valid_file_stream(fp); /* Find the module net which sources from this port! */ - for (const size_t& pin : module_manager.module_port(parent_module, module_input_port).pins()) { - disable_analysis_module_input_pin_net_sinks(fp, module_manager, parent_module, - parent_instance_name, - module_input_port, pin, - mapped_net, - mux_instance_to_net_map); + for (const size_t& pin : + module_manager.module_port(parent_module, module_input_port).pins()) { + disable_analysis_module_input_pin_net_sinks( + fp, module_manager, parent_module, parent_instance_name, + module_input_port, pin, mapped_net, mux_instance_to_net_map); } } /******************************************************************** - * Disable all the unused inputs of routing multiplexers, which are not used by benchmark - * Here, we start from each output of a child module, and traverse forward to the sink + * Disable all the unused inputs of routing multiplexers, which are not used by + benchmark + * Here, we start from each output of a child module, and traverse forward to + the sink * port of the module net whose source is the input - * We will find the instance name which is the parent of the sink port, and search the - * net id through the instance_name_to_net_map - * The the net id does not match the net id of this input, we will disable the sink port! + * We will find the instance name which is the parent of the sink port, and + search the + * net id through the instance_name_to_net_map + * The the net id does not match the net id of this input, we will disable the + sink port! * * Parent_module * +--------------------------------------------- @@ -171,43 +181,48 @@ void disable_analysis_module_input_port_net_sinks(std::fstream& fp, * *******************************************************************/ -void disable_analysis_module_output_pin_net_sinks(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const std::string& parent_instance_name, - const ModuleId& child_module, - const size_t& child_instance, - const ModulePortId& child_module_port, - const size_t& child_module_pin, - const AtomNetId& mapped_net, - const std::map mux_instance_to_net_map) { +void disable_analysis_module_output_pin_net_sinks( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& parent_module, const std::string& parent_instance_name, + const ModuleId& child_module, const size_t& child_instance, + const ModulePortId& child_module_port, const size_t& child_module_pin, + const AtomNetId& mapped_net, + const std::map mux_instance_to_net_map) { /* Validate file stream */ valid_file_stream(fp); /* Find the module net which sources from this port! */ - ModuleNetId module_net = module_manager.module_instance_port_net(parent_module, child_module, child_instance, child_module_port, child_module_pin); - VTR_ASSERT(true == module_manager.valid_module_net_id(parent_module, module_net)); + ModuleNetId module_net = module_manager.module_instance_port_net( + parent_module, child_module, child_instance, child_module_port, + child_module_pin); + VTR_ASSERT(true == + module_manager.valid_module_net_id(parent_module, module_net)); /* Touch each sink of the net! */ - for (const ModuleNetSinkId& sink_id : module_manager.module_net_sinks(parent_module, module_net)) { - ModuleId sink_module = module_manager.net_sink_modules(parent_module, module_net)[sink_id]; - size_t sink_instance = module_manager.net_sink_instances(parent_module, module_net)[sink_id]; + for (const ModuleNetSinkId& sink_id : + module_manager.module_net_sinks(parent_module, module_net)) { + ModuleId sink_module = + module_manager.net_sink_modules(parent_module, module_net)[sink_id]; + size_t sink_instance = + module_manager.net_sink_instances(parent_module, module_net)[sink_id]; - /* Skip when sink module is the parent module, - * the output ports of parent modules have been disabled/enabled already! + /* Skip when sink module is the parent module, + * the output ports of parent modules have been disabled/enabled already! */ if (sink_module == parent_module) { continue; } - std::string sink_instance_name = module_manager.instance_name(parent_module, sink_module, sink_instance); + std::string sink_instance_name = + module_manager.instance_name(parent_module, sink_module, sink_instance); bool disable_timing = false; /* Check if this node is used by benchmark */ if (AtomNetId::INVALID() == mapped_net) { /* Disable all the sinks! */ disable_timing = true; } else { - std::map::const_iterator it = mux_instance_to_net_map.find(sink_instance_name); + std::map::const_iterator it = + mux_instance_to_net_map.find(sink_instance_name); if (it != mux_instance_to_net_map.end()) { /* See if the net id matches. If does not match, we should disable! */ if (mapped_net != mux_instance_to_net_map.at(sink_instance_name)) { @@ -221,9 +236,12 @@ void disable_analysis_module_output_pin_net_sinks(std::fstream& fp, continue; } - BasicPort sink_port = module_manager.module_port(sink_module, module_manager.net_sink_ports(parent_module, module_net)[sink_id]); - sink_port.set_width(module_manager.net_sink_pins(parent_module, module_net)[sink_id], - module_manager.net_sink_pins(parent_module, module_net)[sink_id]); + BasicPort sink_port = module_manager.module_port( + sink_module, + module_manager.net_sink_ports(parent_module, module_net)[sink_id]); + sink_port.set_width( + module_manager.net_sink_pins(parent_module, module_net)[sink_id], + module_manager.net_sink_pins(parent_module, module_net)[sink_id]); VTR_ASSERT(!sink_instance_name.empty()); /* Get the input id that is used! Disable the unused inputs! */ diff --git a/openfpga/src/fpga_sdc/analysis_sdc_writer_utils.h b/openfpga/src/fpga_sdc/analysis_sdc_writer_utils.h index fa757622a..118de63e1 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_writer_utils.h +++ b/openfpga/src/fpga_sdc/analysis_sdc_writer_utils.h @@ -5,11 +5,12 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include #include +#include + +#include "atom_netlist_fwd.h" #include "module_manager.h" #include "rr_graph_fwd.h" -#include "atom_netlist_fwd.h" #include "vpr_routing_annotation.h" /******************************************************************** @@ -19,36 +20,29 @@ /* begin namespace openfpga */ namespace openfpga { -bool is_rr_node_to_be_disable_for_analysis(const VprRoutingAnnotation& routing_annotation, - const RRNodeId& cur_rr_node); +bool is_rr_node_to_be_disable_for_analysis( + const VprRoutingAnnotation& routing_annotation, const RRNodeId& cur_rr_node); -void disable_analysis_module_input_pin_net_sinks(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const std::string& parent_instance_name, - const ModulePortId& module_input_port, - const size_t& module_input_pin, - const AtomNetId& mapped_net, - const std::map mux_instance_to_net_map); +void disable_analysis_module_input_pin_net_sinks( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& parent_module, const std::string& parent_instance_name, + const ModulePortId& module_input_port, const size_t& module_input_pin, + const AtomNetId& mapped_net, + const std::map mux_instance_to_net_map); -void disable_analysis_module_input_port_net_sinks(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const std::string& parent_instance_name, - const ModulePortId& module_input_port, - const AtomNetId& mapped_net, - const std::map mux_instance_to_net_map); +void disable_analysis_module_input_port_net_sinks( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& parent_module, const std::string& parent_instance_name, + const ModulePortId& module_input_port, const AtomNetId& mapped_net, + const std::map mux_instance_to_net_map); -void disable_analysis_module_output_pin_net_sinks(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const std::string& parent_instance_name, - const ModuleId& child_module, - const size_t& child_instance, - const ModulePortId& child_module_port, - const size_t& child_module_pin, - const AtomNetId& mapped_net, - const std::map mux_instance_to_net_map); +void disable_analysis_module_output_pin_net_sinks( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& parent_module, const std::string& parent_instance_name, + const ModuleId& child_module, const size_t& child_instance, + const ModulePortId& child_module_port, const size_t& child_module_pin, + const AtomNetId& mapped_net, + const std::map mux_instance_to_net_map); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.cpp b/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.cpp index b64ce473e..1eadf6fda 100644 --- a/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.cpp +++ b/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.cpp @@ -1,7 +1,7 @@ /******************************************************************** - * This file includes functions that print SDC (Synopsys Design Constraint) + * This file includes functions that print SDC (Synopsys Design Constraint) * files in physical design tools, i.e., Place & Route (PnR) tools - * The SDC files are used to constrain the timing of configuration chain + * The SDC files are used to constrain the timing of configuration chain * * Note that this is different from the SDC to constrain VPR Place&Route * engine! These SDCs are designed for PnR to generate FPGA layouts!!! @@ -12,18 +12,16 @@ /* Headers from vtrutil library */ #include "vtr_assert.h" -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_scale.h" -#include "openfpga_port.h" -#include "openfpga_digest.h" - -#include "openfpga_naming.h" - -#include "sdc_writer_utils.h" #include "configuration_chain_sdc_writer.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" +#include "openfpga_scale.h" +#include "sdc_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -31,55 +29,56 @@ namespace openfpga { /******************************************************************** * Print SDC commands to constrain the timing between outputs and inputs * of all the configurable memory modules - * + * * |<------Max/Min delay-->| - * | | + * | | * +------+ out in +------+ * | CCFF |---------------------->| CCFF | * +------+ +------+ * - * This function will be executed in a recursive way, + * This function will be executed in a recursive way, * using a Depth-First Search (DFS) strategy * It will iterate over all the configurable children under each module * and print a SDC command * *******************************************************************/ -static -void rec_print_pnr_sdc_constrain_configurable_chain(std::fstream& fp, - const float& tmax, - const float& tmin, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const std::string& parent_module_path, - std::string& previous_module_path, - ModuleId& previous_module) { - +static void rec_print_pnr_sdc_constrain_configurable_chain( + std::fstream& fp, const float& tmax, const float& tmin, + const ModuleManager& module_manager, const ModuleId& parent_module, + const std::string& parent_module_path, std::string& previous_module_path, + ModuleId& previous_module) { /* For each configurable child, we will go one level down in priority */ - for (size_t child_index = 0; child_index < module_manager.configurable_children(parent_module).size(); ++child_index) { + for (size_t child_index = 0; + child_index < module_manager.configurable_children(parent_module).size(); + ++child_index) { std::string child_module_path = parent_module_path; - ModuleId child_module_id = module_manager.configurable_children(parent_module)[child_index]; - size_t child_instance_id = module_manager.configurable_child_instances(parent_module)[child_index]; + ModuleId child_module_id = + module_manager.configurable_children(parent_module)[child_index]; + size_t child_instance_id = + module_manager.configurable_child_instances(parent_module)[child_index]; std::string child_instance_name; - if (true == module_manager.instance_name(parent_module, child_module_id, child_instance_id).empty()) { - child_instance_name = generate_instance_name(module_manager.module_name(child_module_id), child_instance_id); + if (true == + module_manager + .instance_name(parent_module, child_module_id, child_instance_id) + .empty()) { + child_instance_name = generate_instance_name( + module_manager.module_name(child_module_id), child_instance_id); } else { - child_instance_name = module_manager.instance_name(parent_module, child_module_id, child_instance_id); + child_instance_name = module_manager.instance_name( + parent_module, child_module_id, child_instance_id); } child_module_path += child_instance_name; - + child_module_path = format_dir_path(child_module_path); - rec_print_pnr_sdc_constrain_configurable_chain(fp, - tmax, tmin, - module_manager, - child_module_id, - child_module_path, - previous_module_path, - previous_module); + rec_print_pnr_sdc_constrain_configurable_chain( + fp, tmax, tmin, module_manager, child_module_id, child_module_path, + previous_module_path, previous_module); } - /* If there is no configurable children any more, this is a leaf module, print a SDC command for disable timing */ + /* If there is no configurable children any more, this is a leaf module, print + * a SDC command for disable timing */ if (0 < module_manager.configurable_children(parent_module).size()) { return; } @@ -90,7 +89,8 @@ void rec_print_pnr_sdc_constrain_configurable_chain(std::fstream& fp, /* Disable timing for each output port of this module */ if (!previous_module_path.empty()) { bool first_port = true; - for (const BasicPort& output_port : module_manager.module_ports_by_type(previous_module, ModuleManager::MODULE_OUTPUT_PORT)) { + for (const BasicPort& output_port : module_manager.module_ports_by_type( + previous_module, ModuleManager::MODULE_OUTPUT_PORT)) { /* Only the first output port will be considered, * being consistent with build_memory_module.cpp:395 */ @@ -98,22 +98,17 @@ void rec_print_pnr_sdc_constrain_configurable_chain(std::fstream& fp, continue; } - for (const BasicPort& input_port : module_manager.module_ports_by_type(parent_module, ModuleManager::MODULE_INPUT_PORT)) { - print_pnr_sdc_constrain_max_delay(fp, - previous_module_path, - output_port.get_name(), - parent_module_path, - input_port.get_name(), - tmax); + for (const BasicPort& input_port : module_manager.module_ports_by_type( + parent_module, ModuleManager::MODULE_INPUT_PORT)) { + print_pnr_sdc_constrain_max_delay( + fp, previous_module_path, output_port.get_name(), parent_module_path, + input_port.get_name(), tmax); - print_pnr_sdc_constrain_min_delay(fp, - previous_module_path, - output_port.get_name(), - parent_module_path, - input_port.get_name(), - tmin); + print_pnr_sdc_constrain_min_delay( + fp, previous_module_path, output_port.get_name(), parent_module_path, + input_port.get_name(), tmin); } - + first_port = false; } } @@ -123,24 +118,22 @@ void rec_print_pnr_sdc_constrain_configurable_chain(std::fstream& fp, previous_module = parent_module; } - /******************************************************************** * Break combinational loops in FPGA fabric, which mainly come from - * configurable memory cells. + * configurable memory cells. * To handle this, we disable the outputs of memory cells *******************************************************************/ -void print_pnr_sdc_constrain_configurable_chain(const std::string& sdc_fname, - const float& time_unit, - const float& max_delay, - const float& min_delay, - const bool& include_time_stamp, - const ModuleManager& module_manager) { - +void print_pnr_sdc_constrain_configurable_chain( + const std::string& sdc_fname, const float& time_unit, const float& max_delay, + const float& min_delay, const bool& include_time_stamp, + const ModuleManager& module_manager) { /* Create the directory */ create_directory(find_path_dir_name(sdc_fname)); /* Start time count */ - std::string timer_message = std::string("Write SDC to constrain configurable chain for P&R flow '") + sdc_fname + std::string("'"); + std::string timer_message = + std::string("Write SDC to constrain configurable chain for P&R flow '") + + sdc_fname + std::string("'"); vtr::ScopedStartFinishTimer timer(timer_message); /* Create the file stream */ @@ -150,9 +143,9 @@ void print_pnr_sdc_constrain_configurable_chain(const std::string& sdc_fname, check_file_stream(sdc_fname.c_str(), fp); /* Generate the descriptions*/ - print_sdc_file_header(fp, - std::string("Timing constraints for configurable chains used in PnR"), - include_time_stamp); + print_sdc_file_header( + fp, std::string("Timing constraints for configurable chains used in PnR"), + include_time_stamp); /* Print time unit for the SDC file */ print_sdc_timescale(fp, time_unit_to_string(time_unit)); @@ -161,15 +154,14 @@ void print_pnr_sdc_constrain_configurable_chain(const std::string& sdc_fname, ModuleId top_module = module_manager.find_module(top_module_name); VTR_ASSERT(true == module_manager.valid_module_id(top_module)); - /* Go recursively in the module manager, starting from the top-level module: instance id of the top-level module is 0 by default */ + /* Go recursively in the module manager, starting from the top-level module: + * instance id of the top-level module is 0 by default */ std::string previous_module_path; ModuleId previous_module = ModuleId::INVALID(); - rec_print_pnr_sdc_constrain_configurable_chain(fp, - max_delay, min_delay, - module_manager, top_module, - format_dir_path(module_manager.module_name(top_module)), - previous_module_path, - previous_module); + rec_print_pnr_sdc_constrain_configurable_chain( + fp, max_delay, min_delay, module_manager, top_module, + format_dir_path(module_manager.module_name(top_module)), + previous_module_path, previous_module); /* Close file handler */ fp.close(); diff --git a/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.h b/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.h index a7a14a223..2bb62e0d3 100644 --- a/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.h +++ b/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.h @@ -6,6 +6,7 @@ *******************************************************************/ #include #include + #include "module_manager.h" /******************************************************************** @@ -15,12 +16,10 @@ /* begin namespace openfpga */ namespace openfpga { -void print_pnr_sdc_constrain_configurable_chain(const std::string& sdc_fname, - const float& time_unit, - const float& max_delay, - const float& min_delay, - const bool& include_time_stamp, - const ModuleManager& module_manager); +void print_pnr_sdc_constrain_configurable_chain( + const std::string& sdc_fname, const float& time_unit, const float& max_delay, + const float& min_delay, const bool& include_time_stamp, + const ModuleManager& module_manager); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/configure_port_sdc_writer.cpp b/openfpga/src/fpga_sdc/configure_port_sdc_writer.cpp index c78259b59..45ad1ebd7 100644 --- a/openfpga/src/fpga_sdc/configure_port_sdc_writer.cpp +++ b/openfpga/src/fpga_sdc/configure_port_sdc_writer.cpp @@ -1,7 +1,7 @@ /******************************************************************** - * This file includes functions that print SDC (Synopsys Design Constraint) + * This file includes functions that print SDC (Synopsys Design Constraint) * files in physical design tools, i.e., Place & Route (PnR) tools - * The SDC files are used to constrain the timing of configuration chain + * The SDC files are used to constrain the timing of configuration chain * * Note that this is different from the SDC to constrain VPR Place&Route * engine! These SDCs are designed for PnR to generate FPGA layouts!!! @@ -12,32 +12,29 @@ /* Headers from vtrutil library */ #include "vtr_assert.h" -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgashell library */ #include "command_exit_codes.h" /* Headers from openfpgautil library */ -#include "openfpga_scale.h" -#include "openfpga_port.h" -#include "openfpga_digest.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" - #include "circuit_library_utils.h" - +#include "configure_port_sdc_writer.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" +#include "openfpga_reserved_words.h" +#include "openfpga_scale.h" +#include "sdc_mux_utils.h" #include "sdc_writer_naming.h" #include "sdc_writer_utils.h" -#include "sdc_mux_utils.h" -#include "configure_port_sdc_writer.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * Break combinational loops in FPGA fabric, which mainly come from + * Break combinational loops in FPGA fabric, which mainly come from * Look-Up Table programmable modules * To handle this, we disable the timing at configuration ports * @@ -45,20 +42,16 @@ namespace openfpga { * 0: success * 1: fatal error occurred *******************************************************************/ -static -int print_sdc_disable_lut_configure_ports(std::fstream& fp, - const bool& flatten_names, - const CircuitLibrary& circuit_lib, - const ModuleManager& module_manager, - const ModuleId& top_module) { - +static int print_sdc_disable_lut_configure_ports( + std::fstream& fp, const bool& flatten_names, + const CircuitLibrary& circuit_lib, const ModuleManager& module_manager, + const ModuleId& top_module) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } /* Iterate over the MUX modules */ for (const CircuitModelId& model : circuit_lib.models()) { - /* Only care LUTs */ if (CIRCUIT_MODEL_LUT != circuit_lib.model_type(model)) { continue; @@ -67,39 +60,43 @@ int print_sdc_disable_lut_configure_ports(std::fstream& fp, std::string programmable_module_name = circuit_lib.model_name(model); /* Find the module name in module manager */ - ModuleId programmable_module = module_manager.find_module(programmable_module_name); + ModuleId programmable_module = + module_manager.find_module(programmable_module_name); VTR_ASSERT(true == module_manager.valid_module_id(programmable_module)); - /* Go recursively in the module manager, - * starting from the top-level module: instance id of the top-level module is 0 by default - * Disable all the outputs of child modules that matches the mux_module id + /* Go recursively in the module manager, + * starting from the top-level module: instance id of the top-level module + * is 0 by default Disable all the outputs of child modules that matches the + * mux_module id */ - for (const CircuitPortId& sram_port : circuit_lib.model_ports_by_type(model, CIRCUIT_MODEL_PORT_SRAM)) { + for (const CircuitPortId& sram_port : + circuit_lib.model_ports_by_type(model, CIRCUIT_MODEL_PORT_SRAM)) { const std::string& sram_port_name = circuit_lib.port_lib_name(sram_port); - VTR_ASSERT(true == module_manager.valid_module_port_id(programmable_module, module_manager.find_module_port(programmable_module, sram_port_name))); - if (CMD_EXEC_FATAL_ERROR == - rec_print_sdc_disable_timing_for_module_ports(fp, - flatten_names, - module_manager, - top_module, - programmable_module, - format_dir_path(module_manager.module_name(top_module)), - sram_port_name)) { + VTR_ASSERT( + true == module_manager.valid_module_port_id( + programmable_module, module_manager.find_module_port( + programmable_module, sram_port_name))); + if (CMD_EXEC_FATAL_ERROR == + rec_print_sdc_disable_timing_for_module_ports( + fp, flatten_names, module_manager, top_module, programmable_module, + format_dir_path(module_manager.module_name(top_module)), + sram_port_name)) { return CMD_EXEC_FATAL_ERROR; } - const std::string& sram_inv_port_name = circuit_lib.port_lib_name(sram_port) + INV_PORT_POSTFIX; - if (false == module_manager.valid_module_port_id(programmable_module, module_manager.find_module_port(programmable_module, sram_inv_port_name))) { + const std::string& sram_inv_port_name = + circuit_lib.port_lib_name(sram_port) + INV_PORT_POSTFIX; + if (false == + module_manager.valid_module_port_id( + programmable_module, module_manager.find_module_port( + programmable_module, sram_inv_port_name))) { continue; } - if (CMD_EXEC_FATAL_ERROR == - rec_print_sdc_disable_timing_for_module_ports(fp, - flatten_names, - module_manager, - top_module, - programmable_module, - format_dir_path(module_manager.module_name(top_module)), - sram_inv_port_name)) { + if (CMD_EXEC_FATAL_ERROR == + rec_print_sdc_disable_timing_for_module_ports( + fp, flatten_names, module_manager, top_module, programmable_module, + format_dir_path(module_manager.module_name(top_module)), + sram_inv_port_name)) { return CMD_EXEC_FATAL_ERROR; } } @@ -109,7 +106,7 @@ int print_sdc_disable_lut_configure_ports(std::fstream& fp, } /******************************************************************** - * Break combinational loops in FPGA fabric, which mainly come from + * Break combinational loops in FPGA fabric, which mainly come from * non-MUX programmable modules * To handle this, we disable the timing at configuration ports * @@ -117,20 +114,16 @@ int print_sdc_disable_lut_configure_ports(std::fstream& fp, * 0: success * 1: fatal error occurred *******************************************************************/ -static -int print_sdc_disable_non_mux_circuit_configure_ports(std::fstream& fp, - const bool& flatten_names, - const CircuitLibrary& circuit_lib, - const ModuleManager& module_manager, - const ModuleId& top_module) { - +static int print_sdc_disable_non_mux_circuit_configure_ports( + std::fstream& fp, const bool& flatten_names, + const CircuitLibrary& circuit_lib, const ModuleManager& module_manager, + const ModuleId& top_module) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } /* Iterate over the MUX modules */ for (const CircuitModelId& model : circuit_lib.models()) { - /* Skip MUXes, they are handled in another function */ if (CIRCUIT_MODEL_MUX == circuit_lib.model_type(model)) { continue; @@ -142,31 +135,35 @@ int print_sdc_disable_non_mux_circuit_configure_ports(std::fstream& fp, } /* We care programmable circuit models only */ - if (0 == circuit_lib.model_ports_by_type(model, CIRCUIT_MODEL_PORT_SRAM).size()) { + if (0 == circuit_lib.model_ports_by_type(model, CIRCUIT_MODEL_PORT_SRAM) + .size()) { continue; } std::string programmable_module_name = circuit_lib.model_name(model); /* Find the module name in module manager */ - ModuleId programmable_module = module_manager.find_module(programmable_module_name); + ModuleId programmable_module = + module_manager.find_module(programmable_module_name); VTR_ASSERT(true == module_manager.valid_module_id(programmable_module)); - /* Go recursively in the module manager, - * starting from the top-level module: instance id of the top-level module is 0 by default - * Disable all the outputs of child modules that matches the mux_module id + /* Go recursively in the module manager, + * starting from the top-level module: instance id of the top-level module + * is 0 by default Disable all the outputs of child modules that matches the + * mux_module id */ - for (const CircuitPortId& sram_port : find_circuit_mode_select_sram_ports(circuit_lib, model)) { + for (const CircuitPortId& sram_port : + find_circuit_mode_select_sram_ports(circuit_lib, model)) { const std::string& sram_port_name = circuit_lib.port_lib_name(sram_port); - VTR_ASSERT(true == module_manager.valid_module_port_id(programmable_module, module_manager.find_module_port(programmable_module, sram_port_name))); - if (CMD_EXEC_FATAL_ERROR == - rec_print_sdc_disable_timing_for_module_ports(fp, - flatten_names, - module_manager, - top_module, - programmable_module, - format_dir_path(module_manager.module_name(top_module)), - sram_port_name)) { + VTR_ASSERT( + true == module_manager.valid_module_port_id( + programmable_module, module_manager.find_module_port( + programmable_module, sram_port_name))); + if (CMD_EXEC_FATAL_ERROR == + rec_print_sdc_disable_timing_for_module_ports( + fp, flatten_names, module_manager, top_module, programmable_module, + format_dir_path(module_manager.module_name(top_module)), + sram_port_name)) { return CMD_EXEC_FATAL_ERROR; } } @@ -177,23 +174,25 @@ int print_sdc_disable_non_mux_circuit_configure_ports(std::fstream& fp, /******************************************************************** * Break combinational loops in FPGA fabric, which mainly come from - * the configure ports of each programmable module. - * To handle this, we disable the configure ports of + * the configure ports of each programmable module. + * To handle this, we disable the configure ports of * - routing multiplexers * - other circuit model that has SRAM ports *******************************************************************/ -int print_sdc_disable_timing_configure_ports(const std::string& sdc_fname, - const bool& flatten_names, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const ModuleManager& module_manager, - const bool& include_time_stamp, - const bool& verbose) { +int print_sdc_disable_timing_configure_ports( + const std::string& sdc_fname, const bool& flatten_names, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, + const ModuleManager& module_manager, const bool& include_time_stamp, + const bool& verbose) { /* Create the directory */ create_directory(find_path_dir_name(sdc_fname)); /* Start time count */ - std::string timer_message = std::string("Write SDC to disable timing on configuration outputs of programmable cells for P&R flow '") + sdc_fname + std::string("'"); + std::string timer_message = + std::string( + "Write SDC to disable timing on configuration outputs of programmable " + "cells for P&R flow '") + + sdc_fname + std::string("'"); vtr::ScopedStartFinishTimer timer(timer_message); /* Create the file stream */ @@ -203,9 +202,11 @@ int print_sdc_disable_timing_configure_ports(const std::string& sdc_fname, check_file_stream(sdc_fname.c_str(), fp); /* Generate the descriptions*/ - print_sdc_file_header(fp, - std::string("Disable configuration outputs of all the programmable cells for PnR"), - include_time_stamp); + print_sdc_file_header( + fp, + std::string( + "Disable configuration outputs of all the programmable cells for PnR"), + include_time_stamp); std::string top_module_name = generate_fpga_top_module_name(); ModuleId top_module = module_manager.find_module(top_module_name); @@ -213,40 +214,30 @@ int print_sdc_disable_timing_configure_ports(const std::string& sdc_fname, /* Disable timing for the configure ports of all the Look-Up Tables */ VTR_LOGV(verbose, "Write disable timing for Look-Up Tables..."); - if (CMD_EXEC_FATAL_ERROR == print_sdc_disable_lut_configure_ports(fp, - flatten_names, - circuit_lib, - module_manager, - top_module)) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Fatal errors occurred\n"); + if (CMD_EXEC_FATAL_ERROR == + print_sdc_disable_lut_configure_ports(fp, flatten_names, circuit_lib, + module_manager, top_module)) { + VTR_LOGF_ERROR(__FILE__, __LINE__, "Fatal errors occurred\n"); return CMD_EXEC_FATAL_ERROR; } VTR_LOGV(verbose, "Done\n"); - + /* Disable timing for the configure ports of all the routing multiplexer */ VTR_LOGV(verbose, "Write disable timing for routing multiplexers..."); - if (CMD_EXEC_FATAL_ERROR == print_sdc_disable_routing_multiplexer_configure_ports(fp, - flatten_names, - mux_lib, - circuit_lib, - module_manager, - top_module)) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Fatal errors occurred\n"); + if (CMD_EXEC_FATAL_ERROR == + print_sdc_disable_routing_multiplexer_configure_ports( + fp, flatten_names, mux_lib, circuit_lib, module_manager, top_module)) { + VTR_LOGF_ERROR(__FILE__, __LINE__, "Fatal errors occurred\n"); return CMD_EXEC_FATAL_ERROR; } VTR_LOGV(verbose, "Done\n"); /* Disable timing for the other programmable circuit models */ VTR_LOGV(verbose, "Write disable timing for other programmable modules..."); - if (CMD_EXEC_FATAL_ERROR == print_sdc_disable_non_mux_circuit_configure_ports(fp, - flatten_names, - circuit_lib, - module_manager, - top_module)) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Fatal errors occurred\n"); + if (CMD_EXEC_FATAL_ERROR == + print_sdc_disable_non_mux_circuit_configure_ports( + fp, flatten_names, circuit_lib, module_manager, top_module)) { + VTR_LOGF_ERROR(__FILE__, __LINE__, "Fatal errors occurred\n"); return CMD_EXEC_FATAL_ERROR; } VTR_LOGV(verbose, "Done\n"); diff --git a/openfpga/src/fpga_sdc/configure_port_sdc_writer.h b/openfpga/src/fpga_sdc/configure_port_sdc_writer.h index bcbe390cc..191c8ae8b 100644 --- a/openfpga/src/fpga_sdc/configure_port_sdc_writer.h +++ b/openfpga/src/fpga_sdc/configure_port_sdc_writer.h @@ -6,6 +6,7 @@ *******************************************************************/ #include #include + #include "module_manager.h" /******************************************************************** @@ -15,13 +16,11 @@ /* begin namespace openfpga */ namespace openfpga { -int print_sdc_disable_timing_configure_ports(const std::string& sdc_fname, - const bool& flatten_names, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const ModuleManager& module_manager, - const bool& include_time_stamp, - const bool& verbose); +int print_sdc_disable_timing_configure_ports( + const std::string& sdc_fname, const bool& flatten_names, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, + const ModuleManager& module_manager, const bool& include_time_stamp, + const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp b/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp index e46dde2d9..d3549cea2 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp @@ -1,8 +1,8 @@ /******************************************************************** - * This file includes functions that print SDC (Synopsys Design Constraint) + * This file includes functions that print SDC (Synopsys Design Constraint) * files in physical design tools, i.e., Place & Route (PnR) tools * The SDC files are used to constrain global ports for each module - * in FPGA fabric, such as Configurable Logic Blocks (CLBs), + * in FPGA fabric, such as Configurable Logic Blocks (CLBs), * Heterogeneous blocks, Switch Blocks (SBs) and Connection Blocks (CBs) * * Note that this is different from the SDC to constrain VPR Place&Route @@ -14,17 +14,16 @@ /* Headers from vtrutil library */ #include "vtr_assert.h" -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_port.h" #include "openfpga_digest.h" +#include "openfpga_port.h" #include "openfpga_scale.h" - +#include "pnr_sdc_global_port.h" #include "sdc_writer_naming.h" #include "sdc_writer_utils.h" -#include "pnr_sdc_global_port.h" /* begin namespace openfpga */ namespace openfpga { @@ -32,15 +31,14 @@ namespace openfpga { /******************************************************************** * Print SDC constraint for a clock port * This format is derived from the open-source SDC syntax, - * which is supposed to be generic + * which is supposed to be generic * * This function is design to the SDC writer for any port * wants to be treated as a clock port *******************************************************************/ -static -void print_pnr_sdc_clock_port(std::fstream& fp, - const BasicPort& port_to_constrain, - const float& clock_period) { +static void print_pnr_sdc_clock_port(std::fstream& fp, + const BasicPort& port_to_constrain, + const float& clock_period) { valid_file_stream(fp); fp << "create_clock"; @@ -49,105 +47,101 @@ void print_pnr_sdc_clock_port(std::fstream& fp, fp << " -waveform {0 " << std::setprecision(10) << clock_period / 2 << "}"; fp << " [get_ports {" << generate_sdc_port(port_to_constrain) << "}]"; fp << std::endl; -} +} /******************************************************************** - * Print SDC constraints for the clock ports which are the global ports + * Print SDC constraints for the clock ports which are the global ports * of FPGA fabric - * + * * For programming clock, we give a fixed period, while for operating - * clock, we constrain with critical path delay + * clock, we constrain with critical path delay *******************************************************************/ -static -void print_pnr_sdc_global_clock_ports(std::fstream& fp, - const float& time_unit, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricGlobalPortInfo& fabric_global_port_info, - const SimulationSetting& sim_setting) { - +static void print_pnr_sdc_global_clock_ports( + std::fstream& fp, const float& time_unit, const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info, + const SimulationSetting& sim_setting) { valid_file_stream(fp); /* Get clock port from the global port */ - for (const FabricGlobalPortId& global_port : fabric_global_port_info.global_ports()) { + for (const FabricGlobalPortId& global_port : + fabric_global_port_info.global_ports()) { if (false == fabric_global_port_info.global_port_is_clock(global_port)) { continue; } /* Reach here, it means a clock port and we need print constraints */ - float clock_period = 1./sim_setting.default_operating_clock_frequency(); + float clock_period = 1. / sim_setting.default_operating_clock_frequency(); /* For programming clock, we give a fixed period */ if (true == fabric_global_port_info.global_port_is_prog(global_port)) { - clock_period = 1./sim_setting.programming_clock_frequency(); + clock_period = 1. / sim_setting.programming_clock_frequency(); /* Print comments */ - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; fp << "# Create programmable clock " << std::endl; - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; } else { /* Print comments */ - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; fp << "# Create clock " << std::endl; - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; } - BasicPort clock_port = module_manager.module_port(top_module, fabric_global_port_info.global_module_port(global_port)); + BasicPort clock_port = module_manager.module_port( + top_module, fabric_global_port_info.global_module_port(global_port)); for (const size_t& pin : clock_port.pins()) { BasicPort port_to_constrain(clock_port.get_name(), pin, pin); /* Should try to find a port defintion from simulation parameters - * If found, it means that we need to use special clock name! + * If found, it means that we need to use special clock name! */ - for (const SimulationClockId& sim_clock : sim_setting.operating_clocks()) { + for (const SimulationClockId& sim_clock : + sim_setting.operating_clocks()) { if (port_to_constrain == sim_setting.clock_port(sim_clock)) { - clock_period = 1./sim_setting.clock_frequency(sim_clock); + clock_period = 1. / sim_setting.clock_frequency(sim_clock); } } - print_pnr_sdc_clock_port(fp, - port_to_constrain, - clock_period / time_unit); + print_pnr_sdc_clock_port(fp, port_to_constrain, clock_period / time_unit); } } } /******************************************************************** - * Print SDC constraints for the non-clock ports which are the global ports + * Print SDC constraints for the non-clock ports which are the global ports * of FPGA fabric * Here, we will the treat the non-clock ports as the clock ports * in the CTS * Note that, this may be applied to the reset, set and other global * signals which do need very balanced delays to each sink *******************************************************************/ -static -void print_pnr_sdc_global_non_clock_ports(std::fstream& fp, - const float& time_unit, - const float& operating_critical_path_delay, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricGlobalPortInfo& fabric_global_port_info) { - +static void print_pnr_sdc_global_non_clock_ports( + std::fstream& fp, const float& time_unit, + const float& operating_critical_path_delay, + const ModuleManager& module_manager, const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info) { valid_file_stream(fp); /* For non-clock port from the global port: give a fixed period */ - for (const FabricGlobalPortId& global_port : fabric_global_port_info.global_ports()) { + for (const FabricGlobalPortId& global_port : + fabric_global_port_info.global_ports()) { if (true == fabric_global_port_info.global_port_is_clock(global_port)) { continue; } /* Print comments */ - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; fp << "# Constrain other global ports " << std::endl; - fp << "##################################################" << std::endl; + fp << "##################################################" << std::endl; - /* Reach here, it means a non-clock global port and we need print constraints */ - float clock_period = operating_critical_path_delay; - BasicPort non_clock_port = module_manager.module_port(top_module, fabric_global_port_info.global_module_port(global_port)); + /* Reach here, it means a non-clock global port and we need print + * constraints */ + float clock_period = operating_critical_path_delay; + BasicPort non_clock_port = module_manager.module_port( + top_module, fabric_global_port_info.global_module_port(global_port)); for (const size_t& pin : non_clock_port.pins()) { BasicPort port_to_constrain(non_clock_port.get_name(), pin, pin); - print_pnr_sdc_clock_port(fp, - port_to_constrain, - clock_period / time_unit); + print_pnr_sdc_clock_port(fp, port_to_constrain, clock_period / time_unit); } } } @@ -158,8 +152,8 @@ void print_pnr_sdc_global_non_clock_ports(std::fstream& fp, * * This ports to appear in this file will be treated in Clock Tree * Synthesis (CTS) - * - * For non-clock global ports, we have an option to select if they + * + * For non-clock global ports, we have an option to select if they * should be treated in CTS or not * In general, we do not recommend to do this *******************************************************************/ @@ -168,7 +162,6 @@ void print_pnr_sdc_global_ports(const PnrSdcOption& options, const ModuleId& top_module, const FabricGlobalPortInfo& global_ports, const SimulationSetting& sim_setting) { - std::string sdc_dir = options.sdc_dir(); float time_unit = options.time_unit(); bool include_time_stamp = options.time_stamp(); @@ -178,7 +171,9 @@ void print_pnr_sdc_global_ports(const PnrSdcOption& options, std::string sdc_fname(sdc_dir + std::string(SDC_GLOBAL_PORTS_FILE_NAME)); /* Start time count */ - std::string timer_message = std::string("Write SDC for constraining clocks for P&R flow '") + sdc_fname + std::string("'"); + std::string timer_message = + std::string("Write SDC for constraining clocks for P&R flow '") + + sdc_fname + std::string("'"); vtr::ScopedStartFinishTimer timer(timer_message); /* Create the file stream */ @@ -188,23 +183,19 @@ void print_pnr_sdc_global_ports(const PnrSdcOption& options, check_file_stream(sdc_fname.c_str(), fp); /* Generate the descriptions*/ - print_sdc_file_header(fp, - std::string("Clock contraints for PnR"), + print_sdc_file_header(fp, std::string("Clock contraints for PnR"), include_time_stamp); /* Print time unit for the SDC file */ print_sdc_timescale(fp, time_unit_to_string(time_unit)); - print_pnr_sdc_global_clock_ports(fp, time_unit, - module_manager, top_module, + print_pnr_sdc_global_clock_ports(fp, time_unit, module_manager, top_module, global_ports, sim_setting); if (true == constrain_non_clock_port) { - print_pnr_sdc_global_non_clock_ports(fp, time_unit, - 1./sim_setting.default_operating_clock_frequency(), - module_manager, top_module, - global_ports); - + print_pnr_sdc_global_non_clock_ports( + fp, time_unit, 1. / sim_setting.default_operating_clock_frequency(), + module_manager, top_module, global_ports); } /* Close file handler */ diff --git a/openfpga/src/fpga_sdc/pnr_sdc_global_port.h b/openfpga/src/fpga_sdc/pnr_sdc_global_port.h index c0d3da94d..3dca3f1e6 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_global_port.h +++ b/openfpga/src/fpga_sdc/pnr_sdc_global_port.h @@ -6,10 +6,11 @@ *******************************************************************/ #include #include -#include "module_manager.h" + #include "fabric_global_port_info.h" -#include "simulation_setting.h" +#include "module_manager.h" #include "pnr_sdc_option.h" +#include "simulation_setting.h" /******************************************************************** * Function declaration diff --git a/openfpga/src/fpga_sdc/pnr_sdc_grid_writer.cpp b/openfpga/src/fpga_sdc/pnr_sdc_grid_writer.cpp index 8d945003e..ae8b42781 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_grid_writer.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_grid_writer.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * This file includes functions that print SDC (Synopsys Design Constraint) + * This file includes functions that print SDC (Synopsys Design Constraint) * files in physical design tools, i.e., Place & Route (PnR) tools * The SDC files are used to constrain the physical design for each grid * (CLBs, heterogeneous blocks etc.) @@ -11,29 +11,26 @@ #include /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_scale.h" -#include "openfpga_port.h" -#include "openfpga_digest.h" -#include "openfpga_side_manager.h" - -#include "openfpga_interconnect_types.h" -#include "vpr_utils.h" #include "mux_utils.h" - -#include "openfpga_reserved_words.h" +#include "openfpga_digest.h" +#include "openfpga_interconnect_types.h" #include "openfpga_naming.h" -#include "pb_type_utils.h" -#include "pb_graph_utils.h" #include "openfpga_physical_tile_utils.h" - +#include "openfpga_port.h" +#include "openfpga_reserved_words.h" +#include "openfpga_scale.h" +#include "openfpga_side_manager.h" +#include "pb_graph_utils.h" +#include "pb_type_utils.h" +#include "pnr_sdc_grid_writer.h" #include "sdc_writer_naming.h" #include "sdc_writer_utils.h" -#include "pnr_sdc_grid_writer.h" +#include "vpr_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -42,34 +39,30 @@ namespace openfpga { * Print pin-to-pin timing constraints for a given interconnection * at an output port of a pb_graph node *******************************************************************/ -static -void print_pnr_sdc_constrain_pb_pin_interc_timing(std::fstream& fp, - const float& time_unit, - const bool& hierarchical, - const std::string& module_path, - const ModuleManager& module_manager, - const ModuleId& parent_module, - t_pb_graph_pin* des_pb_graph_pin, - t_mode* physical_mode, - const bool& constrain_zero_delay_paths) { - - /* Validate file stream */ +static void print_pnr_sdc_constrain_pb_pin_interc_timing( + std::fstream& fp, const float& time_unit, const bool& hierarchical, + const std::string& module_path, const ModuleManager& module_manager, + const ModuleId& parent_module, t_pb_graph_pin* des_pb_graph_pin, + t_mode* physical_mode, const bool& constrain_zero_delay_paths) { + /* Validate file stream */ valid_file_stream(fp); - /* 1. identify pin interconnection type, - * 2. Identify the number of fan-in (Consider interconnection edges of only selected mode) + /* 1. identify pin interconnection type, + * 2. Identify the number of fan-in (Consider interconnection edges of only + * selected mode) * 3. Print SDC timing constraints */ - t_interconnect* cur_interc = pb_graph_pin_interc(des_pb_graph_pin, physical_mode); + t_interconnect* cur_interc = + pb_graph_pin_interc(des_pb_graph_pin, physical_mode); size_t fan_in = pb_graph_pin_inputs(des_pb_graph_pin, cur_interc).size(); - if ((nullptr == cur_interc) || (0 == fan_in)) { + if ((nullptr == cur_interc) || (0 == fan_in)) { /* No interconnection matched */ return; } - /* Print pin-to-pin SDC contraint here */ - /* For more than one mode defined, the direct interc has more than one input_edge , - * We need to find which edge is connected the pin we want + /* Print pin-to-pin SDC contraint here */ + /* For more than one mode defined, the direct interc has more than one + * input_edge , We need to find which edge is connected the pin we want */ for (int iedge = 0; iedge < des_pb_graph_pin->num_input_edges; iedge++) { if (cur_interc != des_pb_graph_pin->input_edges[iedge]->interconnect) { @@ -77,75 +70,99 @@ void print_pnr_sdc_constrain_pb_pin_interc_timing(std::fstream& fp, } /* Source pin, node, pb_type*/ - t_pb_graph_pin* src_pb_graph_pin = des_pb_graph_pin->input_edges[iedge]->input_pins[0]; + t_pb_graph_pin* src_pb_graph_pin = + des_pb_graph_pin->input_edges[iedge]->input_pins[0]; t_pb_graph_node* src_pb_graph_node = src_pb_graph_pin->parent_node; /* Des pin, node, pb_type */ - t_pb_graph_node* des_pb_graph_node = des_pb_graph_pin->parent_node; + t_pb_graph_node* des_pb_graph_node = des_pb_graph_pin->parent_node; /* Find the src module in module manager */ - std::string src_module_name = generate_physical_block_module_name(src_pb_graph_node->pb_type); + std::string src_module_name = + generate_physical_block_module_name(src_pb_graph_node->pb_type); ModuleId src_module = module_manager.find_module(src_module_name); VTR_ASSERT(true == module_manager.valid_module_id(src_module)); - ModulePortId src_module_port_id = module_manager.find_module_port(src_module, generate_pb_type_port_name(src_pb_graph_pin->port)); - VTR_ASSERT(true == module_manager.valid_module_port_id(src_module, src_module_port_id)); + ModulePortId src_module_port_id = module_manager.find_module_port( + src_module, generate_pb_type_port_name(src_pb_graph_pin->port)); + VTR_ASSERT(true == module_manager.valid_module_port_id(src_module, + src_module_port_id)); - /* Generate the name of the des instance name + /* Generate the name of the des instance name * If des module is not the parent module, it is a child module. - * We should find the instance id + * We should find the instance id */ - std::string src_instance_name; + std::string src_instance_name; if (parent_module != src_module) { /* Instance id is actually the placement index */ size_t instance_id = src_pb_graph_node->placement_index; - if (true == module_manager.instance_name(parent_module, src_module, instance_id).empty()) { - src_instance_name += src_module_name; + if (true == + module_manager.instance_name(parent_module, src_module, instance_id) + .empty()) { + src_instance_name += src_module_name; src_instance_name += "_"; src_instance_name += std::to_string(instance_id); src_instance_name += "_"; } else { - VTR_ASSERT_SAFE(true == module_manager.instance_name(parent_module, src_module, instance_id).empty()); - src_instance_name += module_manager.instance_name(parent_module, src_module, instance_id); + VTR_ASSERT_SAFE( + true == + module_manager.instance_name(parent_module, src_module, instance_id) + .empty()); + src_instance_name += + module_manager.instance_name(parent_module, src_module, instance_id); } } /* Generate src port information */ - BasicPort src_port = module_manager.module_port(src_module, src_module_port_id); - src_port.set_width(src_pb_graph_pin->pin_number, src_pb_graph_pin->pin_number); + BasicPort src_port = + module_manager.module_port(src_module, src_module_port_id); + src_port.set_width(src_pb_graph_pin->pin_number, + src_pb_graph_pin->pin_number); /* Find the des module in module manager */ - std::string des_module_name = generate_physical_block_module_name(des_pb_graph_node->pb_type); + std::string des_module_name = + generate_physical_block_module_name(des_pb_graph_node->pb_type); ModuleId des_module = module_manager.find_module(des_module_name); VTR_ASSERT(true == module_manager.valid_module_id(des_module)); - ModulePortId des_module_port_id = module_manager.find_module_port(des_module, generate_pb_type_port_name(des_pb_graph_pin->port)); - VTR_ASSERT(true == module_manager.valid_module_port_id(des_module, des_module_port_id)); + ModulePortId des_module_port_id = module_manager.find_module_port( + des_module, generate_pb_type_port_name(des_pb_graph_pin->port)); + VTR_ASSERT(true == module_manager.valid_module_port_id(des_module, + des_module_port_id)); - /* Generate the name of the des instance name + /* Generate the name of the des instance name * If des module is not the parent module, it is a child module. - * We should find the instance id + * We should find the instance id */ - std::string des_instance_name; + std::string des_instance_name; if (parent_module != des_module) { /* Instance id is actually the placement index */ size_t instance_id = des_pb_graph_node->placement_index; - if (true == module_manager.instance_name(parent_module, des_module, instance_id).empty()) { - des_instance_name += des_module_name; + if (true == + module_manager.instance_name(parent_module, des_module, instance_id) + .empty()) { + des_instance_name += des_module_name; des_instance_name += "_"; des_instance_name += std::to_string(instance_id); des_instance_name += "_"; } else { - VTR_ASSERT_SAFE(true != module_manager.instance_name(parent_module, des_module, instance_id).empty()); - des_instance_name += module_manager.instance_name(parent_module, des_module, instance_id); + VTR_ASSERT_SAFE( + true != + module_manager.instance_name(parent_module, des_module, instance_id) + .empty()); + des_instance_name += + module_manager.instance_name(parent_module, des_module, instance_id); } } /* Generate des port information */ - BasicPort des_port = module_manager.module_port(des_module, des_module_port_id); - des_port.set_width(des_pb_graph_pin->pin_number, des_pb_graph_pin->pin_number); + BasicPort des_port = + module_manager.module_port(des_module, des_module_port_id); + des_port.set_width(des_pb_graph_pin->pin_number, + des_pb_graph_pin->pin_number); - /* If we have a zero-delay path to contrain, we will skip unless users want so */ - if ( (false == constrain_zero_delay_paths) - && (0. == des_pb_graph_pin->input_edges[iedge]->delay_max) ) { + /* If we have a zero-delay path to contrain, we will skip unless users want + * so */ + if ((false == constrain_zero_delay_paths) && + (0. == des_pb_graph_pin->input_edges[iedge]->delay_max)) { continue; } @@ -161,12 +178,10 @@ void print_pnr_sdc_constrain_pb_pin_interc_timing(std::fstream& fp, } /* Print a SDC timing constraint */ - print_pnr_sdc_constrain_max_delay(fp, - src_module_path, - generate_sdc_port(src_port), - des_module_path, - generate_sdc_port(des_port), - des_pb_graph_pin->input_edges[iedge]->delay_max / time_unit); + print_pnr_sdc_constrain_max_delay( + fp, src_module_path, generate_sdc_port(src_port), des_module_path, + generate_sdc_port(des_port), + des_pb_graph_pin->input_edges[iedge]->delay_max / time_unit); } } @@ -174,77 +189,66 @@ void print_pnr_sdc_constrain_pb_pin_interc_timing(std::fstream& fp, * Print port-to-port timing constraints which source from * an output port of a pb_graph node *******************************************************************/ -static -void print_pnr_sdc_constrain_pb_interc_timing(std::fstream& fp, - const float& time_unit, - const bool& hierarchical, - const std::string& module_path, - const ModuleManager& module_manager, - const ModuleId& parent_module, - t_pb_graph_node* des_pb_graph_node, - const e_circuit_pb_port_type& pb_port_type, - t_mode* physical_mode, - const bool& constrain_zero_delay_paths) { - /* Validate file stream */ +static void print_pnr_sdc_constrain_pb_interc_timing( + std::fstream& fp, const float& time_unit, const bool& hierarchical, + const std::string& module_path, const ModuleManager& module_manager, + const ModuleId& parent_module, t_pb_graph_node* des_pb_graph_node, + const e_circuit_pb_port_type& pb_port_type, t_mode* physical_mode, + const bool& constrain_zero_delay_paths) { + /* Validate file stream */ valid_file_stream(fp); switch (pb_port_type) { - case CIRCUIT_PB_PORT_INPUT: { - for (int iport = 0; iport < des_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < des_pb_graph_node->num_input_pins[iport]; ++ipin) { - /* If this is a idle block, we set 0 to the selected edge*/ - /* Get the selected edge of current pin*/ - print_pnr_sdc_constrain_pb_pin_interc_timing(fp, - time_unit, - hierarchical, - module_path, - module_manager, parent_module, - &(des_pb_graph_node->input_pins[iport][ipin]), - physical_mode, - constrain_zero_delay_paths); + case CIRCUIT_PB_PORT_INPUT: { + for (int iport = 0; iport < des_pb_graph_node->num_input_ports; ++iport) { + for (int ipin = 0; ipin < des_pb_graph_node->num_input_pins[iport]; + ++ipin) { + /* If this is a idle block, we set 0 to the selected edge*/ + /* Get the selected edge of current pin*/ + print_pnr_sdc_constrain_pb_pin_interc_timing( + fp, time_unit, hierarchical, module_path, module_manager, + parent_module, &(des_pb_graph_node->input_pins[iport][ipin]), + physical_mode, constrain_zero_delay_paths); + } } + break; } - break; - } - case CIRCUIT_PB_PORT_OUTPUT: { - for (int iport = 0; iport < des_pb_graph_node->num_output_ports; ++iport) { - for (int ipin = 0; ipin < des_pb_graph_node->num_output_pins[iport]; ++ipin) { - print_pnr_sdc_constrain_pb_pin_interc_timing(fp, - time_unit, - hierarchical, - module_path, - module_manager, parent_module, - &(des_pb_graph_node->output_pins[iport][ipin]), - physical_mode, - constrain_zero_delay_paths); + case CIRCUIT_PB_PORT_OUTPUT: { + for (int iport = 0; iport < des_pb_graph_node->num_output_ports; + ++iport) { + for (int ipin = 0; ipin < des_pb_graph_node->num_output_pins[iport]; + ++ipin) { + print_pnr_sdc_constrain_pb_pin_interc_timing( + fp, time_unit, hierarchical, module_path, module_manager, + parent_module, &(des_pb_graph_node->output_pins[iport][ipin]), + physical_mode, constrain_zero_delay_paths); + } } + break; } - break; - } - case CIRCUIT_PB_PORT_CLOCK: { - /* Do NOT constrain clock here, it should be handled by Clock Tree Synthesis */ - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid pb port type!\n"); - exit(1); + case CIRCUIT_PB_PORT_CLOCK: { + /* Do NOT constrain clock here, it should be handled by Clock Tree + * Synthesis */ + break; + } + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid pb port type!\n"); + exit(1); } } /******************************************************************** * This function will generate a SDC file for each pb_type, - * constraining the pin-to-pin timing between + * constraining the pin-to-pin timing between * 1. input port of parent_pb_graph_node and input port of child_pb_graph_nodes - * 2. output port of parent_pb_graph_node and output port of child_pb_graph_nodes + * 2. output port of parent_pb_graph_node and output port of + *child_pb_graph_nodes * 3. output port of child_pb_graph_node and input port of child_pb_graph_nodes *******************************************************************/ -static -void print_pnr_sdc_constrain_pb_graph_node_timing(const PnrSdcOption& options, - const std::string& module_path, - const ModuleManager& module_manager, - t_pb_graph_node* parent_pb_graph_node, - t_mode* physical_mode) { +static void print_pnr_sdc_constrain_pb_graph_node_timing( + const PnrSdcOption& options, const std::string& module_path, + const ModuleManager& module_manager, t_pb_graph_node* parent_pb_graph_node, + t_mode* physical_mode) { std::string sdc_dir = options.sdc_dir(); float time_unit = options.time_unit(); bool hierarchical = options.hierarchical(); @@ -252,15 +256,17 @@ void print_pnr_sdc_constrain_pb_graph_node_timing(const PnrSdcOption& options, bool constrain_zero_delay_paths = options.constrain_zero_delay_paths(); /* Get the pb_type definition related to the node */ - t_pb_type* physical_pb_type = parent_pb_graph_node->pb_type; - std::string pb_module_name = generate_physical_block_module_name(physical_pb_type); + t_pb_type* physical_pb_type = parent_pb_graph_node->pb_type; + std::string pb_module_name = + generate_physical_block_module_name(physical_pb_type); /* Find the pb module in module manager */ ModuleId pb_module = module_manager.find_module(pb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); /* Create the file name for SDC */ - std::string sdc_fname(sdc_dir + pb_module_name + std::string(SDC_FILE_NAME_POSTFIX)); + std::string sdc_fname(sdc_dir + pb_module_name + + std::string(SDC_FILE_NAME_POSTFIX)); /* Create the file stream */ std::fstream fp; @@ -269,54 +275,51 @@ void print_pnr_sdc_constrain_pb_graph_node_timing(const PnrSdcOption& options, check_file_stream(sdc_fname.c_str(), fp); /* Generate the descriptions*/ - print_sdc_file_header(fp, - std::string("Timing constraints for Grid " + pb_module_name + " in PnR"), - include_time_stamp); + print_sdc_file_header( + fp, + std::string("Timing constraints for Grid " + pb_module_name + " in PnR"), + include_time_stamp); /* Print time unit for the SDC file */ print_sdc_timescale(fp, time_unit_to_string(time_unit)); /* We check output_pins of cur_pb_graph_node and its the input_edges - * Built the interconnections between outputs of cur_pb_graph_node and outputs of child_pb_graph_node - * child_pb_graph_node.output_pins -----------------> cur_pb_graph_node.outpins + * Built the interconnections between outputs of cur_pb_graph_node and outputs + * of child_pb_graph_node child_pb_graph_node.output_pins -----------------> + * cur_pb_graph_node.outpins * /|\ * | * input_pins, edges, output_pins - */ - print_pnr_sdc_constrain_pb_interc_timing(fp, - time_unit, - hierarchical, - module_path, - module_manager, pb_module, - parent_pb_graph_node, - CIRCUIT_PB_PORT_OUTPUT, - physical_mode, - constrain_zero_delay_paths); - + */ + print_pnr_sdc_constrain_pb_interc_timing( + fp, time_unit, hierarchical, module_path, module_manager, pb_module, + parent_pb_graph_node, CIRCUIT_PB_PORT_OUTPUT, physical_mode, + constrain_zero_delay_paths); + /* We check input_pins of child_pb_graph_node and its the input_edges - * Built the interconnections between inputs of cur_pb_graph_node and inputs of child_pb_graph_node - * cur_pb_graph_node.input_pins -----------------> child_pb_graph_node.input_pins + * Built the interconnections between inputs of cur_pb_graph_node and inputs + * of child_pb_graph_node cur_pb_graph_node.input_pins -----------------> + * child_pb_graph_node.input_pins * /|\ * | * input_pins, edges, output_pins - */ + */ for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) { - for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; ++jpb) { - t_pb_graph_node* child_pb_graph_node = &(parent_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]); + for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; + ++jpb) { + t_pb_graph_node* child_pb_graph_node = + &(parent_pb_graph_node + ->child_pb_graph_nodes[physical_mode->index][ipb][jpb]); /* For each child_pb_graph_node input pins*/ - print_pnr_sdc_constrain_pb_interc_timing(fp, - time_unit, - hierarchical, - module_path, - module_manager, pb_module, - child_pb_graph_node, - CIRCUIT_PB_PORT_INPUT, - physical_mode, - constrain_zero_delay_paths); - /* Do NOT constrain clock here, it should be handled by Clock Tree Synthesis */ + print_pnr_sdc_constrain_pb_interc_timing( + fp, time_unit, hierarchical, module_path, module_manager, pb_module, + child_pb_graph_node, CIRCUIT_PB_PORT_INPUT, physical_mode, + constrain_zero_delay_paths); + /* Do NOT constrain clock here, it should be handled by Clock Tree + * Synthesis */ } } - + /* Close file handler */ fp.close(); } @@ -329,15 +332,13 @@ void print_pnr_sdc_constrain_pb_graph_node_timing(const PnrSdcOption& options, * This is designed for LUT, adder or other hard IPs * When PnR the modules, we want to minimize the interconnect delay *******************************************************************/ -static -void print_pnr_sdc_constrain_primitive_pb_graph_node(const PnrSdcOption& options, - const std::string& module_path, - const ModuleManager& module_manager, - t_pb_graph_node* primitive_pb_graph_node) { +static void print_pnr_sdc_constrain_primitive_pb_graph_node( + const PnrSdcOption& options, const std::string& module_path, + const ModuleManager& module_manager, + t_pb_graph_node* primitive_pb_graph_node) { /* Validate pb_graph node */ if (nullptr == primitive_pb_graph_node) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid primitive_pb_graph_node.\n"); + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid primitive_pb_graph_node.\n"); exit(1); } @@ -352,15 +353,19 @@ void print_pnr_sdc_constrain_primitive_pb_graph_node(const PnrSdcOption& options t_pb_type* primitive_pb_type = primitive_pb_graph_node->pb_type; if (LUT_CLASS == primitive_pb_type->class_type) { VTR_ASSERT(VPR_PB_TYPE_LUT_MODE < primitive_pb_type->num_modes); - VTR_ASSERT(1 == primitive_pb_type->modes[VPR_PB_TYPE_LUT_MODE].num_pb_type_children); - primitive_pb_type = &(primitive_pb_type->modes[VPR_PB_TYPE_LUT_MODE].pb_type_children[0]); - logical_primitive_pb_graph_node = primitive_pb_graph_node->child_pb_graph_nodes[VPR_PB_TYPE_LUT_MODE][0]; + VTR_ASSERT( + 1 == primitive_pb_type->modes[VPR_PB_TYPE_LUT_MODE].num_pb_type_children); + primitive_pb_type = + &(primitive_pb_type->modes[VPR_PB_TYPE_LUT_MODE].pb_type_children[0]); + logical_primitive_pb_graph_node = + primitive_pb_graph_node->child_pb_graph_nodes[VPR_PB_TYPE_LUT_MODE][0]; VTR_ASSERT(nullptr != logical_primitive_pb_graph_node); } else if (MEMORY_CLASS == primitive_pb_type->class_type) { VTR_ASSERT(1 == primitive_pb_type->num_modes); VTR_ASSERT(1 == primitive_pb_type->modes[0].num_pb_type_children); primitive_pb_type = &(primitive_pb_type->modes[0].pb_type_children[0]); - logical_primitive_pb_graph_node = primitive_pb_graph_node->child_pb_graph_nodes[0][0]; + logical_primitive_pb_graph_node = + primitive_pb_graph_node->child_pb_graph_nodes[0][0]; } VTR_ASSERT(nullptr != primitive_pb_type); VTR_ASSERT(nullptr != logical_primitive_pb_graph_node); @@ -368,18 +373,20 @@ void print_pnr_sdc_constrain_primitive_pb_graph_node(const PnrSdcOption& options /* We can directly return if there is no timing annotation defined */ if (0 == primitive_pb_type->num_annotations) { return; - } + } /* Get the pb_type definition related to the node */ - t_pb_type* physical_pb_type = primitive_pb_graph_node->pb_type; - std::string pb_module_name = generate_physical_block_module_name(physical_pb_type); + t_pb_type* physical_pb_type = primitive_pb_graph_node->pb_type; + std::string pb_module_name = + generate_physical_block_module_name(physical_pb_type); /* Find the pb module in module manager */ ModuleId pb_module = module_manager.find_module(pb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); /* Create the file name for SDC */ - std::string sdc_fname(options.sdc_dir() + pb_module_name + std::string(SDC_FILE_NAME_POSTFIX)); + std::string sdc_fname(options.sdc_dir() + pb_module_name + + std::string(SDC_FILE_NAME_POSTFIX)); /* Create the file stream */ std::fstream fp; @@ -388,72 +395,78 @@ void print_pnr_sdc_constrain_primitive_pb_graph_node(const PnrSdcOption& options check_file_stream(sdc_fname.c_str(), fp); /* Generate the descriptions*/ - print_sdc_file_header(fp, - std::string("Timing constraints for Grid " + pb_module_name + " in PnR"), - options.time_stamp()); + print_sdc_file_header( + fp, + std::string("Timing constraints for Grid " + pb_module_name + " in PnR"), + options.time_stamp()); /* Print time unit for the SDC file */ print_sdc_timescale(fp, time_unit_to_string(options.time_unit())); - /* We traverse the pb_graph pins where we can find pin-to-pin timing annotation - * We walk through input pins here, build timing constraints by pair each input to output - * Because VPR keeps all the timing values in pin_timing data structure instead of pb_graph_pin edges - * Clock pins are not walked through because they will be handled by clock tree synthesis + /* We traverse the pb_graph pins where we can find pin-to-pin timing + * annotation We walk through input pins here, build timing constraints by + * pair each input to output Because VPR keeps all the timing values in + * pin_timing data structure instead of pb_graph_pin edges Clock pins are not + * walked through because they will be handled by clock tree synthesis */ - for (int iport = 0; iport < logical_primitive_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < logical_primitive_pb_graph_node->num_input_pins[iport]; ++ipin) { - t_pb_graph_pin* src_pin = &(logical_primitive_pb_graph_node->input_pins[iport][ipin]); + for (int iport = 0; iport < logical_primitive_pb_graph_node->num_input_ports; + ++iport) { + for (int ipin = 0; + ipin < logical_primitive_pb_graph_node->num_input_pins[iport]; + ++ipin) { + t_pb_graph_pin* src_pin = + &(logical_primitive_pb_graph_node->input_pins[iport][ipin]); - /* Port must exist in the module graph */ - ModulePortId src_module_port_id = module_manager.find_module_port(pb_module, generate_pb_type_port_name(physical_pb_type, src_pin->port)); - VTR_ASSERT(true == module_manager.valid_module_port_id(pb_module, src_module_port_id)); - BasicPort src_port = module_manager.module_port(pb_module, src_module_port_id); - /* Set the correct pin number of the port */ - src_port.set_width(src_pin->pin_number, src_pin->pin_number); + /* Port must exist in the module graph */ + ModulePortId src_module_port_id = module_manager.find_module_port( + pb_module, generate_pb_type_port_name(physical_pb_type, src_pin->port)); + VTR_ASSERT(true == module_manager.valid_module_port_id( + pb_module, src_module_port_id)); + BasicPort src_port = + module_manager.module_port(pb_module, src_module_port_id); + /* Set the correct pin number of the port */ + src_port.set_width(src_pin->pin_number, src_pin->pin_number); - /* Find all the sink pin from this source pb_graph_pin */ - for (int itiming = 0; itiming < src_pin->num_pin_timing; ++itiming) { - t_pb_graph_pin* sink_pin = src_pin->pin_timing[itiming]; + /* Find all the sink pin from this source pb_graph_pin */ + for (int itiming = 0; itiming < src_pin->num_pin_timing; ++itiming) { + t_pb_graph_pin* sink_pin = src_pin->pin_timing[itiming]; - /* Port must exist in the module graph */ - ModulePortId sink_module_port_id = module_manager.find_module_port(pb_module, generate_pb_type_port_name(physical_pb_type, sink_pin->port)); - VTR_ASSERT(true == module_manager.valid_module_port_id(pb_module, sink_module_port_id)); - BasicPort sink_port = module_manager.module_port(pb_module, sink_module_port_id); - /* Set the correct pin number of the port */ - sink_port.set_width(sink_pin->pin_number, sink_pin->pin_number); + /* Port must exist in the module graph */ + ModulePortId sink_module_port_id = module_manager.find_module_port( + pb_module, + generate_pb_type_port_name(physical_pb_type, sink_pin->port)); + VTR_ASSERT(true == module_manager.valid_module_port_id( + pb_module, sink_module_port_id)); + BasicPort sink_port = + module_manager.module_port(pb_module, sink_module_port_id); + /* Set the correct pin number of the port */ + sink_port.set_width(sink_pin->pin_number, sink_pin->pin_number); - /* Find max delay between src and sink pin */ - float tmax = src_pin->pin_timing_del_max[itiming]; + /* Find max delay between src and sink pin */ + float tmax = src_pin->pin_timing_del_max[itiming]; - /* Generate module path in hierarchy depending if the hierarchical is enabled */ - std::string module_hie_path = pb_module_name; - if (false == options.hierarchical()) { - module_hie_path = module_path + pb_module_name; - } + /* Generate module path in hierarchy depending if the hierarchical is + * enabled */ + std::string module_hie_path = pb_module_name; + if (false == options.hierarchical()) { + module_hie_path = module_path + pb_module_name; + } - /* If the delay is zero, constrain only when user wants it */ - if ( (true == options.constrain_zero_delay_paths()) - || (0. != tmax) ) { - print_pnr_sdc_constrain_max_delay(fp, - module_hie_path, - generate_sdc_port(src_port), - module_hie_path, - generate_sdc_port(sink_port), - tmax / options.time_unit()); - } + /* If the delay is zero, constrain only when user wants it */ + if ((true == options.constrain_zero_delay_paths()) || (0. != tmax)) { + print_pnr_sdc_constrain_max_delay( + fp, module_hie_path, generate_sdc_port(src_port), module_hie_path, + generate_sdc_port(sink_port), tmax / options.time_unit()); + } - /* Find min delay between src and sink pin */ - float tmin = src_pin->pin_timing_del_min[itiming]; - /* If the delay is zero, constrain only when user wants it */ - if ( (true == options.constrain_zero_delay_paths()) - || (0. != tmin) ) { - print_pnr_sdc_constrain_min_delay(fp, - module_hie_path, - generate_sdc_port(src_port), - module_hie_path, - generate_sdc_port(sink_port), - tmin / options.time_unit()); - } + /* Find min delay between src and sink pin */ + float tmin = src_pin->pin_timing_del_min[itiming]; + /* If the delay is zero, constrain only when user wants it */ + if ((true == options.constrain_zero_delay_paths()) || (0. != tmin)) { + print_pnr_sdc_constrain_min_delay( + fp, module_hie_path, generate_sdc_port(src_port), module_hie_path, + generate_sdc_port(sink_port), tmin / options.time_unit()); + } } } } @@ -467,16 +480,14 @@ void print_pnr_sdc_constrain_primitive_pb_graph_node(const PnrSdcOption& options * This function will generate a SDC file for each pb_type, * constraining the pin-to-pin timing *******************************************************************/ -static -void rec_print_pnr_sdc_constrain_pb_graph_timing(const PnrSdcOption& options, - const std::string& module_path, - const ModuleManager& module_manager, - const VprDeviceAnnotation& device_annotation, - t_pb_graph_node* parent_pb_graph_node) { +static void rec_print_pnr_sdc_constrain_pb_graph_timing( + const PnrSdcOption& options, const std::string& module_path, + const ModuleManager& module_manager, + const VprDeviceAnnotation& device_annotation, + t_pb_graph_node* parent_pb_graph_node) { /* Validate pb_graph node */ if (nullptr == parent_pb_graph_node) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid parent_pb_graph_node.\n"); + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid parent_pb_graph_node.\n"); exit(1); } @@ -485,52 +496,52 @@ void rec_print_pnr_sdc_constrain_pb_graph_timing(const PnrSdcOption& options, /* Constrain the primitive node if a timing matrix is defined */ if (true == is_primitive_pb_type(parent_pb_type)) { - print_pnr_sdc_constrain_primitive_pb_graph_node(options, - module_path, - module_manager, - parent_pb_graph_node); + print_pnr_sdc_constrain_primitive_pb_graph_node( + options, module_path, module_manager, parent_pb_graph_node); return; } - /* Note we only go through the graph through the physical modes. - * which we build the modules + /* Note we only go through the graph through the physical modes. + * which we build the modules */ - t_mode* physical_mode = device_annotation.physical_mode(parent_pb_type); + t_mode* physical_mode = device_annotation.physical_mode(parent_pb_type); /* Write a SDC file for this pb_type */ - print_pnr_sdc_constrain_pb_graph_node_timing(options, - module_path, - module_manager, - parent_pb_graph_node, - physical_mode); + print_pnr_sdc_constrain_pb_graph_node_timing( + options, module_path, module_manager, parent_pb_graph_node, physical_mode); /* Go recursively to the lower level in the pb_graph - * Note that we assume a full hierarchical P&R, we will only visit pb_graph_node of unique pb_type + * Note that we assume a full hierarchical P&R, we will only visit + * pb_graph_node of unique pb_type */ for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) { - rec_print_pnr_sdc_constrain_pb_graph_timing(options, - format_dir_path(module_path + generate_physical_block_instance_name(&(physical_mode->pb_type_children[ipb]), ipb)), - module_manager, - device_annotation, - &(parent_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][0])); + rec_print_pnr_sdc_constrain_pb_graph_timing( + options, + format_dir_path(module_path + + generate_physical_block_instance_name( + &(physical_mode->pb_type_children[ipb]), ipb)), + module_manager, device_annotation, + &(parent_pb_graph_node + ->child_pb_graph_nodes[physical_mode->index][ipb][0])); } } /******************************************************************** * Top-level function to print timing constraints for pb_types *******************************************************************/ -void print_pnr_sdc_constrain_grid_timing(const PnrSdcOption& options, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const ModuleManager& module_manager, - const ModuleId& top_module) { - +void print_pnr_sdc_constrain_grid_timing( + const PnrSdcOption& options, const DeviceContext& device_ctx, + const VprDeviceAnnotation& device_annotation, + const ModuleManager& module_manager, const ModuleId& top_module) { /* Start time count */ - vtr::ScopedStartFinishTimer timer("Write SDC for constraining grid timing for P&R flow"); + vtr::ScopedStartFinishTimer timer( + "Write SDC for constraining grid timing for P&R flow"); - std::string root_path = format_dir_path(module_manager.module_name(top_module)); + std::string root_path = + format_dir_path(module_manager.module_name(top_module)); - for (const t_physical_tile_type& physical_tile : device_ctx.physical_tile_types) { + for (const t_physical_tile_type& physical_tile : + device_ctx.physical_tile_types) { /* Bypass empty type or nullptr */ if (true == is_empty_type(&physical_tile)) { continue; @@ -538,7 +549,8 @@ void print_pnr_sdc_constrain_grid_timing(const PnrSdcOption& options, for (const t_sub_tile& sub_tile : physical_tile.sub_tiles) { VTR_ASSERT(1 == sub_tile.equivalent_sites.size()); - t_pb_graph_node* pb_graph_head = sub_tile.equivalent_sites[0]->pb_graph_head; + t_pb_graph_node* pb_graph_head = + sub_tile.equivalent_sites[0]->pb_graph_head; if (nullptr == pb_graph_head) { continue; } @@ -548,51 +560,53 @@ void print_pnr_sdc_constrain_grid_timing(const PnrSdcOption& options, * We will search the grids and see where the I/O blocks are located: * - If a I/O block locates on border sides of FPGA fabric: * i.e., one or more from {TOP, RIGHT, BOTTOM, LEFT}, - * we will generate one module for each border side + * we will generate one module for each border side * - If a I/O block locates in the center of FPGA fabric: - * we will generate one module with NUM_SIDES (same treatment as regular grids) + * we will generate one module with NUM_SIDES (same treatment as + * regular grids) */ - std::set io_type_sides = find_physical_io_tile_located_sides(device_ctx.grid, - &physical_tile); - + std::set io_type_sides = + find_physical_io_tile_located_sides(device_ctx.grid, &physical_tile); /* Generate the grid module name */ for (const e_side& io_type_side : io_type_sides) { - std::string grid_module_name = generate_grid_block_module_name(std::string(GRID_MODULE_NAME_PREFIX), - std::string(physical_tile.name), - is_io_type(&physical_tile), - io_type_side); + std::string grid_module_name = generate_grid_block_module_name( + std::string(GRID_MODULE_NAME_PREFIX), + std::string(physical_tile.name), is_io_type(&physical_tile), + io_type_side); /* Find the module Id */ ModuleId grid_module = module_manager.find_module(grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); - std::string module_path = format_dir_path(root_path + grid_module_name); - module_path = format_dir_path(module_path + generate_physical_block_instance_name(pb_graph_head->pb_type, pb_graph_head->placement_index)); + std::string module_path = + format_dir_path(root_path + grid_module_name); + module_path = + format_dir_path(module_path + generate_physical_block_instance_name( + pb_graph_head->pb_type, + pb_graph_head->placement_index)); - rec_print_pnr_sdc_constrain_pb_graph_timing(options, - module_path, - module_manager, - device_annotation, - pb_graph_head); + rec_print_pnr_sdc_constrain_pb_graph_timing( + options, module_path, module_manager, device_annotation, + pb_graph_head); } } else { /* For CLB and heterogenenous blocks */ - std::string grid_module_name = generate_grid_block_module_name(std::string(GRID_MODULE_NAME_PREFIX), - std::string(physical_tile.name), - is_io_type(&physical_tile), - NUM_SIDES); + std::string grid_module_name = generate_grid_block_module_name( + std::string(GRID_MODULE_NAME_PREFIX), std::string(physical_tile.name), + is_io_type(&physical_tile), NUM_SIDES); /* Find the module Id */ ModuleId grid_module = module_manager.find_module(grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); std::string module_path = format_dir_path(root_path + grid_module_name); - module_path = format_dir_path(module_path + generate_physical_block_instance_name(pb_graph_head->pb_type, pb_graph_head->placement_index)); + module_path = + format_dir_path(module_path + generate_physical_block_instance_name( + pb_graph_head->pb_type, + pb_graph_head->placement_index)); - rec_print_pnr_sdc_constrain_pb_graph_timing(options, - module_path, - module_manager, - device_annotation, - pb_graph_head); + rec_print_pnr_sdc_constrain_pb_graph_timing( + options, module_path, module_manager, device_annotation, + pb_graph_head); } } } diff --git a/openfpga/src/fpga_sdc/pnr_sdc_grid_writer.h b/openfpga/src/fpga_sdc/pnr_sdc_grid_writer.h index 1ba2c70d5..d056340eb 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_grid_writer.h +++ b/openfpga/src/fpga_sdc/pnr_sdc_grid_writer.h @@ -6,10 +6,11 @@ *******************************************************************/ #include #include -#include "vpr_context.h" -#include "vpr_device_annotation.h" + #include "module_manager.h" #include "pnr_sdc_option.h" +#include "vpr_context.h" +#include "vpr_device_annotation.h" /******************************************************************** * Function declaration @@ -18,11 +19,10 @@ /* begin namespace openfpga */ namespace openfpga { -void print_pnr_sdc_constrain_grid_timing(const PnrSdcOption& options, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const ModuleManager& module_manager, - const ModuleId& top_module); +void print_pnr_sdc_constrain_grid_timing( + const PnrSdcOption& options, const DeviceContext& device_ctx, + const VprDeviceAnnotation& device_annotation, + const ModuleManager& module_manager, const ModuleId& top_module); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/pnr_sdc_option.cpp b/openfpga/src/fpga_sdc/pnr_sdc_option.cpp index 57e3b5f92..7d6882f5e 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_option.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_option.cpp @@ -1,5 +1,6 @@ /******************************************************************** - * Member functions for a data structure which includes all the options for the SDC generator + * Member functions for a data structure which includes all the options for the + *SDC generator ********************************************************************/ #include "pnr_sdc_option.h" @@ -29,34 +30,21 @@ PnrSdcOption::PnrSdcOption(const std::string& sdc_dir) { /******************************************************************** * Public accessors ********************************************************************/ -std::string PnrSdcOption::sdc_dir() const { - return sdc_dir_; -} +std::string PnrSdcOption::sdc_dir() const { return sdc_dir_; } -bool PnrSdcOption::flatten_names() const { - return flatten_names_; -} +bool PnrSdcOption::flatten_names() const { return flatten_names_; } -bool PnrSdcOption::hierarchical() const { - return hierarchical_; -} +bool PnrSdcOption::hierarchical() const { return hierarchical_; } -float PnrSdcOption::time_unit() const { - return time_unit_; -} +float PnrSdcOption::time_unit() const { return time_unit_; } -bool PnrSdcOption::output_hierarchy() const { - return output_hierarchy_; -} +bool PnrSdcOption::output_hierarchy() const { return output_hierarchy_; } bool PnrSdcOption::generate_sdc_pnr() const { - return constrain_global_port_ - || constrain_grid_ - || constrain_sb_ - || constrain_cb_ - || constrain_configurable_memory_outputs_ - || constrain_routing_multiplexer_outputs_ - || constrain_switch_block_outputs_; + return constrain_global_port_ || constrain_grid_ || constrain_sb_ || + constrain_cb_ || constrain_configurable_memory_outputs_ || + constrain_routing_multiplexer_outputs_ || + constrain_switch_block_outputs_; } bool PnrSdcOption::constrain_global_port() const { @@ -67,17 +55,11 @@ bool PnrSdcOption::constrain_non_clock_global_port() const { return constrain_non_clock_global_port_; } -bool PnrSdcOption::constrain_grid() const { - return constrain_grid_; -} +bool PnrSdcOption::constrain_grid() const { return constrain_grid_; } -bool PnrSdcOption::constrain_sb() const { - return constrain_sb_; -} +bool PnrSdcOption::constrain_sb() const { return constrain_sb_; } -bool PnrSdcOption::constrain_cb() const { - return constrain_cb_; -} +bool PnrSdcOption::constrain_cb() const { return constrain_cb_; } bool PnrSdcOption::constrain_configurable_memory_outputs() const { return constrain_configurable_memory_outputs_; @@ -95,9 +77,7 @@ bool PnrSdcOption::constrain_zero_delay_paths() const { return constrain_zero_delay_paths_; } -bool PnrSdcOption::time_stamp() const { - return time_stamp_; -} +bool PnrSdcOption::time_stamp() const { return time_stamp_; } /******************************************************************** * Public mutators @@ -132,11 +112,13 @@ void PnrSdcOption::set_generate_sdc_pnr(const bool& generate_sdc_pnr) { constrain_switch_block_outputs_ = generate_sdc_pnr; } -void PnrSdcOption::set_constrain_global_port(const bool& constrain_global_port) { +void PnrSdcOption::set_constrain_global_port( + const bool& constrain_global_port) { constrain_global_port_ = constrain_global_port; } -void PnrSdcOption::set_constrain_non_clock_global_port(const bool& constrain_non_clock_global_port) { +void PnrSdcOption::set_constrain_non_clock_global_port( + const bool& constrain_non_clock_global_port) { constrain_non_clock_global_port_ = constrain_non_clock_global_port; } @@ -152,24 +134,26 @@ void PnrSdcOption::set_constrain_cb(const bool& constrain_cb) { constrain_cb_ = constrain_cb; } -void PnrSdcOption::set_constrain_configurable_memory_outputs(const bool& constrain_config_mem_outputs) { +void PnrSdcOption::set_constrain_configurable_memory_outputs( + const bool& constrain_config_mem_outputs) { constrain_configurable_memory_outputs_ = constrain_config_mem_outputs; } -void PnrSdcOption::set_constrain_routing_multiplexer_outputs(const bool& constrain_routing_mux_outputs) { +void PnrSdcOption::set_constrain_routing_multiplexer_outputs( + const bool& constrain_routing_mux_outputs) { constrain_routing_multiplexer_outputs_ = constrain_routing_mux_outputs; } -void PnrSdcOption::set_constrain_switch_block_outputs(const bool& constrain_sb_outputs) { +void PnrSdcOption::set_constrain_switch_block_outputs( + const bool& constrain_sb_outputs) { constrain_switch_block_outputs_ = constrain_sb_outputs; } -void PnrSdcOption::set_constrain_zero_delay_paths(const bool& constrain_zero_delay_paths) { +void PnrSdcOption::set_constrain_zero_delay_paths( + const bool& constrain_zero_delay_paths) { constrain_zero_delay_paths_ = constrain_zero_delay_paths; } -void PnrSdcOption::set_time_stamp(const bool& enable) { - time_stamp_ = enable; -} +void PnrSdcOption::set_time_stamp(const bool& enable) { time_stamp_ = enable; } } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/pnr_sdc_option.h b/openfpga/src/fpga_sdc/pnr_sdc_option.h index 0065acf56..6096964c6 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_option.h +++ b/openfpga/src/fpga_sdc/pnr_sdc_option.h @@ -12,58 +12,64 @@ namespace openfpga { class PnrSdcOption { - public: /* Public Constructors */ - PnrSdcOption(const std::string& sdc_dir); - public: /* Public accessors */ - std::string sdc_dir() const; - bool flatten_names() const; - bool hierarchical() const; - float time_unit() const; - bool output_hierarchy() const; - bool generate_sdc_pnr() const; - bool constrain_global_port() const; - bool constrain_non_clock_global_port() const; - bool constrain_grid() const; - bool constrain_sb() const; - bool constrain_cb() const; - bool constrain_configurable_memory_outputs() const; - bool constrain_routing_multiplexer_outputs() const; - bool constrain_switch_block_outputs() const; - bool constrain_zero_delay_paths() const; - bool time_stamp() const; - public: /* Public mutators */ - void set_sdc_dir(const std::string& sdc_dir); - void set_flatten_names(const bool& flatten_names); - void set_hierarchical(const bool& hierarchical); - void set_time_unit(const float& time_unit); - void set_output_hierarchy(const bool& output_hierarchy); - void set_generate_sdc_pnr(const bool& generate_sdc_pnr); - void set_constrain_global_port(const bool& constrain_global_port); - void set_constrain_non_clock_global_port(const bool& constrain_non_clock_global_port); - void set_constrain_grid(const bool& constrain_grid); - void set_constrain_sb(const bool& constrain_sb); - void set_constrain_cb(const bool& constrain_cb); - void set_constrain_configurable_memory_outputs(const bool& constrain_config_mem_outputs); - void set_constrain_routing_multiplexer_outputs(const bool& constrain_routing_mux_outputs); - void set_constrain_switch_block_outputs(const bool& constrain_sb_outputs); - void set_constrain_zero_delay_paths(const bool& constrain_zero_delay_paths); - void set_time_stamp(const bool& enable); - private: /* Internal data */ - std::string sdc_dir_; - bool flatten_names_; - bool hierarchical_; - float time_unit_; - bool output_hierarchy_; - bool constrain_global_port_; - bool constrain_non_clock_global_port_; - bool constrain_grid_; - bool constrain_sb_; - bool constrain_cb_; - bool constrain_configurable_memory_outputs_; - bool constrain_routing_multiplexer_outputs_; - bool constrain_switch_block_outputs_; - bool constrain_zero_delay_paths_; - bool time_stamp_; + public: /* Public Constructors */ + PnrSdcOption(const std::string& sdc_dir); + + public: /* Public accessors */ + std::string sdc_dir() const; + bool flatten_names() const; + bool hierarchical() const; + float time_unit() const; + bool output_hierarchy() const; + bool generate_sdc_pnr() const; + bool constrain_global_port() const; + bool constrain_non_clock_global_port() const; + bool constrain_grid() const; + bool constrain_sb() const; + bool constrain_cb() const; + bool constrain_configurable_memory_outputs() const; + bool constrain_routing_multiplexer_outputs() const; + bool constrain_switch_block_outputs() const; + bool constrain_zero_delay_paths() const; + bool time_stamp() const; + + public: /* Public mutators */ + void set_sdc_dir(const std::string& sdc_dir); + void set_flatten_names(const bool& flatten_names); + void set_hierarchical(const bool& hierarchical); + void set_time_unit(const float& time_unit); + void set_output_hierarchy(const bool& output_hierarchy); + void set_generate_sdc_pnr(const bool& generate_sdc_pnr); + void set_constrain_global_port(const bool& constrain_global_port); + void set_constrain_non_clock_global_port( + const bool& constrain_non_clock_global_port); + void set_constrain_grid(const bool& constrain_grid); + void set_constrain_sb(const bool& constrain_sb); + void set_constrain_cb(const bool& constrain_cb); + void set_constrain_configurable_memory_outputs( + const bool& constrain_config_mem_outputs); + void set_constrain_routing_multiplexer_outputs( + const bool& constrain_routing_mux_outputs); + void set_constrain_switch_block_outputs(const bool& constrain_sb_outputs); + void set_constrain_zero_delay_paths(const bool& constrain_zero_delay_paths); + void set_time_stamp(const bool& enable); + + private: /* Internal data */ + std::string sdc_dir_; + bool flatten_names_; + bool hierarchical_; + float time_unit_; + bool output_hierarchy_; + bool constrain_global_port_; + bool constrain_non_clock_global_port_; + bool constrain_grid_; + bool constrain_sb_; + bool constrain_cb_; + bool constrain_configurable_memory_outputs_; + bool constrain_routing_multiplexer_outputs_; + bool constrain_switch_block_outputs_; + bool constrain_zero_delay_paths_; + bool time_stamp_; }; } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp index fd03159e4..3732815f7 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp @@ -1,8 +1,9 @@ /******************************************************************** - * This file includes functions that print SDC (Synopsys Design Constraint) + * This file includes functions that print SDC (Synopsys Design Constraint) * files in physical design tools, i.e., Place & Route (PnR) tools - * The SDC files are used to constrain the physical design for each routing modules - * in FPGA fabric, such as Switch Blocks (SBs) and Connection Blocks (CBs) + * The SDC files are used to constrain the physical design for each routing + *modules in FPGA fabric, such as Switch Blocks (SBs) and Connection Blocks + *(CBs) * * Note that this is different from the SDC to constrain VPR Place&Route * engine! These SDCs are designed for PnR to generate FPGA layouts!!! @@ -11,26 +12,22 @@ #include /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_scale.h" -#include "openfpga_port.h" -#include "openfpga_side_manager.h" -#include "openfpga_digest.h" - -#include "mux_utils.h" - -#include "openfpga_naming.h" - -#include "openfpga_rr_graph_utils.h" #include "build_routing_module_utils.h" - +#include "mux_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" +#include "openfpga_rr_graph_utils.h" +#include "openfpga_scale.h" +#include "openfpga_side_manager.h" +#include "pnr_sdc_routing_writer.h" #include "sdc_writer_naming.h" #include "sdc_writer_utils.h" -#include "pnr_sdc_routing_writer.h" /* begin namespace openfpga */ namespace openfpga { @@ -39,8 +36,7 @@ namespace openfpga { * Find the timing constraints between the inputs and outputs of a routing * multiplexer in a Switch Block *******************************************************************/ -static -float find_pnr_sdc_switch_tmax(const t_rr_switch_inf& switch_inf) { +static float find_pnr_sdc_switch_tmax(const t_rr_switch_inf& switch_inf) { return switch_inf.R * switch_inf.Cout + switch_inf.Tdel; } @@ -48,107 +44,91 @@ float find_pnr_sdc_switch_tmax(const t_rr_switch_inf& switch_inf) { * Set timing constraints between the inputs and outputs of a routing * multiplexer in a Switch Block *******************************************************************/ -static -void print_pnr_sdc_constrain_sb_mux_timing(std::fstream& fp, - const float& time_unit, - const bool& hierarchical, - const std::string& module_path, - const ModuleManager& module_manager, - const ModuleId& sb_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const e_side& output_node_side, - const RRNodeId& output_rr_node, - const bool& constrain_zero_delay_paths) { +static void print_pnr_sdc_constrain_sb_mux_timing( + std::fstream& fp, const float& time_unit, const bool& hierarchical, + const std::string& module_path, const ModuleManager& module_manager, + const ModuleId& sb_module, const VprDeviceAnnotation& device_annotation, + const DeviceGrid& grids, const RRGraphView& rr_graph, const RRGSB& rr_gsb, + const e_side& output_node_side, const RRNodeId& output_rr_node, + const bool& constrain_zero_delay_paths) { /* Validate file stream */ valid_file_stream(fp); - VTR_ASSERT( ( CHANX == rr_graph.node_type(output_rr_node) ) - || ( CHANY == rr_graph.node_type(output_rr_node) )); + VTR_ASSERT((CHANX == rr_graph.node_type(output_rr_node)) || + (CHANY == rr_graph.node_type(output_rr_node))); /* Find the module port corresponding to the output rr_node */ - ModulePinInfo module_output_port = find_switch_block_module_chan_port(module_manager, - sb_module, - rr_graph, - rr_gsb, - output_node_side, - output_rr_node, - OUT_PORT); + ModulePinInfo module_output_port = find_switch_block_module_chan_port( + module_manager, sb_module, rr_graph, rr_gsb, output_node_side, + output_rr_node, OUT_PORT); - /* Find the module port corresponding to the fan-in rr_nodes of the output rr_node */ - std::vector module_input_ports = find_switch_block_module_input_ports(module_manager, - sb_module, - grids, - device_annotation, - rr_graph, - rr_gsb, - get_rr_graph_configurable_driver_nodes(rr_graph, output_rr_node)); + /* Find the module port corresponding to the fan-in rr_nodes of the output + * rr_node */ + std::vector module_input_ports = + find_switch_block_module_input_ports( + module_manager, sb_module, grids, device_annotation, rr_graph, rr_gsb, + get_rr_graph_configurable_driver_nodes(rr_graph, output_rr_node)); /* Find timing constraints for each path (edge) */ std::map switch_delays; size_t edge_counter = 0; - for (const RREdgeId& edge : rr_graph.node_configurable_in_edges(output_rr_node)) { + for (const RREdgeId& edge : + rr_graph.node_configurable_in_edges(output_rr_node)) { /* Get the switch delay */ const RRSwitchId& driver_switch = rr_graph.edge_switch(edge); - switch_delays[module_input_ports[edge_counter]] = find_pnr_sdc_switch_tmax(rr_graph.rr_switch_inf(driver_switch)); + switch_delays[module_input_ports[edge_counter]] = + find_pnr_sdc_switch_tmax(rr_graph.rr_switch_inf(driver_switch)); edge_counter++; } /* Find the starting points */ for (const ModulePinInfo& module_input_port : module_input_ports) { - /* If we have a zero-delay path to contrain, we will skip unless users want so */ - if ( (false == constrain_zero_delay_paths) - && (0. == switch_delays[module_input_port]) ) { + /* If we have a zero-delay path to contrain, we will skip unless users want + * so */ + if ((false == constrain_zero_delay_paths) && + (0. == switch_delays[module_input_port])) { continue; } - BasicPort src_port(module_manager.module_port(sb_module, module_input_port.first).get_name(), - module_input_port.second, - module_input_port.second); + BasicPort src_port( + module_manager.module_port(sb_module, module_input_port.first).get_name(), + module_input_port.second, module_input_port.second); - BasicPort sink_port(module_manager.module_port(sb_module, module_output_port.first).get_name(), - module_output_port.second, - module_output_port.second); + BasicPort sink_port( + module_manager.module_port(sb_module, module_output_port.first) + .get_name(), + module_output_port.second, module_output_port.second); /* Constrain a path */ if (false == hierarchical) { - print_pnr_sdc_constrain_max_delay(fp, - module_path, - generate_sdc_port(src_port), - module_path, - generate_sdc_port(sink_port), - switch_delays[module_input_port] / time_unit); + print_pnr_sdc_constrain_max_delay( + fp, module_path, generate_sdc_port(src_port), module_path, + generate_sdc_port(sink_port), + switch_delays[module_input_port] / time_unit); } else { VTR_ASSERT_SAFE(true == hierarchical); - print_pnr_sdc_constrain_max_delay(fp, - std::string(), - generate_sdc_port(src_port), - std::string(), - generate_sdc_port(sink_port), - switch_delays[module_input_port] / time_unit); + print_pnr_sdc_constrain_max_delay( + fp, std::string(), generate_sdc_port(src_port), std::string(), + generate_sdc_port(sink_port), + switch_delays[module_input_port] / time_unit); } } } /******************************************************************** - * Set timing constraints between the inputs and outputs of SBs, + * Set timing constraints between the inputs and outputs of SBs, * which are connected by routing multiplexers with the given delays * specified in architectural XML file * * To enable block by block timing constraining, we generate the SDC * file for each unique SB module *******************************************************************/ -static -void print_pnr_sdc_constrain_sb_timing(const PnrSdcOption& options, - const std::string& module_path, - const ModuleManager& module_manager, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb) { +static void print_pnr_sdc_constrain_sb_timing( + const PnrSdcOption& options, const std::string& module_path, + const ModuleManager& module_manager, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const RRGSB& rr_gsb) { std::string sdc_dir = options.sdc_dir(); float time_unit = options.time_unit(); bool hierarchical = options.hierarchical(); @@ -157,7 +137,9 @@ void print_pnr_sdc_constrain_sb_timing(const PnrSdcOption& options, /* Create the file name for Verilog netlist */ vtr::Point gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); - std::string sdc_fname(sdc_dir + generate_switch_block_module_name(gsb_coordinate) + std::string(SDC_FILE_NAME_POSTFIX)); + std::string sdc_fname(sdc_dir + + generate_switch_block_module_name(gsb_coordinate) + + std::string(SDC_FILE_NAME_POSTFIX)); /* Create the file stream */ std::fstream fp; @@ -166,13 +148,15 @@ void print_pnr_sdc_constrain_sb_timing(const PnrSdcOption& options, /* Validate file stream */ check_file_stream(sdc_fname.c_str(), fp); - std::string sb_module_name = generate_switch_block_module_name(gsb_coordinate); + std::string sb_module_name = + generate_switch_block_module_name(gsb_coordinate); ModuleId sb_module = module_manager.find_module(sb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); /* Generate the descriptions*/ print_sdc_file_header(fp, - std::string("Constrain timing of Switch Block " + sb_module_name + " for PnR"), + std::string("Constrain timing of Switch Block " + + sb_module_name + " for PnR"), include_time_stamp); /* Print time unit for the SDC file */ @@ -180,29 +164,25 @@ void print_pnr_sdc_constrain_sb_timing(const PnrSdcOption& options, for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); - for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) { - const RRNodeId& chan_rr_node = rr_gsb.get_chan_node(side_manager.get_side(), itrack); + for (size_t itrack = 0; + itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) { + const RRNodeId& chan_rr_node = + rr_gsb.get_chan_node(side_manager.get_side(), itrack); /* We only care the output port and it should indicate a SB mux */ - if (OUT_PORT != rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) { - continue; + if (OUT_PORT != + rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) { + continue; } /* Constrain thru wires */ - if (false != rr_gsb.is_sb_node_passing_wire(rr_graph, side_manager.get_side(), itrack)) { + if (false != rr_gsb.is_sb_node_passing_wire( + rr_graph, side_manager.get_side(), itrack)) { continue; - } + } /* This is a MUX, constrain all the paths from an input to an output */ - print_pnr_sdc_constrain_sb_mux_timing(fp, - time_unit, - hierarchical, - module_path, - module_manager, sb_module, - device_annotation, - grids, - rr_graph, - rr_gsb, - side_manager.get_side(), - chan_rr_node, - constrain_zero_delay_paths); + print_pnr_sdc_constrain_sb_mux_timing( + fp, time_unit, hierarchical, module_path, module_manager, sb_module, + device_annotation, grids, rr_graph, rr_gsb, side_manager.get_side(), + chan_rr_node, constrain_zero_delay_paths); } } @@ -214,16 +194,14 @@ void print_pnr_sdc_constrain_sb_timing(const PnrSdcOption& options, * Print SDC timing constraints for Switch blocks * This function is designed for flatten routing hierarchy *******************************************************************/ -void print_pnr_sdc_flatten_routing_constrain_sb_timing(const PnrSdcOption& options, - const ModuleManager& module_manager, - const ModuleId& top_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb) { - +void print_pnr_sdc_flatten_routing_constrain_sb_timing( + const PnrSdcOption& options, const ModuleManager& module_manager, + const ModuleId& top_module, const VprDeviceAnnotation& device_annotation, + const DeviceGrid& grids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb) { /* Start time count */ - vtr::ScopedStartFinishTimer timer("Write SDC for constrain Switch Block timing for P&R flow"); + vtr::ScopedStartFinishTimer timer( + "Write SDC for constrain Switch Block timing for P&R flow"); std::string root_path = module_manager.module_name(top_module); @@ -238,19 +216,16 @@ void print_pnr_sdc_flatten_routing_constrain_sb_timing(const PnrSdcOption& optio } vtr::Point gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); - std::string sb_instance_name = generate_switch_block_module_name(gsb_coordinate); + std::string sb_instance_name = + generate_switch_block_module_name(gsb_coordinate); ModuleId sb_module = module_manager.find_module(sb_instance_name); VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); std::string module_path = format_dir_path(root_path) + sb_instance_name; - print_pnr_sdc_constrain_sb_timing(options, - module_path, - module_manager, - device_annotation, - grids, - rr_graph, + print_pnr_sdc_constrain_sb_timing(options, module_path, module_manager, + device_annotation, grids, rr_graph, rr_gsb); } } @@ -260,16 +235,14 @@ void print_pnr_sdc_flatten_routing_constrain_sb_timing(const PnrSdcOption& optio * Print SDC timing constraints for Switch blocks * This function is designed for compact routing hierarchy *******************************************************************/ -void print_pnr_sdc_compact_routing_constrain_sb_timing(const PnrSdcOption& options, - const ModuleManager& module_manager, - const ModuleId& top_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb) { - +void print_pnr_sdc_compact_routing_constrain_sb_timing( + const PnrSdcOption& options, const ModuleManager& module_manager, + const ModuleId& top_module, const VprDeviceAnnotation& device_annotation, + const DeviceGrid& grids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb) { /* Start time count */ - vtr::ScopedStartFinishTimer timer("Write SDC for constrain Switch Block timing for P&R flow"); + vtr::ScopedStartFinishTimer timer( + "Write SDC for constrain Switch Block timing for P&R flow"); std::string root_path = module_manager.module_name(top_module); @@ -280,22 +253,19 @@ void print_pnr_sdc_compact_routing_constrain_sb_timing(const PnrSdcOption& optio } /* Find all the sb instance under this module - * Create a regular expression to include these instance names + * Create a regular expression to include these instance names */ vtr::Point gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); - std::string sb_module_name = generate_switch_block_module_name(gsb_coordinate); + std::string sb_module_name = + generate_switch_block_module_name(gsb_coordinate); ModuleId sb_module = module_manager.find_module(sb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); - + std::string module_path = format_dir_path(root_path) + sb_module_name; - print_pnr_sdc_constrain_sb_timing(options, - module_path, - module_manager, - device_annotation, - grids, - rr_graph, + print_pnr_sdc_constrain_sb_timing(options, module_path, module_manager, + device_annotation, grids, rr_graph, rr_gsb); } } @@ -304,30 +274,24 @@ void print_pnr_sdc_compact_routing_constrain_sb_timing(const PnrSdcOption& optio * Set timing constraints between the inputs and outputs of a routing * multiplexer in a Connection Block *******************************************************************/ -static -void print_pnr_sdc_constrain_cb_mux_timing(std::fstream& fp, - const float& time_unit, - const bool& hierarchical, - const std::string& module_path, - const ModuleManager& module_manager, - const ModuleId& cb_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const t_rr_type& cb_type, - const RRNodeId& output_rr_node, - const bool& constrain_zero_delay_paths) { +static void print_pnr_sdc_constrain_cb_mux_timing( + std::fstream& fp, const float& time_unit, const bool& hierarchical, + const std::string& module_path, const ModuleManager& module_manager, + const ModuleId& cb_module, const VprDeviceAnnotation& device_annotation, + const DeviceGrid& grids, const RRGraphView& rr_graph, const RRGSB& rr_gsb, + const t_rr_type& cb_type, const RRNodeId& output_rr_node, + const bool& constrain_zero_delay_paths) { /* Validate file stream */ valid_file_stream(fp); VTR_ASSERT(IPIN == rr_graph.node_type(output_rr_node)); - + /* We have OPINs since we may have direct connections: - * These connections should be handled by other functions in the compact_netlist.c - * So we just return here for OPINs + * These connections should be handled by other functions in the + * compact_netlist.c So we just return here for OPINs */ - std::vector input_rr_nodes = get_rr_graph_configurable_driver_nodes(rr_graph, output_rr_node); + std::vector input_rr_nodes = + get_rr_graph_configurable_driver_nodes(rr_graph, output_rr_node); if (0 == input_rr_nodes.size()) { return; @@ -337,8 +301,8 @@ void print_pnr_sdc_constrain_cb_mux_timing(std::fstream& fp, * As a result, the direct connection is considered to be configurable... * Here, I simply kick out OPINs in CB connection because they should be built * in the top mopdule. - * - * Note: this MUST BE reconsidered if we do have OPIN connected to IPINs + * + * Note: this MUST BE reconsidered if we do have OPIN connected to IPINs * through a programmable multiplexer!!! */ if (true == is_ipin_direct_connected_opin(rr_graph, output_rr_node)) { @@ -346,80 +310,69 @@ void print_pnr_sdc_constrain_cb_mux_timing(std::fstream& fp, } /* Find the module port corresponding to the output rr_node */ - ModulePortId module_output_port = find_connection_block_module_ipin_port(module_manager, - cb_module, - grids, - device_annotation, - rr_graph, - rr_gsb, - output_rr_node); + ModulePortId module_output_port = find_connection_block_module_ipin_port( + module_manager, cb_module, grids, device_annotation, rr_graph, rr_gsb, + output_rr_node); - /* Find the module port corresponding to the fan-in rr_nodes of the output rr_node */ - std::vector module_input_ports = find_connection_block_module_input_ports(module_manager, - cb_module, - rr_graph, - rr_gsb, - cb_type, - input_rr_nodes); + /* Find the module port corresponding to the fan-in rr_nodes of the output + * rr_node */ + std::vector module_input_ports = + find_connection_block_module_input_ports( + module_manager, cb_module, rr_graph, rr_gsb, cb_type, input_rr_nodes); /* Find timing constraints for each path (edge) */ std::map switch_delays; size_t edge_counter = 0; - for (const RREdgeId& edge : rr_graph.node_configurable_in_edges(output_rr_node)) { + for (const RREdgeId& edge : + rr_graph.node_configurable_in_edges(output_rr_node)) { /* Get the switch delay */ const RRSwitchId& driver_switch = rr_graph.edge_switch(edge); - switch_delays[module_input_ports[edge_counter]] = find_pnr_sdc_switch_tmax(rr_graph.rr_switch_inf(driver_switch)); + switch_delays[module_input_ports[edge_counter]] = + find_pnr_sdc_switch_tmax(rr_graph.rr_switch_inf(driver_switch)); edge_counter++; } /* Find the starting points */ for (const ModulePinInfo& module_input_port : module_input_ports) { - /* If we have a zero-delay path to contrain, we will skip unless users want so */ - if ( (false == constrain_zero_delay_paths) - && (0. == switch_delays[module_input_port]) ) { + /* If we have a zero-delay path to contrain, we will skip unless users want + * so */ + if ((false == constrain_zero_delay_paths) && + (0. == switch_delays[module_input_port])) { continue; } - BasicPort input_port(module_manager.module_port(cb_module, module_input_port.first).get_name(), - module_input_port.second, - module_input_port.second); - BasicPort output_port = module_manager.module_port(cb_module, module_output_port); + BasicPort input_port( + module_manager.module_port(cb_module, module_input_port.first).get_name(), + module_input_port.second, module_input_port.second); + BasicPort output_port = + module_manager.module_port(cb_module, module_output_port); /* Constrain a path */ if (true == hierarchical) { - print_pnr_sdc_constrain_max_delay(fp, - std::string(), - generate_sdc_port(input_port), - std::string(), - generate_sdc_port(output_port), - switch_delays[module_input_port] / time_unit); + print_pnr_sdc_constrain_max_delay( + fp, std::string(), generate_sdc_port(input_port), std::string(), + generate_sdc_port(output_port), + switch_delays[module_input_port] / time_unit); } else { VTR_ASSERT_SAFE(false == hierarchical); - print_pnr_sdc_constrain_max_delay(fp, - std::string(module_path), - generate_sdc_port(input_port), - std::string(module_path), - generate_sdc_port(output_port), - switch_delays[module_input_port] / time_unit); - + print_pnr_sdc_constrain_max_delay( + fp, std::string(module_path), generate_sdc_port(input_port), + std::string(module_path), generate_sdc_port(output_port), + switch_delays[module_input_port] / time_unit); } } } /******************************************************************** - * Print SDC timing constraints for a Connection block + * Print SDC timing constraints for a Connection block * This function is designed for compact routing hierarchy *******************************************************************/ -static -void print_pnr_sdc_constrain_cb_timing(const PnrSdcOption& options, - const std::string& module_path, - const ModuleManager& module_manager, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const t_rr_type& cb_type) { +static void print_pnr_sdc_constrain_cb_timing( + const PnrSdcOption& options, const std::string& module_path, + const ModuleManager& module_manager, + const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type) { std::string sdc_dir = options.sdc_dir(); float time_unit = options.time_unit(); bool include_time_stamp = options.time_stamp(); @@ -427,10 +380,13 @@ void print_pnr_sdc_constrain_cb_timing(const PnrSdcOption& options, bool constrain_zero_delay_paths = options.constrain_zero_delay_paths(); /* Create the netlist */ - vtr::Point gsb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); + vtr::Point gsb_coordinate(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); /* Find the module name and create a SDC file for it */ - std::string sdc_fname(sdc_dir + generate_connection_block_module_name(cb_type, gsb_coordinate) + std::string(SDC_FILE_NAME_POSTFIX)); + std::string sdc_fname( + sdc_dir + generate_connection_block_module_name(cb_type, gsb_coordinate) + + std::string(SDC_FILE_NAME_POSTFIX)); /* Create the file stream */ std::fstream fp; @@ -439,70 +395,72 @@ void print_pnr_sdc_constrain_cb_timing(const PnrSdcOption& options, /* Validate file stream */ check_file_stream(sdc_fname.c_str(), fp); - std::string cb_module_name = generate_connection_block_module_name(cb_type, gsb_coordinate); + std::string cb_module_name = + generate_connection_block_module_name(cb_type, gsb_coordinate); ModuleId cb_module = module_manager.find_module(cb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); /* Generate the descriptions*/ print_sdc_file_header(fp, - std::string("Constrain timing of Connection Block " + cb_module_name + " for PnR"), + std::string("Constrain timing of Connection Block " + + cb_module_name + " for PnR"), include_time_stamp); /* Print time unit for the SDC file */ print_sdc_timescale(fp, time_unit_to_string(time_unit)); /* Contrain each routing track inside the connection block */ - for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); ++itrack) { + for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); + ++itrack) { /* Create a port description for the input */ - std::string input_port_name = generate_cb_module_track_port_name(cb_type, - IN_PORT, - 0 == itrack % 2); - ModulePortId input_port_id = module_manager.find_module_port(cb_module, input_port_name); - BasicPort input_port(module_manager.module_port(cb_module, input_port_id).get_name(), - itrack / 2, itrack / 2); + std::string input_port_name = + generate_cb_module_track_port_name(cb_type, IN_PORT, 0 == itrack % 2); + ModulePortId input_port_id = + module_manager.find_module_port(cb_module, input_port_name); + BasicPort input_port( + module_manager.module_port(cb_module, input_port_id).get_name(), + itrack / 2, itrack / 2); /* Create a port description for the output */ - std::string output_port_name = generate_cb_module_track_port_name(cb_type, - OUT_PORT, - 0 == itrack % 2); - ModulePortId output_port_id = module_manager.find_module_port(cb_module, output_port_name); - BasicPort output_port(module_manager.module_port(cb_module, output_port_id).get_name(), - itrack / 2, itrack / 2); + std::string output_port_name = + generate_cb_module_track_port_name(cb_type, OUT_PORT, 0 == itrack % 2); + ModulePortId output_port_id = + module_manager.find_module_port(cb_module, output_port_name); + BasicPort output_port( + module_manager.module_port(cb_module, output_port_id).get_name(), + itrack / 2, itrack / 2); /* Connection block routing segment ids for each track */ - RRSegmentId segment_id = rr_gsb.get_chan_node_segment(rr_gsb.get_cb_chan_side(cb_type), itrack); + RRSegmentId segment_id = + rr_gsb.get_chan_node_segment(rr_gsb.get_cb_chan_side(cb_type), itrack); /* Computing the delay of the routing segment - * Here we just assume a simple 1-level RC delay model + * Here we just assume a simple 1-level RC delay model * TODO: Should consider multi-level RC delay models * where the number of levels are defined by users */ - float routing_segment_delay = rr_graph.rr_segments(segment_id).Rmetal - * rr_graph.rr_segments(segment_id).Cmetal; + float routing_segment_delay = rr_graph.rr_segments(segment_id).Rmetal * + rr_graph.rr_segments(segment_id).Cmetal; - /* If we have a zero-delay path to contrain, we will skip unless users want so */ - if ( (false == constrain_zero_delay_paths) - && (0. == routing_segment_delay) ) { + /* If we have a zero-delay path to contrain, we will skip unless users want + * so */ + if ((false == constrain_zero_delay_paths) && + (0. == routing_segment_delay)) { continue; } /* Constrain a path with routing segment delay */ if (true == hierarchical) { - print_pnr_sdc_constrain_max_delay(fp, - std::string(), - generate_sdc_port(input_port), - std::string(), - generate_sdc_port(output_port), - routing_segment_delay / time_unit); + print_pnr_sdc_constrain_max_delay( + fp, std::string(), generate_sdc_port(input_port), std::string(), + generate_sdc_port(output_port), routing_segment_delay / time_unit); } else { VTR_ASSERT_SAFE(false == hierarchical); - print_pnr_sdc_constrain_max_delay(fp, - std::string(module_path), - generate_sdc_port(input_port), - std::string(module_path), - generate_sdc_port(output_port), - routing_segment_delay / time_unit); + print_pnr_sdc_constrain_max_delay( + fp, std::string(module_path), generate_sdc_port(input_port), + std::string(module_path), generate_sdc_port(output_port), + routing_segment_delay / time_unit); } } @@ -512,17 +470,13 @@ void print_pnr_sdc_constrain_cb_timing(const PnrSdcOption& options, for (size_t side = 0; side < cb_sides.size(); ++side) { enum e_side cb_ipin_side = cb_sides[side]; SideManager side_manager(cb_ipin_side); - for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); ++inode) { + for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); + ++inode) { const RRNodeId& ipin_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, inode); - print_pnr_sdc_constrain_cb_mux_timing(fp, - time_unit, - hierarchical, module_path, - module_manager, cb_module, - device_annotation, - grids, - rr_graph, rr_gsb, cb_type, - ipin_rr_node, - constrain_zero_delay_paths); + print_pnr_sdc_constrain_cb_mux_timing( + fp, time_unit, hierarchical, module_path, module_manager, cb_module, + device_annotation, grids, rr_graph, rr_gsb, cb_type, ipin_rr_node, + constrain_zero_delay_paths); } } @@ -532,17 +486,13 @@ void print_pnr_sdc_constrain_cb_timing(const PnrSdcOption& options, /******************************************************************** * Iterate over all the connection blocks in a device - * and print SDC file for each of them + * and print SDC file for each of them *******************************************************************/ -static -void print_pnr_sdc_flatten_routing_constrain_cb_timing(const PnrSdcOption& options, - const ModuleManager& module_manager, - const ModuleId& top_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, - const t_rr_type& cb_type) { +static void print_pnr_sdc_flatten_routing_constrain_cb_timing( + const PnrSdcOption& options, const ModuleManager& module_manager, + const ModuleId& top_module, const VprDeviceAnnotation& device_annotation, + const DeviceGrid& grids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, const t_rr_type& cb_type) { /* Build unique X-direction connection block modules */ vtr::Point cb_range = device_rr_gsb.get_gsb_range(); @@ -551,7 +501,7 @@ void print_pnr_sdc_flatten_routing_constrain_cb_timing(const PnrSdcOption& optio for (size_t ix = 0; ix < cb_range.x(); ++ix) { for (size_t iy = 0; iy < cb_range.y(); ++iy) { /* Check if the connection block exists in the device! - * Some of them do NOT exist due to heterogeneous blocks (height > 1) + * Some of them do NOT exist due to heterogeneous blocks (height > 1) * We will skip those modules */ const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); @@ -560,123 +510,103 @@ void print_pnr_sdc_flatten_routing_constrain_cb_timing(const PnrSdcOption& optio } /* Find all the cb instance under this module - * Create a regular expression to include these instance names + * Create a regular expression to include these instance names */ - vtr::Point gsb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); - std::string cb_instance_name = generate_connection_block_module_name(cb_type, gsb_coordinate); + vtr::Point gsb_coordinate(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); + std::string cb_instance_name = + generate_connection_block_module_name(cb_type, gsb_coordinate); ModuleId cb_module = module_manager.find_module(cb_instance_name); VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); std::string module_path = format_dir_path(root_path) + cb_instance_name; - print_pnr_sdc_constrain_cb_timing(options, - module_path, - module_manager, - device_annotation, - grids, - rr_graph, - rr_gsb, - cb_type); - + print_pnr_sdc_constrain_cb_timing(options, module_path, module_manager, + device_annotation, grids, rr_graph, + rr_gsb, cb_type); } } } /******************************************************************** * Iterate over all the connection blocks in a device - * and print SDC file for each of them + * and print SDC file for each of them *******************************************************************/ -void print_pnr_sdc_flatten_routing_constrain_cb_timing(const PnrSdcOption& options, - const ModuleManager& module_manager, - const ModuleId& top_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb) { - +void print_pnr_sdc_flatten_routing_constrain_cb_timing( + const PnrSdcOption& options, const ModuleManager& module_manager, + const ModuleId& top_module, const VprDeviceAnnotation& device_annotation, + const DeviceGrid& grids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb) { /* Start time count */ - vtr::ScopedStartFinishTimer timer("Write SDC for constrain Connection Block timing for P&R flow"); + vtr::ScopedStartFinishTimer timer( + "Write SDC for constrain Connection Block timing for P&R flow"); - print_pnr_sdc_flatten_routing_constrain_cb_timing(options, - module_manager, top_module, - device_annotation, - grids, - rr_graph, - device_rr_gsb, - CHANX); + print_pnr_sdc_flatten_routing_constrain_cb_timing( + options, module_manager, top_module, device_annotation, grids, rr_graph, + device_rr_gsb, CHANX); - print_pnr_sdc_flatten_routing_constrain_cb_timing(options, - module_manager, top_module, - device_annotation, - grids, - rr_graph, - device_rr_gsb, - CHANY); + print_pnr_sdc_flatten_routing_constrain_cb_timing( + options, module_manager, top_module, device_annotation, grids, rr_graph, + device_rr_gsb, CHANY); } /******************************************************************** * Print SDC timing constraints for Connection blocks * This function is designed for compact routing hierarchy *******************************************************************/ -void print_pnr_sdc_compact_routing_constrain_cb_timing(const PnrSdcOption& options, - const ModuleManager& module_manager, - const ModuleId& top_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb) { - +void print_pnr_sdc_compact_routing_constrain_cb_timing( + const PnrSdcOption& options, const ModuleManager& module_manager, + const ModuleId& top_module, const VprDeviceAnnotation& device_annotation, + const DeviceGrid& grids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb) { /* Start time count */ - vtr::ScopedStartFinishTimer timer("Write SDC for constrain Connection Block timing for P&R flow"); + vtr::ScopedStartFinishTimer timer( + "Write SDC for constrain Connection Block timing for P&R flow"); std::string root_path = module_manager.module_name(top_module); /* Print SDC for unique X-direction connection block modules */ - for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANX); ++icb) { + for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANX); + ++icb) { const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(CHANX, icb); /* Find all the cb instance under this module - * Create a regular expression to include these instance names + * Create a regular expression to include these instance names */ - vtr::Point gsb_coordinate(unique_mirror.get_cb_x(CHANX), unique_mirror.get_cb_y(CHANX)); - std::string cb_module_name = generate_connection_block_module_name(CHANX, gsb_coordinate); + vtr::Point gsb_coordinate(unique_mirror.get_cb_x(CHANX), + unique_mirror.get_cb_y(CHANX)); + std::string cb_module_name = + generate_connection_block_module_name(CHANX, gsb_coordinate); ModuleId cb_module = module_manager.find_module(cb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); std::string module_path = format_dir_path(root_path) + cb_module_name; - print_pnr_sdc_constrain_cb_timing(options, - module_path, - module_manager, - device_annotation, - grids, - rr_graph, - unique_mirror, - CHANX); + print_pnr_sdc_constrain_cb_timing(options, module_path, module_manager, + device_annotation, grids, rr_graph, + unique_mirror, CHANX); } /* Print SDC for unique Y-direction connection block modules */ - for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANY); ++icb) { + for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANY); + ++icb) { const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(CHANY, icb); /* Find all the cb instance under this module - * Create a regular expression to include these instance names + * Create a regular expression to include these instance names */ - vtr::Point gsb_coordinate(unique_mirror.get_cb_x(CHANY), unique_mirror.get_cb_y(CHANY)); - std::string cb_module_name = generate_connection_block_module_name(CHANY, gsb_coordinate); + vtr::Point gsb_coordinate(unique_mirror.get_cb_x(CHANY), + unique_mirror.get_cb_y(CHANY)); + std::string cb_module_name = + generate_connection_block_module_name(CHANY, gsb_coordinate); ModuleId cb_module = module_manager.find_module(cb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); std::string module_path = format_dir_path(root_path) + cb_module_name; - print_pnr_sdc_constrain_cb_timing(options, - module_path, - module_manager, - device_annotation, - grids, - rr_graph, - unique_mirror, - CHANY); + print_pnr_sdc_constrain_cb_timing(options, module_path, module_manager, + device_annotation, grids, rr_graph, + unique_mirror, CHANY); } } diff --git a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.h b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.h index 4fbf1c838..9ea45c9e6 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.h +++ b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.h @@ -6,12 +6,13 @@ *******************************************************************/ #include #include -#include "module_manager.h" -#include "device_rr_gsb.h" -#include "rr_graph_view.h" + #include "device_grid.h" -#include "vpr_device_annotation.h" +#include "device_rr_gsb.h" +#include "module_manager.h" #include "pnr_sdc_option.h" +#include "rr_graph_view.h" +#include "vpr_device_annotation.h" /******************************************************************** * Function declaration @@ -20,37 +21,29 @@ /* begin namespace openfpga */ namespace openfpga { -void print_pnr_sdc_flatten_routing_constrain_sb_timing(const PnrSdcOption& options, - const ModuleManager& module_manager, - const ModuleId& top_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb); +void print_pnr_sdc_flatten_routing_constrain_sb_timing( + const PnrSdcOption& options, const ModuleManager& module_manager, + const ModuleId& top_module, const VprDeviceAnnotation& device_annotation, + const DeviceGrid& grids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb); -void print_pnr_sdc_compact_routing_constrain_sb_timing(const PnrSdcOption& options, - const ModuleManager& module_manager, - const ModuleId& top_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb); +void print_pnr_sdc_compact_routing_constrain_sb_timing( + const PnrSdcOption& options, const ModuleManager& module_manager, + const ModuleId& top_module, const VprDeviceAnnotation& device_annotation, + const DeviceGrid& grids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb); -void print_pnr_sdc_flatten_routing_constrain_cb_timing(const PnrSdcOption& options, - const ModuleManager& module_manager, - const ModuleId& top_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb); +void print_pnr_sdc_flatten_routing_constrain_cb_timing( + const PnrSdcOption& options, const ModuleManager& module_manager, + const ModuleId& top_module, const VprDeviceAnnotation& device_annotation, + const DeviceGrid& grids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb); -void print_pnr_sdc_compact_routing_constrain_cb_timing(const PnrSdcOption& options, - const ModuleManager& module_manager, - const ModuleId& top_module, - const VprDeviceAnnotation& device_annotation, - const DeviceGrid& grids, - const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb); +void print_pnr_sdc_compact_routing_constrain_cb_timing( + const PnrSdcOption& options, const ModuleManager& module_manager, + const ModuleId& top_module, const VprDeviceAnnotation& device_annotation, + const DeviceGrid& grids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp b/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp index 280f9608b..b7b272641 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp @@ -1,8 +1,8 @@ /******************************************************************** - * This file includes functions that print SDC (Synopsys Design Constraint) + * This file includes functions that print SDC (Synopsys Design Constraint) * files in physical design tools, i.e., Place & Route (PnR) tools * The SDC files are used to constrain the physical design for each module - * in FPGA fabric, such as Configurable Logic Blocks (CLBs), + * in FPGA fabric, such as Configurable Logic Blocks (CLBs), * Heterogeneous blocks, Switch Blocks (SBs) and Connection Blocks (CBs) * * Note that this is different from the SDC to constrain VPR Place&Route @@ -14,48 +14,46 @@ /* Headers from vtrutil library */ #include "vtr_assert.h" -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgautil library */ +#include "mux_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" #include "openfpga_port.h" #include "openfpga_wildcard_string.h" -#include "openfpga_digest.h" - -#include "mux_utils.h" - -#include "openfpga_naming.h" - -#include "sdc_writer_naming.h" -#include "sdc_writer_utils.h" +#include "pnr_sdc_global_port.h" +#include "pnr_sdc_grid_writer.h" +#include "pnr_sdc_routing_writer.h" +#include "pnr_sdc_writer.h" +#include "sdc_hierarchy_writer.h" #include "sdc_memory_utils.h" #include "sdc_mux_utils.h" -#include "sdc_hierarchy_writer.h" -#include "pnr_sdc_global_port.h" -#include "pnr_sdc_routing_writer.h" -#include "pnr_sdc_grid_writer.h" -#include "pnr_sdc_writer.h" +#include "sdc_writer_naming.h" +#include "sdc_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** * Break combinational loops in FPGA fabric, which mainly come from - * configurable memory cells. + * configurable memory cells. * To handle this, we disable the outputs of memory cells *******************************************************************/ -static -void print_pnr_sdc_constrain_configurable_memory_outputs(const std::string& sdc_dir, - const bool& flatten_names, - const bool& include_time_stamp, - const ModuleManager& module_manager, - const ModuleId& top_module) { - +static void print_pnr_sdc_constrain_configurable_memory_outputs( + const std::string& sdc_dir, const bool& flatten_names, + const bool& include_time_stamp, const ModuleManager& module_manager, + const ModuleId& top_module) { /* Create the file name for Verilog netlist */ - std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_CONFIG_MEM_OUTPUTS_FILE_NAME)); + std::string sdc_fname(sdc_dir + + std::string(SDC_DISABLE_CONFIG_MEM_OUTPUTS_FILE_NAME)); /* Start time count */ - std::string timer_message = std::string("Write SDC to disable configurable memory outputs for P&R flow '") + sdc_fname + std::string("'"); + std::string timer_message = + std::string( + "Write SDC to disable configurable memory outputs for P&R flow '") + + sdc_fname + std::string("'"); vtr::ScopedStartFinishTimer timer(timer_message); /* Create the file stream */ @@ -65,35 +63,38 @@ void print_pnr_sdc_constrain_configurable_memory_outputs(const std::string& sdc_ check_file_stream(sdc_fname.c_str(), fp); /* Generate the descriptions*/ - print_sdc_file_header(fp, std::string("Disable configurable memory outputs for PnR"), include_time_stamp); + print_sdc_file_header( + fp, std::string("Disable configurable memory outputs for PnR"), + include_time_stamp); - /* Go recursively in the module manager, starting from the top-level module: instance id of the top-level module is 0 by default */ - rec_print_pnr_sdc_disable_configurable_memory_module_output(fp, flatten_names, - module_manager, top_module, - format_dir_path(module_manager.module_name(top_module))); + /* Go recursively in the module manager, starting from the top-level module: + * instance id of the top-level module is 0 by default */ + rec_print_pnr_sdc_disable_configurable_memory_module_output( + fp, flatten_names, module_manager, top_module, + format_dir_path(module_manager.module_name(top_module))); /* Close file handler */ fp.close(); } /******************************************************************** - * Break combinational loops in FPGA fabric, which mainly come from + * Break combinational loops in FPGA fabric, which mainly come from * loops of multiplexers. * To handle this, we disable the timing at outputs of Switch blocks * This function is designed for flatten routing hierarchy *******************************************************************/ -static -void print_pnr_sdc_flatten_routing_disable_switch_block_outputs(const std::string& sdc_dir, - const bool& flatten_names, - const bool& include_time_stamp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const DeviceRRGSB& device_rr_gsb) { +static void print_pnr_sdc_flatten_routing_disable_switch_block_outputs( + const std::string& sdc_dir, const bool& flatten_names, + const bool& include_time_stamp, const ModuleManager& module_manager, + const ModuleId& top_module, const DeviceRRGSB& device_rr_gsb) { /* Create the file name for Verilog netlist */ - std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_SB_OUTPUTS_FILE_NAME)); + std::string sdc_fname(sdc_dir + + std::string(SDC_DISABLE_SB_OUTPUTS_FILE_NAME)); /* Start time count */ - std::string timer_message = std::string("Write SDC to disable switch block outputs for P&R flow '") + sdc_fname + std::string("'"); + std::string timer_message = + std::string("Write SDC to disable switch block outputs for P&R flow '") + + sdc_fname + std::string("'"); vtr::ScopedStartFinishTimer timer(timer_message); /* Create the file stream */ @@ -103,12 +104,14 @@ void print_pnr_sdc_flatten_routing_disable_switch_block_outputs(const std::strin check_file_stream(sdc_fname.c_str(), fp); /* Generate the descriptions*/ - print_sdc_file_header(fp, std::string("Disable Switch Block outputs for PnR"), include_time_stamp); + print_sdc_file_header(fp, std::string("Disable Switch Block outputs for PnR"), + include_time_stamp); - std::string root_path = format_dir_path(module_manager.module_name(top_module)); + std::string root_path = + format_dir_path(module_manager.module_name(top_module)); - /* Build wildcard names for the instance names of multiple-instanced-blocks (MIB) - * We will find all the instance names and see there are common prefix + /* Build wildcard names for the instance names of multiple-instanced-blocks + * (MIB) We will find all the instance names and see there are common prefix * If so, we can use wildcards */ std::map> wildcard_names; @@ -127,28 +130,31 @@ void print_pnr_sdc_flatten_routing_disable_switch_block_outputs(const std::strin std::string module_path = root_path; vtr::Point gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); - std::string sb_instance_name = generate_switch_block_module_name(gsb_coordinate); + std::string sb_instance_name = + generate_switch_block_module_name(gsb_coordinate); ModuleId sb_module = module_manager.find_module(sb_instance_name); VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); - if (false == flatten_names) { - /* Try to adapt to a wildcard name: replace all the numbers with a wildcard character '*' */ - WildCardString wildcard_str(sb_instance_name); + if (false == flatten_names) { + /* Try to adapt to a wildcard name: replace all the numbers with a + * wildcard character '*' */ + WildCardString wildcard_str(sb_instance_name); /* If the wildcard name is already in the list, we can skip this - * Otherwise, we have to - * - output this instance - * - record the wildcard name in the map + * Otherwise, we have to + * - output this instance + * - record the wildcard name in the map */ - if ( (0 < wildcard_names.count(sb_module)) - && (wildcard_names.at(sb_module).end() != std::find(wildcard_names.at(sb_module).begin(), - wildcard_names.at(sb_module).end(), - wildcard_str.data())) ) { + if ((0 < wildcard_names.count(sb_module)) && + (wildcard_names.at(sb_module).end() != + std::find(wildcard_names.at(sb_module).begin(), + wildcard_names.at(sb_module).end(), + wildcard_str.data()))) { continue; } module_path += wildcard_str.data(); - + wildcard_names[sb_module].push_back(wildcard_str.data()); } else { module_path += sb_instance_name; @@ -159,25 +165,27 @@ void print_pnr_sdc_flatten_routing_disable_switch_block_outputs(const std::strin std::vector port_wildcard_names; /* Disable the outputs of the module */ - for (const BasicPort& output_port : module_manager.module_ports_by_type(sb_module, ModuleManager::MODULE_OUTPUT_PORT)) { - std::string port_name = output_port.get_name(); + for (const BasicPort& output_port : module_manager.module_ports_by_type( + sb_module, ModuleManager::MODULE_OUTPUT_PORT)) { + std::string port_name = output_port.get_name(); - if (false == flatten_names) { - /* Try to adapt to a wildcard name: replace all the numbers with a wildcard character '*' */ - WildCardString port_wildcard_str(output_port.get_name()); + if (false == flatten_names) { + /* Try to adapt to a wildcard name: replace all the numbers with a + * wildcard character '*' */ + WildCardString port_wildcard_str(output_port.get_name()); /* If the wildcard name is already in the list, we can skip this - * Otherwise, we have to - * - output this port + * Otherwise, we have to + * - output this port * - record the wildcard name in the vector */ - if (port_wildcard_names.end() != std::find(port_wildcard_names.begin(), - port_wildcard_names.end(), - port_wildcard_str.data())) { + if (port_wildcard_names.end() != + std::find(port_wildcard_names.begin(), port_wildcard_names.end(), + port_wildcard_str.data())) { continue; } port_name = port_wildcard_str.data(); - + port_wildcard_names.push_back(port_wildcard_str.data()); } @@ -189,29 +197,29 @@ void print_pnr_sdc_flatten_routing_disable_switch_block_outputs(const std::strin } } } - + /* Close file handler */ fp.close(); } /******************************************************************** - * Break combinational loops in FPGA fabric, which mainly come from + * Break combinational loops in FPGA fabric, which mainly come from * loops of multiplexers. * To handle this, we disable the timing at outputs of Switch blocks * This function is designed for compact routing hierarchy *******************************************************************/ -static -void print_pnr_sdc_compact_routing_disable_switch_block_outputs(const std::string& sdc_dir, - const bool& flatten_names, - const bool& include_time_stamp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const DeviceRRGSB& device_rr_gsb) { +static void print_pnr_sdc_compact_routing_disable_switch_block_outputs( + const std::string& sdc_dir, const bool& flatten_names, + const bool& include_time_stamp, const ModuleManager& module_manager, + const ModuleId& top_module, const DeviceRRGSB& device_rr_gsb) { /* Create the file name for Verilog netlist */ - std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_SB_OUTPUTS_FILE_NAME)); + std::string sdc_fname(sdc_dir + + std::string(SDC_DISABLE_SB_OUTPUTS_FILE_NAME)); /* Start time count */ - std::string timer_message = std::string("Write SDC to disable switch block outputs for P&R flow '") + sdc_fname + std::string("'"); + std::string timer_message = + std::string("Write SDC to disable switch block outputs for P&R flow '") + + sdc_fname + std::string("'"); vtr::ScopedStartFinishTimer timer(timer_message); /* Create the file stream */ @@ -221,12 +229,14 @@ void print_pnr_sdc_compact_routing_disable_switch_block_outputs(const std::strin check_file_stream(sdc_fname.c_str(), fp); /* Generate the descriptions*/ - print_sdc_file_header(fp, std::string("Disable Switch Block outputs for PnR"), include_time_stamp); + print_sdc_file_header(fp, std::string("Disable Switch Block outputs for PnR"), + include_time_stamp); - std::string root_path = format_dir_path(module_manager.module_name(top_module)); + std::string root_path = + format_dir_path(module_manager.module_name(top_module)); - /* Build wildcard names for the instance names of multiple-instanced-blocks (MIB) - * We will find all the instance names and see there are common prefix + /* Build wildcard names for the instance names of multiple-instanced-blocks + * (MIB) We will find all the instance names and see there are common prefix * If so, we can use wildcards */ std::map> wildcard_names; @@ -240,34 +250,39 @@ void print_pnr_sdc_compact_routing_disable_switch_block_outputs(const std::strin } vtr::Point gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); - std::string sb_module_name = generate_switch_block_module_name(gsb_coordinate); + std::string sb_module_name = + generate_switch_block_module_name(gsb_coordinate); ModuleId sb_module = module_manager.find_module(sb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); - + std::string module_path = root_path; /* Find all the instances in the top-level module */ - for (const size_t& instance_id : module_manager.child_module_instances(top_module, sb_module)) { - std::string sb_instance_name = module_manager.instance_name(top_module, sb_module, instance_id); + for (const size_t& instance_id : + module_manager.child_module_instances(top_module, sb_module)) { + std::string sb_instance_name = + module_manager.instance_name(top_module, sb_module, instance_id); - if (false == flatten_names) { - /* Try to adapt to a wildcard name: replace all the numbers with a wildcard character '*' */ - WildCardString wildcard_str(sb_instance_name); + if (false == flatten_names) { + /* Try to adapt to a wildcard name: replace all the numbers with a + * wildcard character '*' */ + WildCardString wildcard_str(sb_instance_name); /* If the wildcard name is already in the list, we can skip this - * Otherwise, we have to - * - output this instance - * - record the wildcard name in the map + * Otherwise, we have to + * - output this instance + * - record the wildcard name in the map */ - if ( (0 < wildcard_names.count(sb_module)) - && (wildcard_names.at(sb_module).end() != std::find(wildcard_names.at(sb_module).begin(), - wildcard_names.at(sb_module).end(), - wildcard_str.data())) ) { + if ((0 < wildcard_names.count(sb_module)) && + (wildcard_names.at(sb_module).end() != + std::find(wildcard_names.at(sb_module).begin(), + wildcard_names.at(sb_module).end(), + wildcard_str.data()))) { continue; } module_path += wildcard_str.data(); - + wildcard_names[sb_module].push_back(wildcard_str.data()); } else { module_path += sb_instance_name; @@ -278,25 +293,27 @@ void print_pnr_sdc_compact_routing_disable_switch_block_outputs(const std::strin std::vector port_wildcard_names; /* Disable the outputs of the module */ - for (const BasicPort& output_port : module_manager.module_ports_by_type(sb_module, ModuleManager::MODULE_OUTPUT_PORT)) { - std::string port_name = output_port.get_name(); + for (const BasicPort& output_port : module_manager.module_ports_by_type( + sb_module, ModuleManager::MODULE_OUTPUT_PORT)) { + std::string port_name = output_port.get_name(); - if (false == flatten_names) { - /* Try to adapt to a wildcard name: replace all the numbers with a wildcard character '*' */ - WildCardString port_wildcard_str(output_port.get_name()); + if (false == flatten_names) { + /* Try to adapt to a wildcard name: replace all the numbers with a + * wildcard character '*' */ + WildCardString port_wildcard_str(output_port.get_name()); /* If the wildcard name is already in the list, we can skip this - * Otherwise, we have to - * - output this port + * Otherwise, we have to + * - output this port * - record the wildcard name in the vector */ - if (port_wildcard_names.end() != std::find(port_wildcard_names.begin(), - port_wildcard_names.end(), - port_wildcard_str.data())) { + if (port_wildcard_names.end() != + std::find(port_wildcard_names.begin(), port_wildcard_names.end(), + port_wildcard_str.data())) { continue; } port_name = port_wildcard_str.data(); - + port_wildcard_names.push_back(port_wildcard_str.data()); } @@ -308,7 +325,7 @@ void print_pnr_sdc_compact_routing_disable_switch_block_outputs(const std::strin } } } - + /* Close file handler */ fp.close(); } @@ -318,7 +335,7 @@ void print_pnr_sdc_compact_routing_disable_switch_block_outputs(const std::strin * This function will generate files upon the options provided by users * 1. Design constraints for CLBs * 2. Design constraints for Switch Blocks - * 3. Design constraints for Connection Blocks + * 3. Design constraints for Connection Blocks * 4. Design constraints for breaking the combinational loops in FPGA fabric *******************************************************************/ void print_pnr_sdc(const PnrSdcOption& sdc_options, @@ -326,148 +343,106 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options, const VprDeviceAnnotation& device_annotation, const DeviceRRGSB& device_rr_gsb, const ModuleManager& module_manager, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, const FabricGlobalPortInfo& global_ports, const SimulationSetting& sim_setting, const bool& compact_routing_hierarchy) { - std::string top_module_name = generate_fpga_top_module_name(); ModuleId top_module = module_manager.find_module(top_module_name); VTR_ASSERT(true == module_manager.valid_module_id(top_module)); /* Constrain global ports */ if (true == sdc_options.constrain_global_port()) { - print_pnr_sdc_global_ports(sdc_options, - module_manager, top_module, global_ports, - sim_setting); + print_pnr_sdc_global_ports(sdc_options, module_manager, top_module, + global_ports, sim_setting); } /* Output Design Constraints to disable outputs of memory cells */ if (true == sdc_options.constrain_configurable_memory_outputs()) { - print_pnr_sdc_constrain_configurable_memory_outputs(sdc_options.sdc_dir(), - sdc_options.flatten_names(), - sdc_options.time_stamp(), - module_manager, - top_module); - } + print_pnr_sdc_constrain_configurable_memory_outputs( + sdc_options.sdc_dir(), sdc_options.flatten_names(), + sdc_options.time_stamp(), module_manager, top_module); + } /* Break loops from Multiplexer Output */ if (true == sdc_options.constrain_routing_multiplexer_outputs()) { - print_sdc_disable_routing_multiplexer_outputs(sdc_options.sdc_dir(), - sdc_options.flatten_names(), - sdc_options.time_stamp(), - mux_lib, circuit_lib, - module_manager, - top_module); + print_sdc_disable_routing_multiplexer_outputs( + sdc_options.sdc_dir(), sdc_options.flatten_names(), + sdc_options.time_stamp(), mux_lib, circuit_lib, module_manager, + top_module); } /* Break loops from any SB output */ if (true == sdc_options.constrain_switch_block_outputs()) { if (true == compact_routing_hierarchy) { - print_pnr_sdc_compact_routing_disable_switch_block_outputs(sdc_options.sdc_dir(), - sdc_options.flatten_names(), - sdc_options.time_stamp(), - module_manager, top_module, - device_rr_gsb); + print_pnr_sdc_compact_routing_disable_switch_block_outputs( + sdc_options.sdc_dir(), sdc_options.flatten_names(), + sdc_options.time_stamp(), module_manager, top_module, device_rr_gsb); } else { - VTR_ASSERT_SAFE (false == compact_routing_hierarchy); - print_pnr_sdc_flatten_routing_disable_switch_block_outputs(sdc_options.sdc_dir(), - sdc_options.flatten_names(), - sdc_options.time_stamp(), - module_manager, top_module, - device_rr_gsb); + VTR_ASSERT_SAFE(false == compact_routing_hierarchy); + print_pnr_sdc_flatten_routing_disable_switch_block_outputs( + sdc_options.sdc_dir(), sdc_options.flatten_names(), + sdc_options.time_stamp(), module_manager, top_module, device_rr_gsb); } } /* Output routing constraints for Switch Blocks */ if (true == sdc_options.constrain_sb()) { if (true == compact_routing_hierarchy) { - print_pnr_sdc_compact_routing_constrain_sb_timing(sdc_options, - module_manager, - top_module, - device_annotation, - device_ctx.grid, - device_ctx.rr_graph, - device_rr_gsb); + print_pnr_sdc_compact_routing_constrain_sb_timing( + sdc_options, module_manager, top_module, device_annotation, + device_ctx.grid, device_ctx.rr_graph, device_rr_gsb); } else { - VTR_ASSERT_SAFE (false == compact_routing_hierarchy); - print_pnr_sdc_flatten_routing_constrain_sb_timing(sdc_options, - module_manager, - top_module, - device_annotation, - device_ctx.grid, - device_ctx.rr_graph, - device_rr_gsb); + VTR_ASSERT_SAFE(false == compact_routing_hierarchy); + print_pnr_sdc_flatten_routing_constrain_sb_timing( + sdc_options, module_manager, top_module, device_annotation, + device_ctx.grid, device_ctx.rr_graph, device_rr_gsb); } } /* Output hierachy to plain text file */ - if ( (true == sdc_options.constrain_sb()) - && (true == sdc_options.output_hierarchy()) - && (true == compact_routing_hierarchy) ) { - print_pnr_sdc_routing_sb_hierarchy(sdc_options.sdc_dir(), - module_manager, - top_module, - device_rr_gsb); + if ((true == sdc_options.constrain_sb()) && + (true == sdc_options.output_hierarchy()) && + (true == compact_routing_hierarchy)) { + print_pnr_sdc_routing_sb_hierarchy(sdc_options.sdc_dir(), module_manager, + top_module, device_rr_gsb); } /* Output routing constraints for Connection Blocks */ if (true == sdc_options.constrain_cb()) { if (true == compact_routing_hierarchy) { - print_pnr_sdc_compact_routing_constrain_cb_timing(sdc_options, - module_manager, - top_module, - device_annotation, - device_ctx.grid, - device_ctx.rr_graph, - device_rr_gsb); + print_pnr_sdc_compact_routing_constrain_cb_timing( + sdc_options, module_manager, top_module, device_annotation, + device_ctx.grid, device_ctx.rr_graph, device_rr_gsb); } else { - VTR_ASSERT_SAFE (false == compact_routing_hierarchy); - print_pnr_sdc_flatten_routing_constrain_cb_timing(sdc_options, - module_manager, - top_module, - device_annotation, - device_ctx.grid, - device_ctx.rr_graph, - device_rr_gsb); + VTR_ASSERT_SAFE(false == compact_routing_hierarchy); + print_pnr_sdc_flatten_routing_constrain_cb_timing( + sdc_options, module_manager, top_module, device_annotation, + device_ctx.grid, device_ctx.rr_graph, device_rr_gsb); } } /* Output hierachy to plain text file */ - if ( (true == sdc_options.constrain_cb()) - && (true == sdc_options.output_hierarchy()) - && (true == compact_routing_hierarchy) ) { - print_pnr_sdc_routing_cb_hierarchy(sdc_options.sdc_dir(), - module_manager, - top_module, - CHANX, - device_rr_gsb); + if ((true == sdc_options.constrain_cb()) && + (true == sdc_options.output_hierarchy()) && + (true == compact_routing_hierarchy)) { + print_pnr_sdc_routing_cb_hierarchy(sdc_options.sdc_dir(), module_manager, + top_module, CHANX, device_rr_gsb); - print_pnr_sdc_routing_cb_hierarchy(sdc_options.sdc_dir(), - module_manager, - top_module, - CHANY, - device_rr_gsb); + print_pnr_sdc_routing_cb_hierarchy(sdc_options.sdc_dir(), module_manager, + top_module, CHANY, device_rr_gsb); } /* Output Timing constraints for Programmable blocks */ if (true == sdc_options.constrain_grid()) { - print_pnr_sdc_constrain_grid_timing(sdc_options, - device_ctx, - device_annotation, - module_manager, - top_module); + print_pnr_sdc_constrain_grid_timing( + sdc_options, device_ctx, device_annotation, module_manager, top_module); } - if ( (true == sdc_options.constrain_grid()) - && (true == sdc_options.output_hierarchy()) ) { - print_pnr_sdc_grid_hierarchy(sdc_options.sdc_dir(), - device_ctx, - device_annotation, - module_manager, - top_module); - + if ((true == sdc_options.constrain_grid()) && + (true == sdc_options.output_hierarchy())) { + print_pnr_sdc_grid_hierarchy(sdc_options.sdc_dir(), device_ctx, + device_annotation, module_manager, top_module); } } diff --git a/openfpga/src/fpga_sdc/pnr_sdc_writer.h b/openfpga/src/fpga_sdc/pnr_sdc_writer.h index 169d91543..00c1642eb 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_writer.h +++ b/openfpga/src/fpga_sdc/pnr_sdc_writer.h @@ -6,15 +6,16 @@ *******************************************************************/ #include #include -#include "vpr_context.h" -#include "vpr_device_annotation.h" + +#include "circuit_library.h" #include "device_rr_gsb.h" +#include "fabric_global_port_info.h" #include "module_manager.h" #include "mux_library.h" -#include "circuit_library.h" -#include "simulation_setting.h" -#include "fabric_global_port_info.h" #include "pnr_sdc_option.h" +#include "simulation_setting.h" +#include "vpr_context.h" +#include "vpr_device_annotation.h" /******************************************************************** * Function declaration @@ -28,8 +29,7 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options, const VprDeviceAnnotation& device_annotation, const DeviceRRGSB& device_rr_gsb, const ModuleManager& module_manager, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, const FabricGlobalPortInfo& global_ports, const SimulationSetting& sim_setting, const bool& compact_routing_hierarchy); diff --git a/openfpga/src/fpga_sdc/sdc_hierarchy_writer.cpp b/openfpga/src/fpga_sdc/sdc_hierarchy_writer.cpp index e7f23917d..e9d46fa4a 100644 --- a/openfpga/src/fpga_sdc/sdc_hierarchy_writer.cpp +++ b/openfpga/src/fpga_sdc/sdc_hierarchy_writer.cpp @@ -2,45 +2,41 @@ * Output instance hierarchy in SDC to file formats ***************************************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgautil library */ #include "openfpga_digest.h" - -#include "openfpga_reserved_words.h" #include "openfpga_naming.h" - -#include "pb_type_utils.h" #include "openfpga_physical_tile_utils.h" - -#include "sdc_writer_naming.h" +#include "openfpga_reserved_words.h" +#include "pb_type_utils.h" #include "sdc_hierarchy_writer.h" +#include "sdc_writer_naming.h" /* begin namespace openfpga */ namespace openfpga { /*************************************************************************************** - * Write the hierarchy of Switch Block module and its instances to a plain text file - * e.g., - * - * / + * Write the hierarchy of Switch Block module and its instances to a plain text + *file e.g., / * ... - * This file is mainly used by hierarchical P&R flow + * This file is mainly used by hierarchical P&R flow * * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture + * Return 1 if there are more serious bugs in the architecture * Return 2 if fail when creating files ***************************************************************************************/ void print_pnr_sdc_routing_sb_hierarchy(const std::string& sdc_dir, const ModuleManager& module_manager, const ModuleId& top_module, const DeviceRRGSB& device_rr_gsb) { - std::string fname(sdc_dir + std::string(SDC_SB_HIERARCHY_FILE_NAME)); - std::string timer_message = std::string("Write Switch Block hierarchy to plain-text file '") + fname + std::string("'"); + std::string timer_message = + std::string("Write Switch Block hierarchy to plain-text file '") + fname + + std::string("'"); std::string dir_path = format_dir_path(find_path_dir_name(fname)); @@ -68,25 +64,31 @@ void print_pnr_sdc_routing_sb_hierarchy(const std::string& sdc_dir, } /* Find all the sb instance under this module - * Create a regular expression to include these instance names + * Create a regular expression to include these instance names */ vtr::Point gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); - std::string sb_module_name = generate_switch_block_module_name(gsb_coordinate); + std::string sb_module_name = + generate_switch_block_module_name(gsb_coordinate); ModuleId sb_module = module_manager.find_module(sb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); /* Create the file name for SDC */ - std::string sdc_fname(sdc_dir + generate_switch_block_module_name(gsb_coordinate) + std::string(SDC_FILE_NAME_POSTFIX)); + std::string sdc_fname(sdc_dir + + generate_switch_block_module_name(gsb_coordinate) + + std::string(SDC_FILE_NAME_POSTFIX)); - fp << "- " << sb_module_name << ":" << "\n"; + fp << "- " << sb_module_name << ":" + << "\n"; /* Go through all the instance */ - for (const size_t& instance_id : module_manager.child_module_instances(top_module, sb_module)) { - std::string sb_instance_name = module_manager.instance_name(top_module, sb_module, instance_id); + for (const size_t& instance_id : + module_manager.child_module_instances(top_module, sb_module)) { + std::string sb_instance_name = + module_manager.instance_name(top_module, sb_module, instance_id); fp << " "; - fp << "- " << sb_instance_name << "\n"; - } + fp << "- " << sb_instance_name << "\n"; + } fp << "\n"; } @@ -96,15 +98,13 @@ void print_pnr_sdc_routing_sb_hierarchy(const std::string& sdc_dir, } /*************************************************************************************** - * Write the hierarchy of Switch Block module and its instances to a plain text file - * e.g., - * - * / + * Write the hierarchy of Switch Block module and its instances to a plain text + *file e.g., / * ... - * This file is mainly used by hierarchical P&R flow + * This file is mainly used by hierarchical P&R flow * * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture + * Return 1 if there are more serious bugs in the architecture * Return 2 if fail when creating files ***************************************************************************************/ void print_pnr_sdc_routing_cb_hierarchy(const std::string& sdc_dir, @@ -112,7 +112,6 @@ void print_pnr_sdc_routing_cb_hierarchy(const std::string& sdc_dir, const ModuleId& top_module, const t_rr_type& cb_type, const DeviceRRGSB& device_rr_gsb) { - std::string fname(sdc_dir); if (CHANX == cb_type) { fname += std::string(SDC_CBX_HIERARCHY_FILE_NAME); @@ -121,7 +120,9 @@ void print_pnr_sdc_routing_cb_hierarchy(const std::string& sdc_dir, fname += std::string(SDC_CBY_HIERARCHY_FILE_NAME); } - std::string timer_message = std::string("Write Connection Block hierarchy to plain-text file '") + fname + std::string("'"); + std::string timer_message = + std::string("Write Connection Block hierarchy to plain-text file '") + + fname + std::string("'"); std::string dir_path = format_dir_path(find_path_dir_name(fname)); @@ -143,28 +144,37 @@ void print_pnr_sdc_routing_cb_hierarchy(const std::string& sdc_dir, check_file_stream(fname.c_str(), fp); /* Print SDC for unique X-direction connection block modules */ - for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(cb_type); ++icb) { - const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(cb_type, icb); + for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(cb_type); + ++icb) { + const RRGSB& unique_mirror = + device_rr_gsb.get_cb_unique_module(cb_type, icb); /* Find all the cb instance under this module - * Create a regular expression to include these instance names + * Create a regular expression to include these instance names */ - vtr::Point gsb_coordinate(unique_mirror.get_cb_x(cb_type), unique_mirror.get_cb_y(cb_type)); - std::string cb_module_name = generate_connection_block_module_name(cb_type, gsb_coordinate); + vtr::Point gsb_coordinate(unique_mirror.get_cb_x(cb_type), + unique_mirror.get_cb_y(cb_type)); + std::string cb_module_name = + generate_connection_block_module_name(cb_type, gsb_coordinate); ModuleId cb_module = module_manager.find_module(cb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); /* Create the file name for SDC */ - std::string sdc_fname(sdc_dir + generate_connection_block_module_name(cb_type, gsb_coordinate) + std::string(SDC_FILE_NAME_POSTFIX)); + std::string sdc_fname( + sdc_dir + generate_connection_block_module_name(cb_type, gsb_coordinate) + + std::string(SDC_FILE_NAME_POSTFIX)); - fp << "- " << cb_module_name << ":" << "\n"; + fp << "- " << cb_module_name << ":" + << "\n"; /* Go through all the instance */ - for (const size_t& instance_id : module_manager.child_module_instances(top_module, cb_module)) { - std::string cb_instance_name = module_manager.instance_name(top_module, cb_module, instance_id); + for (const size_t& instance_id : + module_manager.child_module_instances(top_module, cb_module)) { + std::string cb_instance_name = + module_manager.instance_name(top_module, cb_module, instance_id); fp << " "; - fp << "- " << cb_instance_name << "\n"; - } + fp << "- " << cb_instance_name << "\n"; + } fp << "\n"; } @@ -174,88 +184,87 @@ void print_pnr_sdc_routing_cb_hierarchy(const std::string& sdc_dir, } /******************************************************************** - * Recursively write the hierarchy of pb_type and its instances to a plain text file - * e.g., - * - * / + * Recursively write the hierarchy of pb_type and its instances to a plain text + *file e.g., / * ... - * This file is mainly used by hierarchical P&R flow + * This file is mainly used by hierarchical P&R flow *******************************************************************/ -static -void rec_print_pnr_sdc_grid_pb_graph_hierarchy(std::fstream& fp, - const size_t& depth, - const ModuleManager& module_manager, - const ModuleId& parent_pb_module, - const VprDeviceAnnotation& device_annotation, - t_pb_graph_node* parent_pb_graph_node) { +static void rec_print_pnr_sdc_grid_pb_graph_hierarchy( + std::fstream& fp, const size_t& depth, const ModuleManager& module_manager, + const ModuleId& parent_pb_module, + const VprDeviceAnnotation& device_annotation, + t_pb_graph_node* parent_pb_graph_node) { /* Validate the file stream */ VTR_ASSERT(true == valid_file_stream(fp)); /* Validate pb_graph node */ if (nullptr == parent_pb_graph_node) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid parent_pb_graph_node.\n"); + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid parent_pb_graph_node.\n"); exit(1); } /* Get the pb_type */ t_pb_type* parent_pb_type = parent_pb_graph_node->pb_type; - std::string pb_module_name = generate_physical_block_module_name(parent_pb_type); + std::string pb_module_name = + generate_physical_block_module_name(parent_pb_type); /* Find the pb module in module manager */ ModuleId pb_module = module_manager.find_module(pb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); write_space_to_file(fp, depth * 2); - fp << "- " << pb_module_name << ":" << "\n"; + fp << "- " << pb_module_name << ":" + << "\n"; /* Go through all the instance */ - for (const size_t& instance_id : module_manager.child_module_instances(parent_pb_module, pb_module)) { - std::string child_instance_name = module_manager.instance_name(parent_pb_module, pb_module, instance_id); + for (const size_t& instance_id : + module_manager.child_module_instances(parent_pb_module, pb_module)) { + std::string child_instance_name = + module_manager.instance_name(parent_pb_module, pb_module, instance_id); write_space_to_file(fp, depth * 2); fp << " "; - fp << "- " << child_instance_name; + fp << "- " << child_instance_name; if (true == is_primitive_pb_type(parent_pb_type)) { fp << "\n"; return; } - - fp << ":" << "\n"; - /* Note we only go through the graph through the physical modes. - * which we build the modules + fp << ":" + << "\n"; + + /* Note we only go through the graph through the physical modes. + * which we build the modules */ - t_mode* physical_mode = device_annotation.physical_mode(parent_pb_type); + t_mode* physical_mode = device_annotation.physical_mode(parent_pb_type); /* Go recursively to the lower level in the pb_graph - * Note that we assume a full hierarchical P&R, we will only visit pb_graph_node of unique pb_type + * Note that we assume a full hierarchical P&R, we will only visit + * pb_graph_node of unique pb_type */ for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) { - for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; ++jpb) { - rec_print_pnr_sdc_grid_pb_graph_hierarchy(fp, - depth + 2, - module_manager, - pb_module, - device_annotation, - &(parent_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb])); + for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; + ++jpb) { + rec_print_pnr_sdc_grid_pb_graph_hierarchy( + fp, depth + 2, module_manager, pb_module, device_annotation, + &(parent_pb_graph_node + ->child_pb_graph_nodes[physical_mode->index][ipb][jpb])); } } - } + } } - /*************************************************************************************** * Write the hierarchy of grid module and its instances to a plain text file * e.g., * * / * ... - * This file is mainly used by hierarchical P&R flow + * This file is mainly used by hierarchical P&R flow * * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture + * Return 1 if there are more serious bugs in the architecture * Return 2 if fail when creating files ***************************************************************************************/ void print_pnr_sdc_grid_hierarchy(const std::string& sdc_dir, @@ -263,10 +272,11 @@ void print_pnr_sdc_grid_hierarchy(const std::string& sdc_dir, const VprDeviceAnnotation& device_annotation, const ModuleManager& module_manager, const ModuleId& top_module) { - std::string fname(sdc_dir + std::string(SDC_GRID_HIERARCHY_FILE_NAME)); - std::string timer_message = std::string("Write Grid hierarchy to plain-text file '") + fname + std::string("'"); + std::string timer_message = + std::string("Write Grid hierarchy to plain-text file '") + fname + + std::string("'"); std::string dir_path = format_dir_path(find_path_dir_name(fname)); @@ -287,9 +297,11 @@ void print_pnr_sdc_grid_hierarchy(const std::string& sdc_dir, /* Validate the file stream */ check_file_stream(fname.c_str(), fp); - std::string root_path = format_dir_path(module_manager.module_name(top_module)); + std::string root_path = + format_dir_path(module_manager.module_name(top_module)); - for (const t_physical_tile_type& physical_tile : device_ctx.physical_tile_types) { + for (const t_physical_tile_type& physical_tile : + device_ctx.physical_tile_types) { /* Bypass empty type or nullptr */ if (true == is_empty_type(&physical_tile)) { continue; @@ -297,7 +309,8 @@ void print_pnr_sdc_grid_hierarchy(const std::string& sdc_dir, for (const t_sub_tile& sub_tile : physical_tile.sub_tiles) { VTR_ASSERT(1 == sub_tile.equivalent_sites.size()); - t_pb_graph_node* pb_graph_head = sub_tile.equivalent_sites[0]->pb_graph_head; + t_pb_graph_node* pb_graph_head = + sub_tile.equivalent_sites[0]->pb_graph_head; if (nullptr == pb_graph_head) { continue; } @@ -307,66 +320,67 @@ void print_pnr_sdc_grid_hierarchy(const std::string& sdc_dir, * We will search the grids and see where the I/O blocks are located: * - If a I/O block locates on border sides of FPGA fabric: * i.e., one or more from {TOP, RIGHT, BOTTOM, LEFT}, - * we will generate one module for each border side + * we will generate one module for each border side * - If a I/O block locates in the center of FPGA fabric: - * we will generate one module with NUM_SIDES (same treatment as regular grids) + * we will generate one module with NUM_SIDES (same treatment as + * regular grids) */ - std::set io_type_sides = find_physical_io_tile_located_sides(device_ctx.grid, - &physical_tile); - + std::set io_type_sides = + find_physical_io_tile_located_sides(device_ctx.grid, &physical_tile); /* Generate the grid module name */ for (const e_side& io_type_side : io_type_sides) { - std::string grid_module_name = generate_grid_block_module_name(std::string(GRID_MODULE_NAME_PREFIX), - std::string(physical_tile.name), - is_io_type(&physical_tile), - io_type_side); + std::string grid_module_name = generate_grid_block_module_name( + std::string(GRID_MODULE_NAME_PREFIX), + std::string(physical_tile.name), is_io_type(&physical_tile), + io_type_side); /* Find the module Id */ ModuleId grid_module = module_manager.find_module(grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); - fp << "- " << grid_module_name << ":" << "\n"; + fp << "- " << grid_module_name << ":" + << "\n"; /* Go through all the instance */ - for (const size_t& instance_id : module_manager.child_module_instances(top_module, grid_module)) { - std::string grid_instance_name = module_manager.instance_name(top_module, grid_module, instance_id); + for (const size_t& instance_id : + module_manager.child_module_instances(top_module, grid_module)) { + std::string grid_instance_name = module_manager.instance_name( + top_module, grid_module, instance_id); fp << " "; - fp << "- " << grid_instance_name << ":" << "\n"; + fp << "- " << grid_instance_name << ":" + << "\n"; - rec_print_pnr_sdc_grid_pb_graph_hierarchy(fp, - 2, - module_manager, - grid_module, - device_annotation, - pb_graph_head); - } + rec_print_pnr_sdc_grid_pb_graph_hierarchy( + fp, 2, module_manager, grid_module, device_annotation, + pb_graph_head); + } fp << "\n"; } } else { /* For CLB and heterogenenous blocks */ - std::string grid_module_name = generate_grid_block_module_name(std::string(GRID_MODULE_NAME_PREFIX), - std::string(physical_tile.name), - is_io_type(&physical_tile), - NUM_SIDES); + std::string grid_module_name = generate_grid_block_module_name( + std::string(GRID_MODULE_NAME_PREFIX), std::string(physical_tile.name), + is_io_type(&physical_tile), NUM_SIDES); /* Find the module Id */ ModuleId grid_module = module_manager.find_module(grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); - fp << "- " << grid_module_name << ":" << "\n"; + fp << "- " << grid_module_name << ":" + << "\n"; /* Go through all the instance */ - for (const size_t& instance_id : module_manager.child_module_instances(top_module, grid_module)) { - std::string grid_instance_name = module_manager.instance_name(top_module, grid_module, instance_id); + for (const size_t& instance_id : + module_manager.child_module_instances(top_module, grid_module)) { + std::string grid_instance_name = + module_manager.instance_name(top_module, grid_module, instance_id); fp << " "; - fp << "- " << grid_instance_name << ":" << "\n"; + fp << "- " << grid_instance_name << ":" + << "\n"; - rec_print_pnr_sdc_grid_pb_graph_hierarchy(fp, - 2, - module_manager, - grid_module, - device_annotation, - pb_graph_head); - } + rec_print_pnr_sdc_grid_pb_graph_hierarchy( + fp, 2, module_manager, grid_module, device_annotation, + pb_graph_head); + } fp << "\n"; } } @@ -376,5 +390,4 @@ void print_pnr_sdc_grid_hierarchy(const std::string& sdc_dir, fp.close(); } - } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/sdc_hierarchy_writer.h b/openfpga/src/fpga_sdc/sdc_hierarchy_writer.h index eb4aaf9c0..39c5fd565 100644 --- a/openfpga/src/fpga_sdc/sdc_hierarchy_writer.h +++ b/openfpga/src/fpga_sdc/sdc_hierarchy_writer.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" #include "openfpga_context.h" +#include "vpr_context.h" /******************************************************************** * Function declaration @@ -31,7 +31,6 @@ void print_pnr_sdc_grid_hierarchy(const std::string& sdc_dir, const ModuleManager& module_manager, const ModuleId& top_module); - } /* end namespace openfpga */ #endif diff --git a/openfpga/src/fpga_sdc/sdc_memory_utils.cpp b/openfpga/src/fpga_sdc/sdc_memory_utils.cpp index c9459ebaf..12d45b887 100644 --- a/openfpga/src/fpga_sdc/sdc_memory_utils.cpp +++ b/openfpga/src/fpga_sdc/sdc_memory_utils.cpp @@ -8,22 +8,19 @@ #include "vtr_log.h" /* Headers from openfpgautil library */ -#include "openfpga_wildcard_string.h" #include "openfpga_digest.h" - #include "openfpga_naming.h" - -#include "sdc_writer_utils.h" - +#include "openfpga_wildcard_string.h" #include "sdc_memory_utils.h" +#include "sdc_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** * Print SDC commands to disable outputs of all the configurable memory modules - * in a given module - * This function will be executed in a recursive way, + * in a given module + * This function will be executed in a recursive way, * using a Depth-First Search (DFS) strategy * It will iterate over all the configurable children under each module * and print a SDC command to disable its outputs @@ -34,63 +31,71 @@ namespace openfpga { * - When flatten_names is false * It will straightforwardly output the instance name and port name * This function will try to apply wildcard to names - * so that SDC file size can be minimal + * so that SDC file size can be minimal *******************************************************************/ -void rec_print_pnr_sdc_disable_configurable_memory_module_output(std::fstream& fp, - const bool& flatten_names, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const std::string& parent_module_path) { - - /* Build wildcard names for the instance names of multiple-instanced-blocks (MIB) - * We will find all the instance names and see there are common prefix +void rec_print_pnr_sdc_disable_configurable_memory_module_output( + std::fstream& fp, const bool& flatten_names, + const ModuleManager& module_manager, const ModuleId& parent_module, + const std::string& parent_module_path) { + /* Build wildcard names for the instance names of multiple-instanced-blocks + * (MIB) We will find all the instance names and see there are common prefix * If so, we can use wildcards */ std::map> wildcard_names; /* For each configurable child, we will go one level down in priority */ - for (size_t child_index = 0; child_index < module_manager.configurable_children(parent_module).size(); ++child_index) { + for (size_t child_index = 0; + child_index < module_manager.configurable_children(parent_module).size(); + ++child_index) { std::string child_module_path = parent_module_path; - ModuleId child_module_id = module_manager.configurable_children(parent_module)[child_index]; - size_t child_instance_id = module_manager.configurable_child_instances(parent_module)[child_index]; + ModuleId child_module_id = + module_manager.configurable_children(parent_module)[child_index]; + size_t child_instance_id = + module_manager.configurable_child_instances(parent_module)[child_index]; std::string child_instance_name; - if (true == module_manager.instance_name(parent_module, child_module_id, child_instance_id).empty()) { - child_instance_name = generate_instance_name(module_manager.module_name(child_module_id), child_instance_id); + if (true == + module_manager + .instance_name(parent_module, child_module_id, child_instance_id) + .empty()) { + child_instance_name = generate_instance_name( + module_manager.module_name(child_module_id), child_instance_id); } else { - child_instance_name = module_manager.instance_name(parent_module, child_module_id, child_instance_id); + child_instance_name = module_manager.instance_name( + parent_module, child_module_id, child_instance_id); } - if (false == flatten_names) { - /* Try to adapt to a wildcard name: replace all the numbers with a wildcard character '*' */ - WildCardString wildcard_str(child_instance_name); + if (false == flatten_names) { + /* Try to adapt to a wildcard name: replace all the numbers with a + * wildcard character '*' */ + WildCardString wildcard_str(child_instance_name); /* If the wildcard name is already in the list, we can skip this - * Otherwise, we have to - * - output this instance - * - record the wildcard name in the map + * Otherwise, we have to + * - output this instance + * - record the wildcard name in the map */ - if ( (0 < wildcard_names.count(child_module_id)) - && (wildcard_names.at(child_module_id).end() != std::find(wildcard_names.at(child_module_id).begin(), - wildcard_names.at(child_module_id).end(), - wildcard_str.data())) ) { + if ((0 < wildcard_names.count(child_module_id)) && + (wildcard_names.at(child_module_id).end() != + std::find(wildcard_names.at(child_module_id).begin(), + wildcard_names.at(child_module_id).end(), + wildcard_str.data()))) { continue; } child_module_path += wildcard_str.data(); - + wildcard_names[child_module_id].push_back(wildcard_str.data()); } else { child_module_path += child_instance_name; } - + child_module_path = format_dir_path(child_module_path); - rec_print_pnr_sdc_disable_configurable_memory_module_output(fp, flatten_names, - module_manager, - child_module_id, - child_module_path); + rec_print_pnr_sdc_disable_configurable_memory_module_output( + fp, flatten_names, module_manager, child_module_id, child_module_path); } - /* If there is no configurable children any more, this is a leaf module, print a SDC command for disable timing */ + /* If there is no configurable children any more, this is a leaf module, print + * a SDC command for disable timing */ if (0 < module_manager.configurable_children(parent_module).size()) { return; } @@ -99,7 +104,8 @@ void rec_print_pnr_sdc_disable_configurable_memory_module_output(std::fstream& f valid_file_stream(fp); /* Disable timing for each output port of this module */ - for (const BasicPort& output_port : module_manager.module_ports_by_type(parent_module, ModuleManager::MODULE_OUTPUT_PORT)) { + for (const BasicPort& output_port : module_manager.module_ports_by_type( + parent_module, ModuleManager::MODULE_OUTPUT_PORT)) { fp << "set_disable_timing "; fp << parent_module_path << output_port.get_name(); fp << std::endl; diff --git a/openfpga/src/fpga_sdc/sdc_memory_utils.h b/openfpga/src/fpga_sdc/sdc_memory_utils.h index 576b3a36e..238775869 100644 --- a/openfpga/src/fpga_sdc/sdc_memory_utils.h +++ b/openfpga/src/fpga_sdc/sdc_memory_utils.h @@ -6,6 +6,7 @@ *******************************************************************/ #include #include + #include "module_manager.h" /******************************************************************** @@ -15,11 +16,10 @@ /* begin namespace openfpga */ namespace openfpga { -void rec_print_pnr_sdc_disable_configurable_memory_module_output(std::fstream& fp, - const bool& flatten_names, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const std::string& parent_module_path); +void rec_print_pnr_sdc_disable_configurable_memory_module_output( + std::fstream& fp, const bool& flatten_names, + const ModuleManager& module_manager, const ModuleId& parent_module, + const std::string& parent_module_path); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/sdc_mux_utils.cpp b/openfpga/src/fpga_sdc/sdc_mux_utils.cpp index 86cf90519..e162b28a4 100644 --- a/openfpga/src/fpga_sdc/sdc_mux_utils.cpp +++ b/openfpga/src/fpga_sdc/sdc_mux_utils.cpp @@ -12,39 +12,37 @@ #include "command_exit_codes.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" - -#include "mux_utils.h" #include "circuit_library_utils.h" - +#include "mux_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "sdc_mux_utils.h" #include "sdc_writer_naming.h" #include "sdc_writer_utils.h" -#include "sdc_mux_utils.h" - /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * Break combinational loops in FPGA fabric, which mainly come from + * Break combinational loops in FPGA fabric, which mainly come from * loops of multiplexers. * To handle this, we disable the timing at outputs of routing multiplexers *******************************************************************/ -void print_sdc_disable_routing_multiplexer_outputs(const std::string& sdc_dir, - const bool& flatten_names, - const bool& include_time_stamp, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const ModuleManager& module_manager, - const ModuleId& top_module) { +void print_sdc_disable_routing_multiplexer_outputs( + const std::string& sdc_dir, const bool& flatten_names, + const bool& include_time_stamp, const MuxLibrary& mux_lib, + const CircuitLibrary& circuit_lib, const ModuleManager& module_manager, + const ModuleId& top_module) { /* Create the file name for Verilog netlist */ - std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_MUX_OUTPUTS_FILE_NAME)); + std::string sdc_fname(sdc_dir + + std::string(SDC_DISABLE_MUX_OUTPUTS_FILE_NAME)); /* Start time count */ - std::string timer_message = std::string("Write SDC to disable routing multiplexer outputs for P&R flow '") + sdc_fname + std::string("'"); + std::string timer_message = + std::string( + "Write SDC to disable routing multiplexer outputs for P&R flow '") + + sdc_fname + std::string("'"); vtr::ScopedStartFinishTimer timer(timer_message); /* Create the file stream */ @@ -54,38 +52,41 @@ void print_sdc_disable_routing_multiplexer_outputs(const std::string& sdc_dir, check_file_stream(sdc_fname.c_str(), fp); /* Generate the descriptions*/ - print_sdc_file_header(fp, std::string("Disable routing multiplexer outputs for PnR"), include_time_stamp); + print_sdc_file_header( + fp, std::string("Disable routing multiplexer outputs for PnR"), + include_time_stamp); /* Iterate over the MUX modules */ for (const MuxId& mux_id : mux_lib.muxes()) { const CircuitModelId& mux_model = mux_lib.mux_circuit_model(mux_id); - + /* Skip LUTs, we only care about multiplexers here */ if (CIRCUIT_MODEL_MUX != circuit_lib.model_type(mux_model)) { continue; } const MuxGraph& mux_graph = mux_lib.mux_graph(mux_id); - std::string mux_module_name = generate_mux_subckt_name(circuit_lib, mux_model, - find_mux_num_datapath_inputs(circuit_lib, mux_model, mux_graph.num_inputs()), - std::string("")); + std::string mux_module_name = generate_mux_subckt_name( + circuit_lib, mux_model, + find_mux_num_datapath_inputs(circuit_lib, mux_model, + mux_graph.num_inputs()), + std::string("")); /* Find the module name in module manager */ ModuleId mux_module = module_manager.find_module(mux_module_name); VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); - /* Go recursively in the module manager, - * starting from the top-level module: instance id of the top-level module is 0 by default - * Disable all the outputs of child modules that matches the mux_module id + /* Go recursively in the module manager, + * starting from the top-level module: instance id of the top-level module + * is 0 by default Disable all the outputs of child modules that matches the + * mux_module id */ - for (const BasicPort& output_port : module_manager.module_ports_by_type(mux_module, ModuleManager::MODULE_OUTPUT_PORT)) { - rec_print_sdc_disable_timing_for_module_ports(fp, - flatten_names, - module_manager, - top_module, - mux_module, - format_dir_path(module_manager.module_name(top_module)), - output_port.get_name()); + for (const BasicPort& output_port : module_manager.module_ports_by_type( + mux_module, ModuleManager::MODULE_OUTPUT_PORT)) { + rec_print_sdc_disable_timing_for_module_ports( + fp, flatten_names, module_manager, top_module, mux_module, + format_dir_path(module_manager.module_name(top_module)), + output_port.get_name()); } } @@ -94,21 +95,19 @@ void print_sdc_disable_routing_multiplexer_outputs(const std::string& sdc_dir, } /******************************************************************** - * Break combinational loops in FPGA fabric, which mainly come from + * Break combinational loops in FPGA fabric, which mainly come from * loops of multiplexers. - * To handle this, we disable the timing at configuration ports of routing multiplexers + * To handle this, we disable the timing at configuration ports of routing + *multiplexers * * Return code: * 0: success * 1: fatal error occurred *******************************************************************/ -int print_sdc_disable_routing_multiplexer_configure_ports(std::fstream& fp, - const bool& flatten_names, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const ModuleManager& module_manager, - const ModuleId& top_module) { - +int print_sdc_disable_routing_multiplexer_configure_ports( + std::fstream& fp, const bool& flatten_names, const MuxLibrary& mux_lib, + const CircuitLibrary& circuit_lib, const ModuleManager& module_manager, + const ModuleId& top_module) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } @@ -121,48 +120,51 @@ int print_sdc_disable_routing_multiplexer_configure_ports(std::fstream& fp, if (CIRCUIT_MODEL_MUX != circuit_lib.model_type(mux_model)) { continue; } - + const MuxGraph& mux_graph = mux_lib.mux_graph(mux_id); - std::string mux_module_name = generate_mux_subckt_name(circuit_lib, mux_model, - find_mux_num_datapath_inputs(circuit_lib, mux_model, mux_graph.num_inputs()), - std::string("")); + std::string mux_module_name = generate_mux_subckt_name( + circuit_lib, mux_model, + find_mux_num_datapath_inputs(circuit_lib, mux_model, + mux_graph.num_inputs()), + std::string("")); /* Find the module name in module manager */ ModuleId mux_module = module_manager.find_module(mux_module_name); VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); - /* Go recursively in the module manager, - * starting from the top-level module: instance id of the top-level module is 0 by default - * Disable all the outputs of child modules that matches the mux_module id + /* Go recursively in the module manager, + * starting from the top-level module: instance id of the top-level module + * is 0 by default Disable all the outputs of child modules that matches the + * mux_module id */ - for (const CircuitPortId& mux_sram_port : find_circuit_regular_sram_ports(circuit_lib, mux_model)) { - const std::string& mux_sram_port_name = circuit_lib.port_lib_name(mux_sram_port); - VTR_ASSERT(true == module_manager.valid_module_port_id(mux_module, module_manager.find_module_port(mux_module, mux_sram_port_name))); - if (CMD_EXEC_FATAL_ERROR == - rec_print_sdc_disable_timing_for_module_ports(fp, - flatten_names, - module_manager, - top_module, - mux_module, - format_dir_path(module_manager.module_name(top_module)), - mux_sram_port_name)) { + for (const CircuitPortId& mux_sram_port : + find_circuit_regular_sram_ports(circuit_lib, mux_model)) { + const std::string& mux_sram_port_name = + circuit_lib.port_lib_name(mux_sram_port); + VTR_ASSERT(true == module_manager.valid_module_port_id( + mux_module, module_manager.find_module_port( + mux_module, mux_sram_port_name))); + if (CMD_EXEC_FATAL_ERROR == + rec_print_sdc_disable_timing_for_module_ports( + fp, flatten_names, module_manager, top_module, mux_module, + format_dir_path(module_manager.module_name(top_module)), + mux_sram_port_name)) { return CMD_EXEC_FATAL_ERROR; } - const std::string& mux_sram_inv_port_name = circuit_lib.port_lib_name(mux_sram_port) + INV_PORT_POSTFIX; - VTR_ASSERT(true == module_manager.valid_module_port_id(mux_module, module_manager.find_module_port(mux_module, mux_sram_inv_port_name))); - if (CMD_EXEC_FATAL_ERROR == - rec_print_sdc_disable_timing_for_module_ports(fp, - flatten_names, - module_manager, - top_module, - mux_module, - format_dir_path(module_manager.module_name(top_module)), - mux_sram_inv_port_name)) { + const std::string& mux_sram_inv_port_name = + circuit_lib.port_lib_name(mux_sram_port) + INV_PORT_POSTFIX; + VTR_ASSERT(true == module_manager.valid_module_port_id( + mux_module, module_manager.find_module_port( + mux_module, mux_sram_inv_port_name))); + if (CMD_EXEC_FATAL_ERROR == + rec_print_sdc_disable_timing_for_module_ports( + fp, flatten_names, module_manager, top_module, mux_module, + format_dir_path(module_manager.module_name(top_module)), + mux_sram_inv_port_name)) { return CMD_EXEC_FATAL_ERROR; } } - } return CMD_EXEC_SUCCESS; diff --git a/openfpga/src/fpga_sdc/sdc_mux_utils.h b/openfpga/src/fpga_sdc/sdc_mux_utils.h index 46c02bd1d..2e901b597 100644 --- a/openfpga/src/fpga_sdc/sdc_mux_utils.h +++ b/openfpga/src/fpga_sdc/sdc_mux_utils.h @@ -6,9 +6,10 @@ *******************************************************************/ #include #include -#include "mux_library.h" + #include "circuit_library.h" #include "module_manager.h" +#include "mux_library.h" /******************************************************************** * Function declaration @@ -17,21 +18,16 @@ /* begin namespace openfpga */ namespace openfpga { -void print_sdc_disable_routing_multiplexer_outputs(const std::string& sdc_dir, - const bool& flatten_names, - const bool& include_time_stamp, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const ModuleManager& module_manager, - const ModuleId& top_module); - -int print_sdc_disable_routing_multiplexer_configure_ports(std::fstream& fp, - const bool& flatten_names, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const ModuleManager& module_manager, - const ModuleId& top_module); +void print_sdc_disable_routing_multiplexer_outputs( + const std::string& sdc_dir, const bool& flatten_names, + const bool& include_time_stamp, const MuxLibrary& mux_lib, + const CircuitLibrary& circuit_lib, const ModuleManager& module_manager, + const ModuleId& top_module); +int print_sdc_disable_routing_multiplexer_configure_ports( + std::fstream& fp, const bool& flatten_names, const MuxLibrary& mux_lib, + const CircuitLibrary& circuit_lib, const ModuleManager& module_manager, + const ModuleId& top_module); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/sdc_writer_naming.h b/openfpga/src/fpga_sdc/sdc_writer_naming.h index 58cfdac8c..fe3247d87 100644 --- a/openfpga/src/fpga_sdc/sdc_writer_naming.h +++ b/openfpga/src/fpga_sdc/sdc_writer_naming.h @@ -7,10 +7,14 @@ namespace openfpga { constexpr const char* SDC_FILE_NAME_POSTFIX = ".sdc"; constexpr const char* SDC_GLOBAL_PORTS_FILE_NAME = "global_ports.sdc"; -constexpr const char* SDC_BENCHMARK_ANALYSIS_FILE_NAME= "fpga_top_analysis.sdc"; -constexpr const char* SDC_DISABLE_CONFIG_MEM_OUTPUTS_FILE_NAME = "disable_configurable_memory_outputs.sdc"; -constexpr const char* SDC_DISABLE_MUX_OUTPUTS_FILE_NAME = "disable_routing_multiplexer_outputs.sdc"; -constexpr const char* SDC_DISABLE_SB_OUTPUTS_FILE_NAME = "disable_sb_outputs.sdc"; +constexpr const char* SDC_BENCHMARK_ANALYSIS_FILE_NAME = + "fpga_top_analysis.sdc"; +constexpr const char* SDC_DISABLE_CONFIG_MEM_OUTPUTS_FILE_NAME = + "disable_configurable_memory_outputs.sdc"; +constexpr const char* SDC_DISABLE_MUX_OUTPUTS_FILE_NAME = + "disable_routing_multiplexer_outputs.sdc"; +constexpr const char* SDC_DISABLE_SB_OUTPUTS_FILE_NAME = + "disable_sb_outputs.sdc"; constexpr const char* SDC_CB_FILE_NAME = "cb.sdc"; constexpr const char* SDC_GRID_HIERARCHY_FILE_NAME = "grid_hierarchy.txt"; diff --git a/openfpga/src/fpga_sdc/sdc_writer_utils.cpp b/openfpga/src/fpga_sdc/sdc_writer_utils.cpp index 8287b6020..d85e7f8de 100644 --- a/openfpga/src/fpga_sdc/sdc_writer_utils.cpp +++ b/openfpga/src/fpga_sdc/sdc_writer_utils.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * This file include most utilized functions to be used in SDC writers + * This file include most utilized functions to be used in SDC writers *******************************************************************/ #include #include @@ -11,22 +11,18 @@ /* Headers from openfpgautil library */ #include "openfpga_digest.h" -#include "openfpga_wildcard_string.h" - #include "openfpga_naming.h" - +#include "openfpga_wildcard_string.h" #include "sdc_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * Write a head (description) in SDC file + * Write a head (description) in SDC file *******************************************************************/ -void print_sdc_file_header(std::fstream& fp, - const std::string& usage, +void print_sdc_file_header(std::fstream& fp, const std::string& usage, const bool& include_time_stamp) { - valid_file_stream(fp); fp << "#############################################" << std::endl; @@ -37,7 +33,7 @@ void print_sdc_file_header(std::fstream& fp, fp << "#\tOrganization: University of Utah " << std::endl; if (include_time_stamp) { - auto end = std::chrono::system_clock::now(); + auto end = std::chrono::system_clock::now(); std::time_t end_time = std::chrono::system_clock::to_time_t(end); fp << "#\tDate: " << std::ctime(&end_time); } @@ -47,11 +43,9 @@ void print_sdc_file_header(std::fstream& fp, } /******************************************************************** - * Write a timescale definition in SDC file + * Write a timescale definition in SDC file *******************************************************************/ -void print_sdc_timescale(std::fstream& fp, - const std::string& timescale) { - +void print_sdc_timescale(std::fstream& fp, const std::string& timescale) { valid_file_stream(fp); fp << "#############################################" << std::endl; @@ -67,12 +61,13 @@ void print_sdc_timescale(std::fstream& fp, std::string generate_sdc_port(const BasicPort& port) { std::string sdc_line; - std::string size_str = "[" + std::to_string(port.get_lsb()) + ":" + std::to_string(port.get_msb()) + "]"; + std::string size_str = "[" + std::to_string(port.get_lsb()) + ":" + + std::to_string(port.get_msb()) + "]"; /* Only connection require a format of [:] - * others require a format of [:] + * others require a format of [:] */ - /* When LSB == MSB, we can use a simplified format + /* When LSB == MSB, we can use a simplified format * If LSB != 0, we need to give explicit pin number * [] * Otherwise, we can keep a compact format @@ -88,7 +83,8 @@ std::string generate_sdc_port(const BasicPort& port) { } /******************************************************************** - * Constrain a path between two ports of a module with a given maximum timing value + * Constrain a path between two ports of a module with a given maximum timing + *value *******************************************************************/ void print_pnr_sdc_constrain_max_delay(std::fstream& fp, const std::string& src_instance_name, @@ -108,7 +104,7 @@ void print_pnr_sdc_constrain_max_delay(std::fstream& fp, fp << src_port_name; fp << " -to "; - + if (!des_instance_name.empty()) { fp << format_dir_path(des_instance_name); } @@ -120,16 +116,14 @@ void print_pnr_sdc_constrain_max_delay(std::fstream& fp, } /******************************************************************** - * Constrain a path between two ports of a module with a given maximum timing value - * This function use regular expression and get_pins which are - * from open-source SDC 2.1 format + * Constrain a path between two ports of a module with a given maximum timing + *value This function use regular expression and get_pins which are from + *open-source SDC 2.1 format *******************************************************************/ -void print_pnr_sdc_regexp_constrain_max_delay(std::fstream& fp, - const std::string& src_instance_name, - const std::string& src_port_name, - const std::string& des_instance_name, - const std::string& des_port_name, - const float& delay) { +void print_pnr_sdc_regexp_constrain_max_delay( + std::fstream& fp, const std::string& src_instance_name, + const std::string& src_port_name, const std::string& des_instance_name, + const std::string& des_port_name, const float& delay) { /* Validate file stream */ valid_file_stream(fp); @@ -146,7 +140,7 @@ void print_pnr_sdc_regexp_constrain_max_delay(std::fstream& fp, fp << " -to "; fp << "[get_pins -regexp \""; - + if (!des_instance_name.empty()) { fp << format_dir_path(des_instance_name); } @@ -160,7 +154,8 @@ void print_pnr_sdc_regexp_constrain_max_delay(std::fstream& fp, } /******************************************************************** - * Constrain a path between two ports of a module with a given minimum timing value + * Constrain a path between two ports of a module with a given minimum timing + *value *******************************************************************/ void print_pnr_sdc_constrain_min_delay(std::fstream& fp, const std::string& src_instance_name, @@ -180,7 +175,7 @@ void print_pnr_sdc_constrain_min_delay(std::fstream& fp, fp << src_port_name; fp << " -to "; - + if (!des_instance_name.empty()) { fp << format_dir_path(des_instance_name); } @@ -195,20 +190,20 @@ void print_pnr_sdc_constrain_min_delay(std::fstream& fp, * Constrain a path between two ports of a module with a given timing value * Note: this function uses set_max_delay !!! *******************************************************************/ -void print_pnr_sdc_constrain_module_port2port_timing(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& input_parent_module_id, - const ModulePortId& module_input_port_id, - const ModuleId& output_parent_module_id, - const ModulePortId& module_output_port_id, - const float& tmax) { - print_pnr_sdc_constrain_max_delay(fp, - module_manager.module_name(input_parent_module_id), - generate_sdc_port(module_manager.module_port(input_parent_module_id, module_input_port_id)), - module_manager.module_name(output_parent_module_id), - generate_sdc_port(module_manager.module_port(output_parent_module_id, module_output_port_id)), - tmax); - +void print_pnr_sdc_constrain_module_port2port_timing( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& input_parent_module_id, + const ModulePortId& module_input_port_id, + const ModuleId& output_parent_module_id, + const ModulePortId& module_output_port_id, const float& tmax) { + print_pnr_sdc_constrain_max_delay( + fp, module_manager.module_name(input_parent_module_id), + generate_sdc_port( + module_manager.module_port(input_parent_module_id, module_input_port_id)), + module_manager.module_name(output_parent_module_id), + generate_sdc_port(module_manager.module_port(output_parent_module_id, + module_output_port_id)), + tmax); } /******************************************************************** @@ -216,27 +211,26 @@ void print_pnr_sdc_constrain_module_port2port_timing(std::fstream& fp, * This function will NOT output the module name * Note: this function uses set_max_delay !!! *******************************************************************/ -void print_pnr_sdc_constrain_port2port_timing(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& input_parent_module_id, - const ModulePortId& module_input_port_id, - const ModuleId& output_parent_module_id, - const ModulePortId& module_output_port_id, - const float& tmax) { - print_pnr_sdc_constrain_max_delay(fp, - std::string(), - generate_sdc_port(module_manager.module_port(input_parent_module_id, module_input_port_id)), - std::string(), - generate_sdc_port(module_manager.module_port(output_parent_module_id, module_output_port_id)), - tmax); - +void print_pnr_sdc_constrain_port2port_timing( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& input_parent_module_id, + const ModulePortId& module_input_port_id, + const ModuleId& output_parent_module_id, + const ModulePortId& module_output_port_id, const float& tmax) { + print_pnr_sdc_constrain_max_delay( + fp, std::string(), + generate_sdc_port( + module_manager.module_port(input_parent_module_id, module_input_port_id)), + std::string(), + generate_sdc_port(module_manager.module_port(output_parent_module_id, + module_output_port_id)), + tmax); } /******************************************************************** - * Disable timing for a port + * Disable timing for a port *******************************************************************/ -void print_sdc_disable_port_timing(std::fstream& fp, - const BasicPort& port) { +void print_sdc_disable_port_timing(std::fstream& fp, const BasicPort& port) { /* Validate file stream */ valid_file_stream(fp); @@ -248,11 +242,10 @@ void print_sdc_disable_port_timing(std::fstream& fp, } /******************************************************************** - * Set the input delay for a port in SDC format + * Set the input delay for a port in SDC format * Note that the input delay will be bounded by a clock port *******************************************************************/ -void print_sdc_set_port_input_delay(std::fstream& fp, - const BasicPort& port, +void print_sdc_set_port_input_delay(std::fstream& fp, const BasicPort& port, const BasicPort& clock_port, const float& delay) { /* Validate file stream */ @@ -265,7 +258,7 @@ void print_sdc_set_port_input_delay(std::fstream& fp, fp << generate_sdc_port(clock_port); fp << " -max "; - + fp << std::setprecision(10) << delay; fp << " "; @@ -276,11 +269,10 @@ void print_sdc_set_port_input_delay(std::fstream& fp, } /******************************************************************** - * Set the output delay for a port in SDC format + * Set the output delay for a port in SDC format * Note that the output delay will be bounded by a clock port *******************************************************************/ -void print_sdc_set_port_output_delay(std::fstream& fp, - const BasicPort& port, +void print_sdc_set_port_output_delay(std::fstream& fp, const BasicPort& port, const BasicPort& clock_port, const float& delay) { /* Validate file stream */ @@ -293,7 +285,7 @@ void print_sdc_set_port_output_delay(std::fstream& fp, fp << generate_sdc_port(clock_port); fp << " -max "; - + fp << std::setprecision(10) << delay; fp << " "; @@ -305,8 +297,8 @@ void print_sdc_set_port_output_delay(std::fstream& fp, /******************************************************************** * Print SDC commands to disable a given port of modules - * in a given module id - * This function will be executed in a recursive way, + * in a given module id + * This function will be executed in a recursive way, * using a Depth-First Search (DFS) strategy * It will iterate over all the configurable children under each module * and print a SDC command to disable its outputs @@ -321,72 +313,73 @@ void print_sdc_set_port_output_delay(std::fstream& fp, * - When flatten_names is false * It will straightforwardly output the instance name and port name * This function will try to apply wildcard to names - * so that SDC file size can be minimal + * so that SDC file size can be minimal *******************************************************************/ -int rec_print_sdc_disable_timing_for_module_ports(std::fstream& fp, - const bool& flatten_names, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const ModuleId& module_to_disable, - const std::string& parent_module_path, - const std::string& disable_port_name) { - +int rec_print_sdc_disable_timing_for_module_ports( + std::fstream& fp, const bool& flatten_names, + const ModuleManager& module_manager, const ModuleId& parent_module, + const ModuleId& module_to_disable, const std::string& parent_module_path, + const std::string& disable_port_name) { if (false == valid_file_stream(fp)) { return 1; } - /* Build wildcard names for the instance names of multiple-instanced-blocks (MIB) - * We will find all the instance names and see there are common prefix + /* Build wildcard names for the instance names of multiple-instanced-blocks + * (MIB) We will find all the instance names and see there are common prefix * If so, we can use wildcards */ std::map> wildcard_names; /* For each child, we will go one level down in priority */ - for (const ModuleId& child_module : module_manager.child_modules(parent_module)) { - + for (const ModuleId& child_module : + module_manager.child_modules(parent_module)) { /* Iterate over the child instances*/ - for (const size_t& child_instance : module_manager.child_module_instances(parent_module, child_module)) { + for (const size_t& child_instance : + module_manager.child_module_instances(parent_module, child_module)) { std::string child_module_path = parent_module_path; std::string child_instance_name; - if (true == module_manager.instance_name(parent_module, child_module, child_instance).empty()) { - child_instance_name = generate_instance_name(module_manager.module_name(child_module), child_instance); + if (true == module_manager + .instance_name(parent_module, child_module, child_instance) + .empty()) { + child_instance_name = generate_instance_name( + module_manager.module_name(child_module), child_instance); } else { - child_instance_name = module_manager.instance_name(parent_module, child_module, child_instance); + child_instance_name = module_manager.instance_name( + parent_module, child_module, child_instance); } - if (false == flatten_names) { - /* Try to adapt to a wildcard name: replace all the numbers with a wildcard character '*' */ - WildCardString wildcard_str(child_instance_name); + if (false == flatten_names) { + /* Try to adapt to a wildcard name: replace all the numbers with a + * wildcard character '*' */ + WildCardString wildcard_str(child_instance_name); /* If the wildcard name is already in the list, we can skip this - * Otherwise, we have to - * - output this instance - * - record the wildcard name in the map + * Otherwise, we have to + * - output this instance + * - record the wildcard name in the map */ - if ( (0 < wildcard_names.count(child_module)) - && (wildcard_names.at(child_module).end() != std::find(wildcard_names.at(child_module).begin(), - wildcard_names.at(child_module).end(), - wildcard_str.data())) ) { + if ((0 < wildcard_names.count(child_module)) && + (wildcard_names.at(child_module).end() != + std::find(wildcard_names.at(child_module).begin(), + wildcard_names.at(child_module).end(), + wildcard_str.data()))) { continue; } child_module_path += wildcard_str.data(); - + wildcard_names[child_module].push_back(wildcard_str.data()); } else { child_module_path += child_instance_name; } - + child_module_path = format_dir_path(child_module_path); /* If this is NOT the MUX module we want, we go recursively */ if (module_to_disable != child_module) { - int status = rec_print_sdc_disable_timing_for_module_ports(fp, flatten_names, - module_manager, - child_module, - module_to_disable, - child_module_path, - disable_port_name); + int status = rec_print_sdc_disable_timing_for_module_ports( + fp, flatten_names, module_manager, child_module, module_to_disable, + child_module_path, disable_port_name); if (1 == status) { return 1; /* FATAL ERRORS */ } @@ -397,12 +390,15 @@ int rec_print_sdc_disable_timing_for_module_ports(std::fstream& fp, valid_file_stream(fp); /* Reach here, this is the MUX module we want, disable the outputs */ - ModulePortId port_to_disable = module_manager.find_module_port(module_to_disable, disable_port_name); + ModulePortId port_to_disable = + module_manager.find_module_port(module_to_disable, disable_port_name); if (ModulePortId::INVALID() == port_to_disable) { return 1; /* FATAL ERRORS */ } fp << "set_disable_timing "; - fp << child_module_path << module_manager.module_port(module_to_disable, port_to_disable).get_name(); + fp << child_module_path + << module_manager.module_port(module_to_disable, port_to_disable) + .get_name(); fp << std::endl; } } diff --git a/openfpga/src/fpga_sdc/sdc_writer_utils.h b/openfpga/src/fpga_sdc/sdc_writer_utils.h index 7bba93639..82b8bfea5 100644 --- a/openfpga/src/fpga_sdc/sdc_writer_utils.h +++ b/openfpga/src/fpga_sdc/sdc_writer_utils.h @@ -6,8 +6,9 @@ *******************************************************************/ #include #include -#include "openfpga_port.h" + #include "module_manager.h" +#include "openfpga_port.h" /******************************************************************** * Function declaration @@ -16,12 +17,10 @@ /* begin namespace openfpga */ namespace openfpga { -void print_sdc_file_header(std::fstream& fp, - const std::string& usage, +void print_sdc_file_header(std::fstream& fp, const std::string& usage, const bool& include_time_stamp); -void print_sdc_timescale(std::fstream& fp, - const std::string& timescale); +void print_sdc_timescale(std::fstream& fp, const std::string& timescale); std::string generate_sdc_port(const BasicPort& port); @@ -32,12 +31,10 @@ void print_pnr_sdc_constrain_max_delay(std::fstream& fp, const std::string& des_port_name, const float& delay); -void print_pnr_sdc_regexp_constrain_max_delay(std::fstream& fp, - const std::string& src_instance_name, - const std::string& src_port_name, - const std::string& des_instance_name, - const std::string& des_port_name, - const float& delay); +void print_pnr_sdc_regexp_constrain_max_delay( + std::fstream& fp, const std::string& src_instance_name, + const std::string& src_port_name, const std::string& des_instance_name, + const std::string& des_port_name, const float& delay); void print_pnr_sdc_constrain_min_delay(std::fstream& fp, const std::string& src_instance_name, @@ -46,42 +43,35 @@ void print_pnr_sdc_constrain_min_delay(std::fstream& fp, const std::string& des_port_name, const float& delay); -void print_pnr_sdc_constrain_module_port2port_timing(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& input_parent_module_id, - const ModulePortId& module_input_port_id, - const ModuleId& output_parent_module_id, - const ModulePortId& module_output_port_id, - const float& tmax); +void print_pnr_sdc_constrain_module_port2port_timing( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& input_parent_module_id, + const ModulePortId& module_input_port_id, + const ModuleId& output_parent_module_id, + const ModulePortId& module_output_port_id, const float& tmax); -void print_pnr_sdc_constrain_port2port_timing(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& input_parent_module_id, - const ModulePortId& module_input_port_id, - const ModuleId& output_parent_module_id, - const ModulePortId& module_output_port_id, - const float& tmax); +void print_pnr_sdc_constrain_port2port_timing( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& input_parent_module_id, + const ModulePortId& module_input_port_id, + const ModuleId& output_parent_module_id, + const ModulePortId& module_output_port_id, const float& tmax); -void print_sdc_disable_port_timing(std::fstream& fp, - const BasicPort& port); +void print_sdc_disable_port_timing(std::fstream& fp, const BasicPort& port); -void print_sdc_set_port_input_delay(std::fstream& fp, - const BasicPort& port, +void print_sdc_set_port_input_delay(std::fstream& fp, const BasicPort& port, const BasicPort& clock_port, const float& delay); -void print_sdc_set_port_output_delay(std::fstream& fp, - const BasicPort& port, +void print_sdc_set_port_output_delay(std::fstream& fp, const BasicPort& port, const BasicPort& clock_port, const float& delay); -int rec_print_sdc_disable_timing_for_module_ports(std::fstream& fp, - const bool& flatten_names, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const ModuleId& module_to_disable, - const std::string& parent_module_path, - const std::string& disable_port_name); +int rec_print_sdc_disable_timing_for_module_ports( + std::fstream& fp, const bool& flatten_names, + const ModuleManager& module_manager, const ModuleId& parent_module, + const ModuleId& module_to_disable, const std::string& parent_module_path, + const std::string& disable_port_name); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_spice/fabric_spice_options.cpp b/openfpga/src/fpga_spice/fabric_spice_options.cpp index a5f561bb9..458399b2d 100644 --- a/openfpga/src/fpga_spice/fabric_spice_options.cpp +++ b/openfpga/src/fpga_spice/fabric_spice_options.cpp @@ -1,10 +1,10 @@ /****************************************************************************** * Memember functions for data structure FabricSpiceOption ******************************************************************************/ -#include "vtr_assert.h" - #include "fabric_spice_options.h" +#include "vtr_assert.h" + /* begin namespace openfpga */ namespace openfpga { @@ -19,7 +19,7 @@ FabricSpiceOption::FabricSpiceOption() { } /************************************************** - * Public Accessors + * Public Accessors *************************************************/ std::string FabricSpiceOption::output_directory() const { return output_directory_; @@ -29,13 +29,9 @@ bool FabricSpiceOption::explicit_port_mapping() const { return explicit_port_mapping_; } -bool FabricSpiceOption::compress_routing() const { - return compress_routing_; -} +bool FabricSpiceOption::compress_routing() const { return compress_routing_; } -bool FabricSpiceOption::verbose_output() const { - return verbose_output_; -} +bool FabricSpiceOption::verbose_output() const { return verbose_output_; } /****************************************************************************** * Private Mutators diff --git a/openfpga/src/fpga_spice/fabric_spice_options.h b/openfpga/src/fpga_spice/fabric_spice_options.h index 359146fd8..88370a563 100644 --- a/openfpga/src/fpga_spice/fabric_spice_options.h +++ b/openfpga/src/fpga_spice/fabric_spice_options.h @@ -13,24 +13,27 @@ namespace openfpga { * Options for Fabric Spice generator *******************************************************************/ class FabricSpiceOption { - public: /* Public constructor */ - /* Set default options */ - FabricSpiceOption(); - public: /* Public accessors */ - std::string output_directory() const; - bool explicit_port_mapping() const; - bool compress_routing() const; - bool verbose_output() const; - public: /* Public mutators */ - void set_output_directory(const std::string& output_dir); - void set_explicit_port_mapping(const bool& enabled); - void set_compress_routing(const bool& enabled); - void set_verbose_output(const bool& enabled); - private: /* Internal Data */ - std::string output_directory_; - bool explicit_port_mapping_; - bool compress_routing_; - bool verbose_output_; + public: /* Public constructor */ + /* Set default options */ + FabricSpiceOption(); + + public: /* Public accessors */ + std::string output_directory() const; + bool explicit_port_mapping() const; + bool compress_routing() const; + bool verbose_output() const; + + public: /* Public mutators */ + void set_output_directory(const std::string& output_dir); + void set_explicit_port_mapping(const bool& enabled); + void set_compress_routing(const bool& enabled); + void set_verbose_output(const bool& enabled); + + private: /* Internal Data */ + std::string output_directory_; + bool explicit_port_mapping_; + bool compress_routing_; + bool verbose_output_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/fpga_spice/spice_api.cpp b/openfpga/src/fpga_spice/spice_api.cpp index 22c433bd6..99c346cbf 100644 --- a/openfpga/src/fpga_spice/spice_api.cpp +++ b/openfpga/src/fpga_spice/spice_api.cpp @@ -3,8 +3,8 @@ ********************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgashell library */ @@ -13,13 +13,12 @@ /* Headers from openfpgautil library */ #include "openfpga_digest.h" #include "openfpga_reserved_words.h" - -#include "spice_constants.h" -#include "spice_submodule.h" -#include "spice_routing.h" -#include "spice_grid.h" -#include "spice_top_module.h" #include "spice_auxiliary_netlists.h" +#include "spice_constants.h" +#include "spice_grid.h" +#include "spice_routing.h" +#include "spice_submodule.h" +#include "spice_top_module.h" /* Header file for this source file */ #include "spice_api.h" @@ -39,17 +38,16 @@ namespace openfpga { * Note: * - Please do NOT include ANY testbench generation in this function!!! * It is about the fabric itself, independent from any implementation - * All the testbench generation should be in the function fpga_testbench_spice() + * All the testbench generation should be in the function + *fpga_testbench_spice() ********************************************************************/ int fpga_fabric_spice(const ModuleManager& module_manager, NetlistManager& netlist_manager, - const Arch& openfpga_arch, - const MuxLibrary& mux_lib, - const DeviceContext &device_ctx, - const VprDeviceAnnotation &device_annotation, - const DeviceRRGSB &device_rr_gsb, + const Arch& openfpga_arch, const MuxLibrary& mux_lib, + const DeviceContext& device_ctx, + const VprDeviceAnnotation& device_annotation, + const DeviceRRGSB& device_rr_gsb, const FabricSpiceOption& options) { - vtr::ScopedStartFinishTimer timer("Write SPICE netlists for FPGA fabric\n"); std::string src_dir_path = format_dir_path(options.output_directory()); @@ -57,15 +55,19 @@ int fpga_fabric_spice(const ModuleManager& module_manager, /* Create directories */ create_directory(src_dir_path); - /* Sub directory under SRC directory to contain all the primitive block netlists */ - std::string submodule_dir_path = src_dir_path + std::string(DEFAULT_SUBMODULE_DIR_NAME); + /* Sub directory under SRC directory to contain all the primitive block + * netlists */ + std::string submodule_dir_path = + src_dir_path + std::string(DEFAULT_SUBMODULE_DIR_NAME); create_directory(submodule_dir_path); - /* Sub directory under SRC directory to contain all the logic block netlists */ + /* Sub directory under SRC directory to contain all the logic block netlists + */ std::string lb_dir_path = src_dir_path + std::string(DEFAULT_LB_DIR_NAME); create_directory(lb_dir_path); - /* Sub directory under SRC directory to contain all the routing block netlists */ + /* Sub directory under SRC directory to contain all the routing block netlists + */ std::string rr_dir_path = src_dir_path + std::string(DEFAULT_RR_DIR_NAME); create_directory(rr_dir_path); @@ -74,54 +76,42 @@ int fpga_fabric_spice(const ModuleManager& module_manager, * core logic (i.e., logic blocks and routing resources) !!! * This is because that this function will add the primitive Spice modules to * the module manager. - * Without the modules in the module manager, core logic generation is not possible!!! + * Without the modules in the module manager, core logic generation is not + * possible!!! */ int status = CMD_EXEC_SUCCESS; - status = print_spice_submodule(netlist_manager, - module_manager, - openfpga_arch, - mux_lib, - submodule_dir_path); - + status = print_spice_submodule(netlist_manager, module_manager, openfpga_arch, + mux_lib, submodule_dir_path); + if (CMD_EXEC_SUCCESS != status) { return status; } /* Generate routing blocks */ if (true == options.compress_routing()) { - print_spice_unique_routing_modules(netlist_manager, - module_manager, - device_rr_gsb, - rr_dir_path); + print_spice_unique_routing_modules(netlist_manager, module_manager, + device_rr_gsb, rr_dir_path); } else { VTR_ASSERT(false == options.compress_routing()); - print_spice_flatten_routing_modules(netlist_manager, - module_manager, - device_rr_gsb, - rr_dir_path); + print_spice_flatten_routing_modules(netlist_manager, module_manager, + device_rr_gsb, rr_dir_path); } /* Generate grids */ - print_spice_grids(netlist_manager, - module_manager, - device_ctx, device_annotation, - lb_dir_path, - options.verbose_output()); + print_spice_grids(netlist_manager, module_manager, device_ctx, + device_annotation, lb_dir_path, options.verbose_output()); /* Generate FPGA fabric */ - print_spice_top_module(netlist_manager, - module_manager, - src_dir_path); + print_spice_top_module(netlist_manager, module_manager, src_dir_path); /* Generate an netlist including all the fabric-related netlists */ - print_spice_fabric_include_netlist(const_cast(netlist_manager), - src_dir_path, - openfpga_arch.circuit_lib); + print_spice_fabric_include_netlist( + const_cast(netlist_manager), src_dir_path, + openfpga_arch.circuit_lib); /* Given a brief stats on how many Spice modules have been written to files */ - VTR_LOGV(options.verbose_output(), - "Written %lu SPICE modules in total\n", + VTR_LOGV(options.verbose_output(), "Written %lu SPICE modules in total\n", module_manager.num_modules()); return CMD_EXEC_SUCCESS; diff --git a/openfpga/src/fpga_spice/spice_api.h b/openfpga/src/fpga_spice/spice_api.h index 0e08aa440..81100c266 100644 --- a/openfpga/src/fpga_spice/spice_api.h +++ b/openfpga/src/fpga_spice/spice_api.h @@ -1,5 +1,5 @@ -#ifndef SPICE_API_H -#define SPICE_API_H +#ifndef SPICE_API_H +#define SPICE_API_H /******************************************************************** * Include header files that are required by function declaration @@ -7,14 +7,15 @@ #include #include -#include "netlist_manager.h" -#include "module_manager.h" -#include "openfpga_arch.h" -#include "mux_library.h" -#include "vpr_context.h" -#include "vpr_device_annotation.h" + #include "device_rr_gsb.h" #include "fabric_spice_options.h" +#include "module_manager.h" +#include "mux_library.h" +#include "netlist_manager.h" +#include "openfpga_arch.h" +#include "vpr_context.h" +#include "vpr_device_annotation.h" /******************************************************************** * Function declaration @@ -25,11 +26,10 @@ namespace openfpga { int fpga_fabric_spice(const ModuleManager& module_manager, NetlistManager& netlist_manager, - const Arch& openfpga_arch, - const MuxLibrary& mux_lib, - const DeviceContext &device_ctx, - const VprDeviceAnnotation &device_annotation, - const DeviceRRGSB &device_rr_gsb, + const Arch& openfpga_arch, const MuxLibrary& mux_lib, + const DeviceContext& device_ctx, + const VprDeviceAnnotation& device_annotation, + const DeviceRRGSB& device_rr_gsb, const FabricSpiceOption& options); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_spice/spice_auxiliary_netlists.cpp b/openfpga/src/fpga_spice/spice_auxiliary_netlists.cpp index f76464898..91a10b68e 100644 --- a/openfpga/src/fpga_spice/spice_auxiliary_netlists.cpp +++ b/openfpga/src/fpga_spice/spice_auxiliary_netlists.cpp @@ -1,6 +1,6 @@ /******************************************************************** * This file includes functions that are used to generate SPICE files - * or code blocks, with a focus on + * or code blocks, with a focus on * `include user-defined or auto-generated netlists in SPICE format *******************************************************************/ #include @@ -9,13 +9,12 @@ #include "vtr_assert.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - -#include "openfpga_naming.h" #include "circuit_library_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "spice_auxiliary_netlists.h" #include "spice_constants.h" #include "spice_writer_utils.h" -#include "spice_auxiliary_netlists.h" /* begin namespace openfpga */ namespace openfpga { @@ -25,7 +24,7 @@ namespace openfpga { *******************************************************************/ /******************************************************************** - * Print a file that includes all the fabric netlists + * Print a file that includes all the fabric netlists * that have been generated and user-defined. * This does NOT include any testbenches! * Some netlists are open to compile under specific preprocessing flags @@ -33,7 +32,8 @@ namespace openfpga { void print_spice_fabric_include_netlist(const NetlistManager& netlist_manager, const std::string& src_dir, const CircuitLibrary& circuit_lib) { - std::string spice_fname = src_dir + std::string(FABRIC_INCLUDE_SPICE_NETLIST_FILE_NAME); + std::string spice_fname = + src_dir + std::string(FABRIC_INCLUDE_SPICE_NETLIST_FILE_NAME); /* Create the file stream */ std::fstream fp; @@ -43,38 +43,43 @@ void print_spice_fabric_include_netlist(const NetlistManager& netlist_manager, check_file_stream(spice_fname.c_str(), fp); /* Print the title */ - print_spice_file_header(fp, std::string("Fabric Netlist Summary")); + print_spice_file_header(fp, std::string("Fabric Netlist Summary")); /* Include all the user-defined netlists */ print_spice_comment(fp, std::string("Include user-defined netlists")); - for (const std::string& user_defined_netlist : find_circuit_library_unique_spice_netlists(circuit_lib)) { + for (const std::string& user_defined_netlist : + find_circuit_library_unique_spice_netlists(circuit_lib)) { print_spice_include_netlist(fp, user_defined_netlist); } /* Include all the primitive modules */ print_spice_comment(fp, std::string("Include primitive module netlists")); - for (const NetlistId& nlist_id : netlist_manager.netlists_by_type(NetlistManager::SUBMODULE_NETLIST)) { + for (const NetlistId& nlist_id : + netlist_manager.netlists_by_type(NetlistManager::SUBMODULE_NETLIST)) { print_spice_include_netlist(fp, netlist_manager.netlist_name(nlist_id)); } fp << std::endl; /* Include all the CLB, heterogeneous block modules */ print_spice_comment(fp, std::string("Include logic block netlists")); - for (const NetlistId& nlist_id : netlist_manager.netlists_by_type(NetlistManager::LOGIC_BLOCK_NETLIST)) { + for (const NetlistId& nlist_id : + netlist_manager.netlists_by_type(NetlistManager::LOGIC_BLOCK_NETLIST)) { print_spice_include_netlist(fp, netlist_manager.netlist_name(nlist_id)); } fp << std::endl; /* Include all the routing architecture modules */ print_spice_comment(fp, std::string("Include routing module netlists")); - for (const NetlistId& nlist_id : netlist_manager.netlists_by_type(NetlistManager::ROUTING_MODULE_NETLIST)) { + for (const NetlistId& nlist_id : netlist_manager.netlists_by_type( + NetlistManager::ROUTING_MODULE_NETLIST)) { print_spice_include_netlist(fp, netlist_manager.netlist_name(nlist_id)); } fp << std::endl; /* Include FPGA top module */ print_spice_comment(fp, std::string("Include fabric top-level netlists")); - for (const NetlistId& nlist_id : netlist_manager.netlists_by_type(NetlistManager::TOP_MODULE_NETLIST)) { + for (const NetlistId& nlist_id : + netlist_manager.netlists_by_type(NetlistManager::TOP_MODULE_NETLIST)) { print_spice_include_netlist(fp, netlist_manager.netlist_name(nlist_id)); } fp << std::endl; diff --git a/openfpga/src/fpga_spice/spice_auxiliary_netlists.h b/openfpga/src/fpga_spice/spice_auxiliary_netlists.h index aa04a54b9..4234d9f80 100644 --- a/openfpga/src/fpga_spice/spice_auxiliary_netlists.h +++ b/openfpga/src/fpga_spice/spice_auxiliary_netlists.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "circuit_library.h" #include "netlist_manager.h" @@ -21,4 +22,4 @@ void print_spice_fabric_include_netlist(const NetlistManager& netlist_manager, } /* end namespace openfpga */ -#endif +#endif diff --git a/openfpga/src/fpga_spice/spice_buffer.cpp b/openfpga/src/fpga_spice/spice_buffer.cpp index 824e3debc..3e1b60294 100644 --- a/openfpga/src/fpga_spice/spice_buffer.cpp +++ b/openfpga/src/fpga_spice/spice_buffer.cpp @@ -1,9 +1,9 @@ /************************************************ - * This file includes functions on - * outputting SPICE netlists for inverters and buffers + * This file includes functions on + * outputting SPICE netlists for inverters and buffers ***********************************************/ -#include #include +#include #include /* Headers from vtrutil library */ @@ -14,13 +14,11 @@ #include "command_exit_codes.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - #include "circuit_library_utils.h" - +#include "openfpga_digest.h" +#include "spice_buffer.h" #include "spice_constants.h" #include "spice_writer_utils.h" -#include "spice_buffer.h" /* begin namespace openfpga */ namespace openfpga { @@ -28,52 +26,52 @@ namespace openfpga { /******************************************************************** * Generate the SPICE modeling for a power-gated inverter * - * This function is created to be shared by inverter and buffer SPICE netlist writer + * This function is created to be shared by inverter and buffer SPICE netlist + *writer * - * Note: + * Note: * - This function does NOT create a file * but requires a file stream created - * - This function only output SPICE modeling for + * - This function only output SPICE modeling for * an inverter. Any preprocessing or subckt definition should not be included! *******************************************************************/ -static -int print_spice_powergated_inverter_pmos_modeling(std::fstream& fp, - const std::string& trans_name_postfix, - const std::string& input_port_name, - const std::string& output_port_name, - const CircuitLibrary& circuit_lib, - const CircuitPortId& enb_port, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& tech_model, - const float& trans_width) { - +static int print_spice_powergated_inverter_pmos_modeling( + std::fstream& fp, const std::string& trans_name_postfix, + const std::string& input_port_name, const std::string& output_port_name, + const CircuitLibrary& circuit_lib, const CircuitPortId& enb_port, + const TechnologyLibrary& tech_lib, const TechnologyModelId& tech_model, + const float& trans_width) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } /* Write power-gating transistor pairs using the technology model - * Note that for a mulit-bit power gating port, we should cascade the transistors + * Note that for a mulit-bit power gating port, we should cascade the + * transistors */ bool first_enb_pin = true; size_t last_enb_pin; for (const auto& power_gate_pin : circuit_lib.pins(enb_port)) { - BasicPort enb_pin(circuit_lib.port_prefix(enb_port), power_gate_pin, power_gate_pin); - fp << "Xpmos_powergate_" << trans_name_postfix << "_pin_" << power_gate_pin << " "; + BasicPort enb_pin(circuit_lib.port_prefix(enb_port), power_gate_pin, + power_gate_pin); + fp << "Xpmos_powergate_" << trans_name_postfix << "_pin_" << power_gate_pin + << " "; /* For the first pin, we should connect it to local VDD*/ if (true == first_enb_pin) { - fp << output_port_name << "_pmos_pg_" << power_gate_pin << " "; - fp << generate_spice_port(enb_pin) << " "; - fp << SPICE_SUBCKT_VDD_PORT_NAME << " "; - fp << SPICE_SUBCKT_VDD_PORT_NAME << " "; + fp << output_port_name << "_pmos_pg_" << power_gate_pin << " "; + fp << generate_spice_port(enb_pin) << " "; + fp << SPICE_SUBCKT_VDD_PORT_NAME << " "; + fp << SPICE_SUBCKT_VDD_PORT_NAME << " "; first_enb_pin = false; } else { VTR_ASSERT_SAFE(false == first_enb_pin); - fp << output_port_name << "_pmos_pg_" << last_enb_pin << " "; - fp << generate_spice_port(enb_pin) << " "; - fp << output_port_name << "_pmos_pg_" << power_gate_pin << " "; - fp << SPICE_SUBCKT_VDD_PORT_NAME << " "; + fp << output_port_name << "_pmos_pg_" << last_enb_pin << " "; + fp << generate_spice_port(enb_pin) << " "; + fp << output_port_name << "_pmos_pg_" << power_gate_pin << " "; + fp << SPICE_SUBCKT_VDD_PORT_NAME << " "; } - fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX; + fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) + << TRANSISTOR_WRAPPER_POSTFIX; fp << " W=" << std::setprecision(10) << trans_width; fp << "\n"; @@ -83,11 +81,13 @@ int print_spice_powergated_inverter_pmos_modeling(std::fstream& fp, /* Write transistor pairs using the technology model */ fp << "Xpmos_" << trans_name_postfix << " "; - fp << output_port_name << " "; - fp << input_port_name << " "; - fp << output_port_name << "_pmos_pg_" << circuit_lib.pins(enb_port).back() << " "; - fp << SPICE_SUBCKT_VDD_PORT_NAME << " "; - fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX; + fp << output_port_name << " "; + fp << input_port_name << " "; + fp << output_port_name << "_pmos_pg_" << circuit_lib.pins(enb_port).back() + << " "; + fp << SPICE_SUBCKT_VDD_PORT_NAME << " "; + fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) + << TRANSISTOR_WRAPPER_POSTFIX; fp << " W=" << std::setprecision(10) << trans_width; fp << "\n"; @@ -97,25 +97,21 @@ int print_spice_powergated_inverter_pmos_modeling(std::fstream& fp, /******************************************************************** * Generate the SPICE modeling for the NMOS part of a power-gated inverter * - * This function is created to be shared by inverter and buffer SPICE netlist writer + * This function is created to be shared by inverter and buffer SPICE netlist + *writer * - * Note: + * Note: * - This function does NOT create a file * but requires a file stream created - * - This function only output SPICE modeling for + * - This function only output SPICE modeling for * an inverter. Any preprocessing or subckt definition should not be included! *******************************************************************/ -static -int print_spice_powergated_inverter_nmos_modeling(std::fstream& fp, - const std::string& trans_name_postfix, - const std::string& input_port_name, - const std::string& output_port_name, - const CircuitLibrary& circuit_lib, - const CircuitPortId& en_port, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& tech_model, - const float& trans_width) { - +static int print_spice_powergated_inverter_nmos_modeling( + std::fstream& fp, const std::string& trans_name_postfix, + const std::string& input_port_name, const std::string& output_port_name, + const CircuitLibrary& circuit_lib, const CircuitPortId& en_port, + const TechnologyLibrary& tech_lib, const TechnologyModelId& tech_model, + const float& trans_width) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } @@ -123,23 +119,26 @@ int print_spice_powergated_inverter_nmos_modeling(std::fstream& fp, bool first_en_pin = true; size_t last_en_pin; for (const auto& power_gate_pin : circuit_lib.pins(en_port)) { - BasicPort en_pin(circuit_lib.port_prefix(en_port), power_gate_pin, power_gate_pin); - fp << "Xnmos_powergate_" << trans_name_postfix << "_pin_" << power_gate_pin << " "; + BasicPort en_pin(circuit_lib.port_prefix(en_port), power_gate_pin, + power_gate_pin); + fp << "Xnmos_powergate_" << trans_name_postfix << "_pin_" << power_gate_pin + << " "; /* For the first pin, we should connect it to local VDD*/ if (true == first_en_pin) { - fp << output_port_name << "_nmos_pg_" << power_gate_pin << " "; - fp << generate_spice_port(en_pin) << " "; - fp << SPICE_SUBCKT_GND_PORT_NAME << " "; - fp << SPICE_SUBCKT_GND_PORT_NAME << " "; + fp << output_port_name << "_nmos_pg_" << power_gate_pin << " "; + fp << generate_spice_port(en_pin) << " "; + fp << SPICE_SUBCKT_GND_PORT_NAME << " "; + fp << SPICE_SUBCKT_GND_PORT_NAME << " "; first_en_pin = false; } else { VTR_ASSERT_SAFE(false == first_en_pin); - fp << output_port_name << "_nmos_pg_" << last_en_pin << " "; - fp << circuit_lib.port_prefix(en_port) << " "; - fp << output_port_name << "_nmos_pg_" << power_gate_pin << " "; - fp << SPICE_SUBCKT_GND_PORT_NAME << " "; + fp << output_port_name << "_nmos_pg_" << last_en_pin << " "; + fp << circuit_lib.port_prefix(en_port) << " "; + fp << output_port_name << "_nmos_pg_" << power_gate_pin << " "; + fp << SPICE_SUBCKT_GND_PORT_NAME << " "; } - fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX; + fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) + << TRANSISTOR_WRAPPER_POSTFIX; fp << " W=" << std::setprecision(10) << trans_width; fp << "\n"; @@ -148,11 +147,13 @@ int print_spice_powergated_inverter_nmos_modeling(std::fstream& fp, } fp << "Xnmos_" << trans_name_postfix << " "; - fp << output_port_name << " "; - fp << input_port_name << " "; - fp << output_port_name << " _nmos_pg_" << circuit_lib.pins(en_port).back() << " "; - fp << SPICE_SUBCKT_GND_PORT_NAME << " "; - fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX; + fp << output_port_name << " "; + fp << input_port_name << " "; + fp << output_port_name << " _nmos_pg_" << circuit_lib.pins(en_port).back() + << " "; + fp << SPICE_SUBCKT_GND_PORT_NAME << " "; + fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) + << TRANSISTOR_WRAPPER_POSTFIX; fp << " W=" << std::setprecision(10) << trans_width; fp << "\n"; @@ -163,8 +164,8 @@ int print_spice_powergated_inverter_nmos_modeling(std::fstream& fp, * Generate the SPICE subckt for a power gated inverter * The Enable signal controlled the power gating * - * Note: - * - This function supports multi-bit power gating + * Note: + * - This function supports multi-bit power gating * * Schematic * LVDD @@ -205,39 +206,43 @@ int print_spice_powergated_inverter_nmos_modeling(std::fstream& fp, * LGND * *******************************************************************/ -static -int print_spice_powergated_inverter_subckt(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& tech_model) { +static int print_spice_powergated_inverter_subckt( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, const TechnologyLibrary& tech_lib, + const TechnologyModelId& tech_model) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } /* Print the inverter subckt definition */ - print_spice_subckt_definition(fp, module_manager, module_id); + print_spice_subckt_definition(fp, module_manager, module_id); /* Find the input and output ports: - * we do NOT support global ports here, + * we do NOT support global ports here, * it should be handled in another type of inverter subckt (power-gated) */ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); /* Make sure: - * There is only 1 input port and 1 output port, + * There is only 1 input port and 1 output port, * each size of which is 1 */ - VTR_ASSERT( (1 == input_ports.size()) && (1 == circuit_lib.port_size(input_ports[0])) ); - VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + VTR_ASSERT((1 == input_ports.size()) && + (1 == circuit_lib.port_size(input_ports[0]))); + VTR_ASSERT((1 == output_ports.size()) && + (1 == circuit_lib.port_size(output_ports[0]))); - /* If the circuit model is power-gated, we need to find at least one global config_enable signals */ + /* If the circuit model is power-gated, we need to find at least one global + * config_enable signals */ VTR_ASSERT(true == circuit_lib.is_power_gated(circuit_model)); - CircuitPortId en_port = find_circuit_model_power_gate_en_port(circuit_lib, circuit_model); - CircuitPortId enb_port = find_circuit_model_power_gate_enb_port(circuit_lib, circuit_model); + CircuitPortId en_port = + find_circuit_model_power_gate_en_port(circuit_lib, circuit_model); + CircuitPortId enb_port = + find_circuit_model_power_gate_enb_port(circuit_lib, circuit_model); VTR_ASSERT(true == circuit_lib.valid_circuit_port_id(en_port)); VTR_ASSERT(true == circuit_lib.valid_circuit_port_id(enb_port)); @@ -245,30 +250,27 @@ int print_spice_powergated_inverter_subckt(std::fstream& fp, /* Consider use size/bin to compact layout: * Try to size transistors to the max width for each bin - * The last bin may not reach the max width + * The last bin may not reach the max width */ - float regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); - float total_pmos_width = circuit_lib.buffer_size(circuit_model) - * tech_lib.model_pn_ratio(tech_model) - * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float regular_pmos_bin_width = + tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float total_pmos_width = + circuit_lib.buffer_size(circuit_model) * + tech_lib.model_pn_ratio(tech_model) * + tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); int num_pmos_bins = std::ceil(total_pmos_width / regular_pmos_bin_width); - float last_pmos_bin_width = std::fmod(total_pmos_width, regular_pmos_bin_width); - for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { + float last_pmos_bin_width = + std::fmod(total_pmos_width, regular_pmos_bin_width); + for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { float curr_bin_width = regular_pmos_bin_width; /* For last bin, we need an irregular width */ - if ((ibin == num_pmos_bins - 1) - && (0. != last_pmos_bin_width)) { + if ((ibin == num_pmos_bins - 1) && (0. != last_pmos_bin_width)) { curr_bin_width = last_pmos_bin_width; } - status = print_spice_powergated_inverter_pmos_modeling(fp, - std::to_string(ibin), - circuit_lib.port_prefix(input_ports[0]), - circuit_lib.port_prefix(output_ports[0]), - circuit_lib, - enb_port, - tech_lib, - tech_model, - curr_bin_width); + status = print_spice_powergated_inverter_pmos_modeling( + fp, std::to_string(ibin), circuit_lib.port_prefix(input_ports[0]), + circuit_lib.port_prefix(output_ports[0]), circuit_lib, enb_port, tech_lib, + tech_model, curr_bin_width); if (CMD_EXEC_FATAL_ERROR == status) { return status; } @@ -276,36 +278,33 @@ int print_spice_powergated_inverter_subckt(std::fstream& fp, /* Consider use size/bin to compact layout: * Try to size transistors to the max width for each bin - * The last bin may not reach the max width + * The last bin may not reach the max width */ - float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); - float total_nmos_width = circuit_lib.buffer_size(circuit_model) - * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float regular_nmos_bin_width = + tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float total_nmos_width = + circuit_lib.buffer_size(circuit_model) * + tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width); - float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width); - for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { + float last_nmos_bin_width = + std::fmod(total_nmos_width, regular_nmos_bin_width); + for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { float curr_bin_width = regular_nmos_bin_width; /* For last bin, we need an irregular width */ - if ((ibin == num_nmos_bins - 1) - && (0. != last_nmos_bin_width)) { + if ((ibin == num_nmos_bins - 1) && (0. != last_nmos_bin_width)) { curr_bin_width = last_nmos_bin_width; } - status = print_spice_powergated_inverter_nmos_modeling(fp, - std::to_string(ibin), - circuit_lib.port_prefix(input_ports[0]), - circuit_lib.port_prefix(output_ports[0]), - circuit_lib, - en_port, - tech_lib, - tech_model, - curr_bin_width); + status = print_spice_powergated_inverter_nmos_modeling( + fp, std::to_string(ibin), circuit_lib.port_prefix(input_ports[0]), + circuit_lib.port_prefix(output_ports[0]), circuit_lib, en_port, tech_lib, + tech_model, curr_bin_width); if (CMD_EXEC_FATAL_ERROR == status) { return status; } } - print_spice_subckt_end(fp, module_manager.module_name(module_id)); + print_spice_subckt_end(fp, module_manager.module_name(module_id)); return CMD_EXEC_SUCCESS; } @@ -313,34 +312,32 @@ int print_spice_powergated_inverter_subckt(std::fstream& fp, /******************************************************************** * Generate the SPICE modeling for the PMOS part of a regular inverter * - * This function is created to be shared by inverter and buffer SPICE netlist writer + * This function is created to be shared by inverter and buffer SPICE netlist + *writer * - * Note: + * Note: * - This function does NOT create a file * but requires a file stream created - * - This function only output SPICE modeling for + * - This function only output SPICE modeling for * an inverter. Any preprocessing or subckt definition should not be included! *******************************************************************/ -static -int print_spice_regular_inverter_pmos_modeling(std::fstream& fp, - const std::string& trans_name_postfix, - const std::string& input_port_name, - const std::string& output_port_name, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& tech_model, - const float& trans_width) { - +static int print_spice_regular_inverter_pmos_modeling( + std::fstream& fp, const std::string& trans_name_postfix, + const std::string& input_port_name, const std::string& output_port_name, + const TechnologyLibrary& tech_lib, const TechnologyModelId& tech_model, + const float& trans_width) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } /* Write transistor pairs using the technology model */ fp << "Xpmos_" << trans_name_postfix << " "; - fp << output_port_name << " "; - fp << input_port_name << " "; - fp << SPICE_SUBCKT_VDD_PORT_NAME << " "; - fp << SPICE_SUBCKT_VDD_PORT_NAME << " "; - fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX; + fp << output_port_name << " "; + fp << input_port_name << " "; + fp << SPICE_SUBCKT_VDD_PORT_NAME << " "; + fp << SPICE_SUBCKT_VDD_PORT_NAME << " "; + fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) + << TRANSISTOR_WRAPPER_POSTFIX; fp << " W=" << std::setprecision(10) << trans_width; fp << "\n"; @@ -350,33 +347,31 @@ int print_spice_regular_inverter_pmos_modeling(std::fstream& fp, /******************************************************************** * Generate the SPICE modeling for the NMOS part of a regular inverter * - * This function is created to be shared by inverter and buffer SPICE netlist writer + * This function is created to be shared by inverter and buffer SPICE netlist + *writer * - * Note: + * Note: * - This function does NOT create a file * but requires a file stream created - * - This function only output SPICE modeling for + * - This function only output SPICE modeling for * an inverter. Any preprocessing or subckt definition should not be included! *******************************************************************/ -static -int print_spice_regular_inverter_nmos_modeling(std::fstream& fp, - const std::string& trans_name_postfix, - const std::string& input_port_name, - const std::string& output_port_name, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& tech_model, - const float& trans_width) { - +static int print_spice_regular_inverter_nmos_modeling( + std::fstream& fp, const std::string& trans_name_postfix, + const std::string& input_port_name, const std::string& output_port_name, + const TechnologyLibrary& tech_lib, const TechnologyModelId& tech_model, + const float& trans_width) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } fp << "Xnmos_" << trans_name_postfix << " "; - fp << output_port_name << " "; - fp << input_port_name << " "; - fp << SPICE_SUBCKT_GND_PORT_NAME << " "; - fp << SPICE_SUBCKT_GND_PORT_NAME << " "; - fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX; + fp << output_port_name << " "; + fp << input_port_name << " "; + fp << SPICE_SUBCKT_GND_PORT_NAME << " "; + fp << SPICE_SUBCKT_GND_PORT_NAME << " "; + fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) + << TRANSISTOR_WRAPPER_POSTFIX; fp << " W=" << std::setprecision(10) << trans_width; fp << "\n"; @@ -386,7 +381,7 @@ int print_spice_regular_inverter_nmos_modeling(std::fstream& fp, /******************************************************************** * Generate the SPICE subckt for a regular inverter * - * Note: + * Note: * - This function does NOT support power-gating * It should be managed in a separated function * @@ -406,62 +401,62 @@ int print_spice_regular_inverter_nmos_modeling(std::fstream& fp, * LGND * *******************************************************************/ -static -int print_spice_regular_inverter_subckt(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& tech_model) { +static int print_spice_regular_inverter_subckt( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, const TechnologyLibrary& tech_lib, + const TechnologyModelId& tech_model) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } /* Print the inverter subckt definition */ - print_spice_subckt_definition(fp, module_manager, module_id); + print_spice_subckt_definition(fp, module_manager, module_id); /* Find the input and output ports: - * we do NOT support global ports here, + * we do NOT support global ports here, * it should be handled in another type of inverter subckt (power-gated) */ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); /* Make sure: - * There is only 1 input port and 1 output port, + * There is only 1 input port and 1 output port, * each size of which is 1 */ - VTR_ASSERT( (1 == input_ports.size()) && (1 == circuit_lib.port_size(input_ports[0])) ); - VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + VTR_ASSERT((1 == input_ports.size()) && + (1 == circuit_lib.port_size(input_ports[0]))); + VTR_ASSERT((1 == output_ports.size()) && + (1 == circuit_lib.port_size(output_ports[0]))); int status = CMD_EXEC_SUCCESS; /* Consider use size/bin to compact layout: * Try to size transistors to the max width for each bin - * The last bin may not reach the max width + * The last bin may not reach the max width */ - float regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); - float total_pmos_width = circuit_lib.buffer_size(circuit_model) - * tech_lib.model_pn_ratio(tech_model) - * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float regular_pmos_bin_width = + tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float total_pmos_width = + circuit_lib.buffer_size(circuit_model) * + tech_lib.model_pn_ratio(tech_model) * + tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); int num_pmos_bins = std::ceil(total_pmos_width / regular_pmos_bin_width); - float last_pmos_bin_width = std::fmod(total_pmos_width, regular_pmos_bin_width); - for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { + float last_pmos_bin_width = + std::fmod(total_pmos_width, regular_pmos_bin_width); + for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { float curr_bin_width = regular_pmos_bin_width; /* For last bin, we need an irregular width */ - if ((ibin == num_pmos_bins - 1) - && (0. != last_pmos_bin_width)) { + if ((ibin == num_pmos_bins - 1) && (0. != last_pmos_bin_width)) { curr_bin_width = last_pmos_bin_width; } - status = print_spice_regular_inverter_pmos_modeling(fp, - std::to_string(ibin), - circuit_lib.port_prefix(input_ports[0]), - circuit_lib.port_prefix(output_ports[0]), - tech_lib, - tech_model, - curr_bin_width); + status = print_spice_regular_inverter_pmos_modeling( + fp, std::to_string(ibin), circuit_lib.port_prefix(input_ports[0]), + circuit_lib.port_prefix(output_ports[0]), tech_lib, tech_model, + curr_bin_width); if (CMD_EXEC_FATAL_ERROR == status) { return status; } @@ -469,35 +464,34 @@ int print_spice_regular_inverter_subckt(std::fstream& fp, /* Consider use size/bin to compact layout: * Try to size transistors to the max width for each bin - * The last bin may not reach the max width + * The last bin may not reach the max width */ - float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); - float total_nmos_width = circuit_lib.buffer_size(circuit_model) - * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float regular_nmos_bin_width = + tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float total_nmos_width = + circuit_lib.buffer_size(circuit_model) * + tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width); - float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width); + float last_nmos_bin_width = + std::fmod(total_nmos_width, regular_nmos_bin_width); - for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { + for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { float curr_bin_width = regular_nmos_bin_width; /* For last bin, we need an irregular width */ - if ((ibin == num_nmos_bins - 1) - && (0. != last_nmos_bin_width)) { + if ((ibin == num_nmos_bins - 1) && (0. != last_nmos_bin_width)) { curr_bin_width = last_nmos_bin_width; } - status = print_spice_regular_inverter_nmos_modeling(fp, - std::to_string(ibin), - circuit_lib.port_prefix(input_ports[0]), - circuit_lib.port_prefix(output_ports[0]), - tech_lib, - tech_model, - curr_bin_width); + status = print_spice_regular_inverter_nmos_modeling( + fp, std::to_string(ibin), circuit_lib.port_prefix(input_ports[0]), + circuit_lib.port_prefix(output_ports[0]), tech_lib, tech_model, + curr_bin_width); if (CMD_EXEC_FATAL_ERROR == status) { return status; } } - print_spice_subckt_end(fp, module_manager.module_name(module_id)); + print_spice_subckt_end(fp, module_manager.module_name(module_id)); return status; } @@ -515,18 +509,16 @@ int print_spice_inverter_subckt(std::fstream& fp, const TechnologyModelId& tech_model) { int status = CMD_EXEC_SUCCESS; if (true == circuit_lib.is_power_gated(circuit_model)) { - status = print_spice_powergated_inverter_subckt(fp, - module_manager, module_id, - circuit_lib, circuit_model, - tech_lib, tech_model); - } else { + status = print_spice_powergated_inverter_subckt( + fp, module_manager, module_id, circuit_lib, circuit_model, tech_lib, + tech_model); + } else { VTR_ASSERT_SAFE(false == circuit_lib.is_power_gated(circuit_model)); - status = print_spice_regular_inverter_subckt(fp, - module_manager, module_id, + status = print_spice_regular_inverter_subckt(fp, module_manager, module_id, circuit_lib, circuit_model, tech_lib, tech_model); } - + return status; } @@ -535,7 +527,7 @@ int print_spice_inverter_subckt(std::fstream& fp, * which contains at least 2 stages * * Schematic of a multi-stage buffer - * + * * LVDD LVDD * | | * - - @@ -577,39 +569,43 @@ int print_spice_inverter_subckt(std::fstream& fp, * LGND LGND * *******************************************************************/ -static -int print_spice_powergated_buffer_subckt(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& tech_model) { +static int print_spice_powergated_buffer_subckt( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, const TechnologyLibrary& tech_lib, + const TechnologyModelId& tech_model) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } /* Print the inverter subckt definition */ - print_spice_subckt_definition(fp, module_manager, module_id); + print_spice_subckt_definition(fp, module_manager, module_id); /* Find the input and output ports: - * we do NOT support global ports here, + * we do NOT support global ports here, * it should be handled in another type of inverter subckt (power-gated) */ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); /* Make sure: - * There is only 1 input port and 1 output port, + * There is only 1 input port and 1 output port, * each size of which is 1 */ - VTR_ASSERT( (1 == input_ports.size()) && (1 == circuit_lib.port_size(input_ports[0])) ); - VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + VTR_ASSERT((1 == input_ports.size()) && + (1 == circuit_lib.port_size(input_ports[0]))); + VTR_ASSERT((1 == output_ports.size()) && + (1 == circuit_lib.port_size(output_ports[0]))); - /* If the circuit model is power-gated, we need to find at least one global config_enable signals */ + /* If the circuit model is power-gated, we need to find at least one global + * config_enable signals */ VTR_ASSERT(true == circuit_lib.is_power_gated(circuit_model)); - CircuitPortId en_port = find_circuit_model_power_gate_en_port(circuit_lib, circuit_model); - CircuitPortId enb_port = find_circuit_model_power_gate_enb_port(circuit_lib, circuit_model); + CircuitPortId en_port = + find_circuit_model_power_gate_en_port(circuit_lib, circuit_model); + CircuitPortId enb_port = + find_circuit_model_power_gate_enb_port(circuit_lib, circuit_model); VTR_ASSERT(true == circuit_lib.valid_circuit_port_id(en_port)); VTR_ASSERT(true == circuit_lib.valid_circuit_port_id(enb_port)); @@ -619,18 +615,23 @@ int print_spice_powergated_buffer_subckt(std::fstream& fp, VTR_ASSERT(2 <= circuit_lib.buffer_num_levels(circuit_model)); /* Build the array denoting width of inverters per stage */ - std::vector buffer_widths(circuit_lib.buffer_num_levels(circuit_model), 1); - for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); ++level) { - buffer_widths[level] = circuit_lib.buffer_size(circuit_model) - * std::pow(circuit_lib.buffer_f_per_stage(circuit_model), level); + std::vector buffer_widths(circuit_lib.buffer_num_levels(circuit_model), + 1); + for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); + ++level) { + buffer_widths[level] = + circuit_lib.buffer_size(circuit_model) * + std::pow(circuit_lib.buffer_f_per_stage(circuit_model), level); } - for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); ++level) { - std::string input_port_name = circuit_lib.port_prefix(input_ports[0]); - std::string output_port_name = circuit_lib.port_prefix(output_ports[0]); + for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); + ++level) { + std::string input_port_name = circuit_lib.port_prefix(input_ports[0]); + std::string output_port_name = circuit_lib.port_prefix(output_ports[0]); - /* Special for first stage: output port should be an intermediate node - * Special for rest of stages: input port should be the output of previous stage + /* Special for first stage: output port should be an intermediate node + * Special for rest of stages: input port should be the output of previous + * stage */ if (0 == level) { output_port_name += std::string("_level") + std::to_string(level); @@ -641,34 +642,31 @@ int print_spice_powergated_buffer_subckt(std::fstream& fp, /* Consider use size/bin to compact layout: * Try to size transistors to the max width for each bin - * The last bin may not reach the max width + * The last bin may not reach the max width */ - float regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); - float total_pmos_width = buffer_widths[level] - * tech_lib.model_pn_ratio(tech_model) - * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float regular_pmos_bin_width = + tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float total_pmos_width = + buffer_widths[level] * tech_lib.model_pn_ratio(tech_model) * + tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); int num_pmos_bins = std::ceil(total_pmos_width / regular_pmos_bin_width); - float last_pmos_bin_width = std::fmod(total_pmos_width, regular_pmos_bin_width); + float last_pmos_bin_width = + std::fmod(total_pmos_width, regular_pmos_bin_width); - for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { + for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { float curr_bin_width = regular_pmos_bin_width; /* For last bin, we need an irregular width */ - if ((ibin == num_pmos_bins - 1) - && (0. != last_pmos_bin_width)) { + if ((ibin == num_pmos_bins - 1) && (0. != last_pmos_bin_width)) { curr_bin_width = last_pmos_bin_width; } - std::string name_postfix = std::string("level") + std::to_string(level) + std::string("_bin") + std::to_string(ibin); + std::string name_postfix = std::string("level") + std::to_string(level) + + std::string("_bin") + std::to_string(ibin); - status = print_spice_powergated_inverter_pmos_modeling(fp, - name_postfix, - circuit_lib.port_prefix(input_ports[0]), - circuit_lib.port_prefix(output_ports[0]), - circuit_lib, - enb_port, - tech_lib, - tech_model, - curr_bin_width); + status = print_spice_powergated_inverter_pmos_modeling( + fp, name_postfix, circuit_lib.port_prefix(input_ports[0]), + circuit_lib.port_prefix(output_ports[0]), circuit_lib, enb_port, + tech_lib, tech_model, curr_bin_width); if (CMD_EXEC_FATAL_ERROR == status) { return status; } @@ -676,55 +674,52 @@ int print_spice_powergated_buffer_subckt(std::fstream& fp, /* Consider use size/bin to compact layout: * Try to size transistors to the max width for each bin - * The last bin may not reach the max width + * The last bin may not reach the max width */ - float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); - float total_nmos_width = buffer_widths[level] - * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float regular_nmos_bin_width = + tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float total_nmos_width = + buffer_widths[level] * + tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width); - float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width); + float last_nmos_bin_width = + std::fmod(total_nmos_width, regular_nmos_bin_width); - for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { + for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { float curr_bin_width = regular_nmos_bin_width; /* For last bin, we need an irregular width */ - if ((ibin == num_nmos_bins - 1) - && (0. != last_nmos_bin_width)) { + if ((ibin == num_nmos_bins - 1) && (0. != last_nmos_bin_width)) { curr_bin_width = last_nmos_bin_width; } - std::string name_postfix = std::string("level") + std::to_string(level) + std::string("_bin") + std::to_string(ibin); + std::string name_postfix = std::string("level") + std::to_string(level) + + std::string("_bin") + std::to_string(ibin); - status = print_spice_powergated_inverter_nmos_modeling(fp, - name_postfix, - circuit_lib.port_prefix(input_ports[0]), - circuit_lib.port_prefix(output_ports[0]), - circuit_lib, - en_port, - tech_lib, - tech_model, - curr_bin_width); + status = print_spice_powergated_inverter_nmos_modeling( + fp, name_postfix, circuit_lib.port_prefix(input_ports[0]), + circuit_lib.port_prefix(output_ports[0]), circuit_lib, en_port, + tech_lib, tech_model, curr_bin_width); if (CMD_EXEC_FATAL_ERROR == status) { return status; } } } - print_spice_subckt_end(fp, module_manager.module_name(module_id)); + print_spice_subckt_end(fp, module_manager.module_name(module_id)); return CMD_EXEC_SUCCESS; } - /******************************************************************** * Generate the SPICE subckt for a regular buffer * which contains at least 2 stages * - * Note: + * Note: * - This function does NOT support power-gating * It should be managed in a separated function * * Schematic of a multi-stage buffer - * + * * LVDD LVDD * | | * - - @@ -740,34 +735,35 @@ int print_spice_powergated_buffer_subckt(std::fstream& fp, * LGND LGND * *******************************************************************/ -static -int print_spice_regular_buffer_subckt(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& tech_model) { +static int print_spice_regular_buffer_subckt( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, const TechnologyLibrary& tech_lib, + const TechnologyModelId& tech_model) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } /* Print the inverter subckt definition */ - print_spice_subckt_definition(fp, module_manager, module_id); + print_spice_subckt_definition(fp, module_manager, module_id); /* Find the input and output ports: - * we do NOT support global ports here, + * we do NOT support global ports here, * it should be handled in another type of inverter subckt (power-gated) */ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); /* Make sure: - * There is only 1 input port and 1 output port, + * There is only 1 input port and 1 output port, * each size of which is 1 */ - VTR_ASSERT( (1 == input_ports.size()) && (1 == circuit_lib.port_size(input_ports[0])) ); - VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + VTR_ASSERT((1 == input_ports.size()) && + (1 == circuit_lib.port_size(input_ports[0]))); + VTR_ASSERT((1 == output_ports.size()) && + (1 == circuit_lib.port_size(output_ports[0]))); int status = CMD_EXEC_SUCCESS; @@ -775,18 +771,23 @@ int print_spice_regular_buffer_subckt(std::fstream& fp, VTR_ASSERT(2 <= circuit_lib.buffer_num_levels(circuit_model)); /* Build the array denoting width of inverters per stage */ - std::vector buffer_widths(circuit_lib.buffer_num_levels(circuit_model), 1); - for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); ++level) { - buffer_widths[level] = circuit_lib.buffer_size(circuit_model) - * std::pow(circuit_lib.buffer_f_per_stage(circuit_model), level); + std::vector buffer_widths(circuit_lib.buffer_num_levels(circuit_model), + 1); + for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); + ++level) { + buffer_widths[level] = + circuit_lib.buffer_size(circuit_model) * + std::pow(circuit_lib.buffer_f_per_stage(circuit_model), level); } - for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); ++level) { - std::string input_port_name = circuit_lib.port_prefix(input_ports[0]); - std::string output_port_name = circuit_lib.port_prefix(output_ports[0]); + for (size_t level = 0; level < circuit_lib.buffer_num_levels(circuit_model); + ++level) { + std::string input_port_name = circuit_lib.port_prefix(input_ports[0]); + std::string output_port_name = circuit_lib.port_prefix(output_ports[0]); - /* Special for first stage: output port should be an intermediate node - * Special for rest of stages: input port should be the output of previous stage + /* Special for first stage: output port should be an intermediate node + * Special for rest of stages: input port should be the output of previous + * stage */ if (0 == level) { output_port_name += std::string("_level") + std::to_string(level); @@ -794,35 +795,34 @@ int print_spice_regular_buffer_subckt(std::fstream& fp, VTR_ASSERT(0 < level); input_port_name += std::string("_level") + std::to_string(level - 1); } - + /* Consider use size/bin to compact layout: * Try to size transistors to the max width for each bin - * The last bin may not reach the max width + * The last bin may not reach the max width */ - float regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); - float total_pmos_width = buffer_widths[level] - * tech_lib.model_pn_ratio(tech_model) - * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float regular_pmos_bin_width = + tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float total_pmos_width = + buffer_widths[level] * tech_lib.model_pn_ratio(tech_model) * + tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); int num_pmos_bins = std::ceil(total_pmos_width / regular_pmos_bin_width); - float last_pmos_bin_width = std::fmod(total_pmos_width, regular_pmos_bin_width); + float last_pmos_bin_width = + std::fmod(total_pmos_width, regular_pmos_bin_width); - for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { + for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { float curr_bin_width = regular_pmos_bin_width; /* For last bin, we need an irregular width */ - if ((ibin == num_pmos_bins - 1) - && (0. != last_pmos_bin_width)) { + if ((ibin == num_pmos_bins - 1) && (0. != last_pmos_bin_width)) { curr_bin_width = last_pmos_bin_width; } - std::string name_postfix = std::string("level") + std::to_string(level) + std::string("_bin") + std::to_string(ibin); + std::string name_postfix = std::string("level") + std::to_string(level) + + std::string("_bin") + std::to_string(ibin); - status = print_spice_regular_inverter_pmos_modeling(fp, - name_postfix, - circuit_lib.port_prefix(input_ports[0]), - circuit_lib.port_prefix(output_ports[0]), - tech_lib, - tech_model, - curr_bin_width); + status = print_spice_regular_inverter_pmos_modeling( + fp, name_postfix, circuit_lib.port_prefix(input_ports[0]), + circuit_lib.port_prefix(output_ports[0]), tech_lib, tech_model, + curr_bin_width); if (CMD_EXEC_FATAL_ERROR == status) { return status; } @@ -830,44 +830,44 @@ int print_spice_regular_buffer_subckt(std::fstream& fp, /* Consider use size/bin to compact layout: * Try to size transistors to the max width for each bin - * The last bin may not reach the max width + * The last bin may not reach the max width */ - float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); - float total_nmos_width = buffer_widths[level] - * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float regular_nmos_bin_width = + tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float total_nmos_width = + buffer_widths[level] * + tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width); - float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width); + float last_nmos_bin_width = + std::fmod(total_nmos_width, regular_nmos_bin_width); - for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { + for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { float curr_bin_width = regular_nmos_bin_width; /* For last bin, we need an irregular width */ - if ((ibin == num_nmos_bins - 1) - && (0. != last_nmos_bin_width)) { + if ((ibin == num_nmos_bins - 1) && (0. != last_nmos_bin_width)) { curr_bin_width = last_nmos_bin_width; } - std::string name_postfix = std::string("level") + std::to_string(level) + std::string("_bin") + std::to_string(ibin); + std::string name_postfix = std::string("level") + std::to_string(level) + + std::string("_bin") + std::to_string(ibin); - status = print_spice_regular_inverter_nmos_modeling(fp, - name_postfix, - circuit_lib.port_prefix(input_ports[0]), - circuit_lib.port_prefix(output_ports[0]), - tech_lib, - tech_model, - curr_bin_width); + status = print_spice_regular_inverter_nmos_modeling( + fp, name_postfix, circuit_lib.port_prefix(input_ports[0]), + circuit_lib.port_prefix(output_ports[0]), tech_lib, tech_model, + curr_bin_width); if (CMD_EXEC_FATAL_ERROR == status) { return status; } } } - print_spice_subckt_end(fp, module_manager.module_name(module_id)); + print_spice_subckt_end(fp, module_manager.module_name(module_id)); return status; } /******************************************************************** - * Generate the SPICE subckt for an buffer + * Generate the SPICE subckt for an buffer * which consists of multiple stage of inverters *******************************************************************/ int print_spice_buffer_subckt(std::fstream& fp, @@ -879,18 +879,16 @@ int print_spice_buffer_subckt(std::fstream& fp, const TechnologyModelId& tech_model) { int status = CMD_EXEC_SUCCESS; if (true == circuit_lib.is_power_gated(circuit_model)) { - status = print_spice_powergated_buffer_subckt(fp, - module_manager, module_id, + status = print_spice_powergated_buffer_subckt(fp, module_manager, module_id, circuit_lib, circuit_model, tech_lib, tech_model); - } else { + } else { VTR_ASSERT_SAFE(false == circuit_lib.is_power_gated(circuit_model)); - status = print_spice_regular_buffer_subckt(fp, - module_manager, module_id, + status = print_spice_regular_buffer_subckt(fp, module_manager, module_id, circuit_lib, circuit_model, tech_lib, tech_model); } - + return status; } diff --git a/openfpga/src/fpga_spice/spice_buffer.h b/openfpga/src/fpga_spice/spice_buffer.h index d7019f995..a709d0b4c 100644 --- a/openfpga/src/fpga_spice/spice_buffer.h +++ b/openfpga/src/fpga_spice/spice_buffer.h @@ -4,10 +4,11 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include #include -#include "module_manager.h" +#include + #include "circuit_library.h" +#include "module_manager.h" #include "technology_library.h" /******************************************************************** @@ -33,7 +34,6 @@ int print_spice_buffer_subckt(std::fstream& fp, const TechnologyLibrary& tech_lib, const TechnologyModelId& tech_model); - } /* end namespace openfpga */ #endif diff --git a/openfpga/src/fpga_spice/spice_constants.h b/openfpga/src/fpga_spice/spice_constants.h index a881deb93..1414b9061 100644 --- a/openfpga/src/fpga_spice/spice_constants.h +++ b/openfpga/src/fpga_spice/spice_constants.h @@ -14,7 +14,8 @@ constexpr const char* MUX_PRIMITIVES_SPICE_FILE_NAME = "mux_primitives.sp"; constexpr const char* MUXES_SPICE_FILE_NAME = "muxes.sp"; constexpr const char* LUTS_SPICE_FILE_NAME = "luts.sp"; constexpr const char* MEMORIES_SPICE_FILE_NAME = "memories.sp"; -constexpr const char* FABRIC_INCLUDE_SPICE_NETLIST_FILE_NAME = "fabric_netlists.sp"; +constexpr const char* FABRIC_INCLUDE_SPICE_NETLIST_FILE_NAME = + "fabric_netlists.sp"; constexpr const char* SPICE_SUBCKT_VDD_PORT_NAME = "VDD"; constexpr const char* SPICE_SUBCKT_GND_PORT_NAME = "VSS"; diff --git a/openfpga/src/fpga_spice/spice_essential_gates.cpp b/openfpga/src/fpga_spice/spice_essential_gates.cpp index 301b81de1..ec747f970 100644 --- a/openfpga/src/fpga_spice/spice_essential_gates.cpp +++ b/openfpga/src/fpga_spice/spice_essential_gates.cpp @@ -1,11 +1,11 @@ /************************************************ - * This file includes functions on + * This file includes functions on * outputting SPICE netlists for essential gates * which are inverters, buffers, transmission-gates - * logic gates etc. + * logic gates etc. ***********************************************/ -#include #include +#include #include /* Headers from vtrutil library */ @@ -16,18 +16,16 @@ #include "command_exit_codes.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - -#include "openfpga_naming.h" #include "circuit_library_utils.h" - -#include "spice_constants.h" -#include "spice_writer_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" #include "spice_buffer.h" -#include "spice_passgate.h" -#include "spice_logic_gate.h" -#include "spice_wire.h" +#include "spice_constants.h" #include "spice_essential_gates.h" +#include "spice_logic_gate.h" +#include "spice_passgate.h" +#include "spice_wire.h" +#include "spice_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -36,10 +34,9 @@ namespace openfpga { * Generate the SPICE netlist for a constant generator, * i.e., either VDD or GND ***********************************************/ -static -void print_spice_supply_wrapper_subckt(const ModuleManager& module_manager, - std::fstream& fp, - const size_t& const_value) { +static void print_spice_supply_wrapper_subckt( + const ModuleManager& module_manager, std::fstream& fp, + const size_t& const_value) { /* Find the module in module manager */ std::string module_name = generate_const_value_module_name(const_value); ModuleId const_val_module = module_manager.find_module(module_name); @@ -53,8 +50,10 @@ void print_spice_supply_wrapper_subckt(const ModuleManager& module_manager, /* Finish dumping ports */ /* Find the only output*/ - for (const ModulePortId& module_port_id : module_manager.module_ports(const_val_module)) { - BasicPort module_port = module_manager.module_port(const_val_module, module_port_id); + for (const ModulePortId& module_port_id : + module_manager.module_ports(const_val_module)) { + BasicPort module_port = + module_manager.module_port(const_val_module, module_port_id); for (const auto& pin : module_port.pins()) { BasicPort spice_pin(module_port.get_name(), pin, pin); std::string const_pin_name = std::string(SPICE_SUBCKT_VDD_PORT_NAME); @@ -63,13 +62,12 @@ void print_spice_supply_wrapper_subckt(const ModuleManager& module_manager, } else { VTR_ASSERT(1 == const_value); } - - print_spice_short_connection(fp, - generate_spice_port(spice_pin, true), + + print_spice_short_connection(fp, generate_spice_port(spice_pin, true), const_pin_name); } } - + /* Put an end to the SPICE subcircuit */ print_spice_subckt_end(fp, module_name); } @@ -85,19 +83,20 @@ int print_spice_supply_wrappers(NetlistManager& netlist_manager, int status = CMD_EXEC_SUCCESS; /* Create file stream */ - std::string spice_fname = submodule_dir + std::string(SUPPLY_WRAPPER_SPICE_FILE_NAME); - + std::string spice_fname = + submodule_dir + std::string(SUPPLY_WRAPPER_SPICE_FILE_NAME); + std::fstream fp; - + /* Create the file stream */ fp.open(spice_fname, std::fstream::out | std::fstream::trunc); /* Check if the file stream if valid or not */ - check_file_stream(spice_fname.c_str(), fp); - + check_file_stream(spice_fname.c_str(), fp); + /* Create file */ VTR_LOG("Generating SPICE netlist '%s' for voltage supply wrappers...", spice_fname.c_str()); - + print_spice_file_header(fp, std::string("Voltage Supply Wrappers")); /* VDD */ @@ -125,12 +124,11 @@ int print_spice_supply_wrappers(NetlistManager& netlist_manager, * - pass-transistor or transmission gates * - logic gates *******************************************************************/ -int print_spice_essential_gates(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const TechnologyLibrary& tech_lib, - const std::map& circuit_tech_binding, - const std::string& submodule_dir) { +int print_spice_essential_gates( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, const TechnologyLibrary& tech_lib, + const std::map& circuit_tech_binding, + const std::string& submodule_dir) { int status = CMD_EXEC_SUCCESS; /* Iterate over the circuit models */ @@ -141,26 +139,28 @@ int print_spice_essential_gates(NetlistManager& netlist_manager, } /* Output only the model type is supported in auto-generation */ - if ( (CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(circuit_model)) - && (CIRCUIT_MODEL_PASSGATE != circuit_lib.model_type(circuit_model)) - && (CIRCUIT_MODEL_WIRE != circuit_lib.model_type(circuit_model)) - && (CIRCUIT_MODEL_GATE != circuit_lib.model_type(circuit_model))) { - continue; + if ((CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(circuit_model)) && + (CIRCUIT_MODEL_PASSGATE != circuit_lib.model_type(circuit_model)) && + (CIRCUIT_MODEL_WIRE != circuit_lib.model_type(circuit_model)) && + (CIRCUIT_MODEL_GATE != circuit_lib.model_type(circuit_model))) { + continue; } /* Spot module id */ - const ModuleId& module_id = module_manager.find_module(circuit_lib.model_name(circuit_model)); + const ModuleId& module_id = + module_manager.find_module(circuit_lib.model_name(circuit_model)); - TechnologyModelId tech_model; + TechnologyModelId tech_model; /* Focus on inverter/buffer/pass-gate/logic gates only */ - if ( (CIRCUIT_MODEL_INVBUF == circuit_lib.model_type(circuit_model)) - || (CIRCUIT_MODEL_PASSGATE == circuit_lib.model_type(circuit_model)) - || (CIRCUIT_MODEL_GATE == circuit_lib.model_type(circuit_model))) { + if ((CIRCUIT_MODEL_INVBUF == circuit_lib.model_type(circuit_model)) || + (CIRCUIT_MODEL_PASSGATE == circuit_lib.model_type(circuit_model)) || + (CIRCUIT_MODEL_GATE == circuit_lib.model_type(circuit_model))) { auto result = circuit_tech_binding.find(circuit_model); if (result == circuit_tech_binding.end()) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Unable to find technology binding for circuit model '%s'!\n", - circuit_lib.model_name(circuit_model).c_str()); + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Unable to find technology binding for circuit model '%s'!\n", + circuit_lib.model_name(circuit_model).c_str()); return CMD_EXEC_FATAL_ERROR; } /* Valid technology binding. Assign techology model */ @@ -171,20 +171,21 @@ int print_spice_essential_gates(NetlistManager& netlist_manager, } /* Create file stream */ - std::string spice_fname = submodule_dir + circuit_lib.model_name(circuit_model) + std::string(SPICE_NETLIST_FILE_POSTFIX); - + std::string spice_fname = submodule_dir + + circuit_lib.model_name(circuit_model) + + std::string(SPICE_NETLIST_FILE_POSTFIX); + std::fstream fp; - + /* Create the file stream */ fp.open(spice_fname, std::fstream::out | std::fstream::trunc); /* Check if the file stream if valid or not */ - check_file_stream(spice_fname.c_str(), fp); - + check_file_stream(spice_fname.c_str(), fp); + /* Create file */ VTR_LOG("Generating SPICE netlist '%s' for circuit model '%s'...", - spice_fname.c_str(), - circuit_lib.model_name(circuit_model).c_str()); - + spice_fname.c_str(), circuit_lib.model_name(circuit_model).c_str()); + print_spice_file_header(fp, circuit_lib.model_name(circuit_model)); /* A flag to record if any logic has been filled to the netlist */ @@ -194,17 +195,16 @@ int print_spice_essential_gates(NetlistManager& netlist_manager, if (CIRCUIT_MODEL_INVBUF == circuit_lib.model_type(circuit_model)) { if (CIRCUIT_MODEL_BUF_INV == circuit_lib.buffer_type(circuit_model)) { VTR_ASSERT(true == module_manager.valid_module_id(module_id)); - status = print_spice_inverter_subckt(fp, - module_manager, module_id, + status = print_spice_inverter_subckt(fp, module_manager, module_id, circuit_lib, circuit_model, tech_lib, tech_model); netlist_filled = true; } else { - VTR_ASSERT(CIRCUIT_MODEL_BUF_BUF == circuit_lib.buffer_type(circuit_model)); - status = print_spice_buffer_subckt(fp, - module_manager, module_id, - circuit_lib, circuit_model, - tech_lib, tech_model); + VTR_ASSERT(CIRCUIT_MODEL_BUF_BUF == + circuit_lib.buffer_type(circuit_model)); + status = + print_spice_buffer_subckt(fp, module_manager, module_id, circuit_lib, + circuit_model, tech_lib, tech_model); netlist_filled = true; } @@ -215,10 +215,9 @@ int print_spice_essential_gates(NetlistManager& netlist_manager, /* Now branch on netlist writing: for pass-gate logic */ if (CIRCUIT_MODEL_PASSGATE == circuit_lib.model_type(circuit_model)) { - status = print_spice_passgate_subckt(fp, - module_manager, module_id, - circuit_lib, circuit_model, - tech_lib, tech_model); + status = + print_spice_passgate_subckt(fp, module_manager, module_id, circuit_lib, + circuit_model, tech_lib, tech_model); netlist_filled = true; if (CMD_EXEC_FATAL_ERROR == status) { @@ -229,16 +228,15 @@ int print_spice_essential_gates(NetlistManager& netlist_manager, /* Now branch on netlist writing: for logic gate */ if (CIRCUIT_MODEL_GATE == circuit_lib.model_type(circuit_model)) { if (CIRCUIT_MODEL_GATE_AND == circuit_lib.gate_type(circuit_model)) { - status = print_spice_and_gate_subckt(fp, - module_manager, module_id, + status = print_spice_and_gate_subckt(fp, module_manager, module_id, circuit_lib, circuit_model, tech_lib, tech_model); netlist_filled = true; - } else if (CIRCUIT_MODEL_GATE_OR == circuit_lib.gate_type(circuit_model)) { - status = print_spice_or_gate_subckt(fp, - module_manager, module_id, - circuit_lib, circuit_model, - tech_lib, tech_model); + } else if (CIRCUIT_MODEL_GATE_OR == + circuit_lib.gate_type(circuit_model)) { + status = + print_spice_or_gate_subckt(fp, module_manager, module_id, circuit_lib, + circuit_model, tech_lib, tech_model); netlist_filled = true; } @@ -249,8 +247,7 @@ int print_spice_essential_gates(NetlistManager& netlist_manager, /* Now branch on netlist writing: for wires */ if (CIRCUIT_MODEL_WIRE == circuit_lib.model_type(circuit_model)) { - status = print_spice_wire_subckt(fp, - module_manager, module_id, + status = print_spice_wire_subckt(fp, module_manager, module_id, circuit_lib, circuit_model); netlist_filled = true; if (CMD_EXEC_FATAL_ERROR == status) { @@ -262,9 +259,11 @@ int print_spice_essential_gates(NetlistManager& netlist_manager, * If not, flag a fatal error */ if (false == netlist_filled) { - VTR_LOG_ERROR("Cannot auto-generate netlist for circuit model '%s'!\n\tThe circuit topology is not supported yet!\n", - circuit_lib.model_name(circuit_model).c_str()); - status = CMD_EXEC_FATAL_ERROR; + VTR_LOG_ERROR( + "Cannot auto-generate netlist for circuit model '%s'!\n\tThe circuit " + "topology is not supported yet!\n", + circuit_lib.model_name(circuit_model).c_str()); + status = CMD_EXEC_FATAL_ERROR; break; } @@ -274,10 +273,11 @@ int print_spice_essential_gates(NetlistManager& netlist_manager, /* Add fname to the netlist name list */ NetlistId nlist_id = netlist_manager.add_netlist(spice_fname); VTR_ASSERT(NetlistId::INVALID() != nlist_id); - netlist_manager.set_netlist_type(nlist_id, NetlistManager::SUBMODULE_NETLIST); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::SUBMODULE_NETLIST); VTR_LOG("Done\n"); - } + } return status; } diff --git a/openfpga/src/fpga_spice/spice_essential_gates.h b/openfpga/src/fpga_spice/spice_essential_gates.h index dc40a2531..e264a90a6 100644 --- a/openfpga/src/fpga_spice/spice_essential_gates.h +++ b/openfpga/src/fpga_spice/spice_essential_gates.h @@ -4,11 +4,12 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include #include -#include "netlist_manager.h" -#include "module_manager.h" +#include + #include "circuit_library.h" +#include "module_manager.h" +#include "netlist_manager.h" #include "technology_library.h" /******************************************************************** @@ -22,12 +23,11 @@ int print_spice_supply_wrappers(NetlistManager& netlist_manager, const ModuleManager& module_manager, const std::string& submodule_dir); -int print_spice_essential_gates(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const TechnologyLibrary& tech_lib, - const std::map& circuit_tech_binding, - const std::string& submodule_dir); +int print_spice_essential_gates( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, const TechnologyLibrary& tech_lib, + const std::map& circuit_tech_binding, + const std::string& submodule_dir); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_spice/spice_grid.cpp b/openfpga/src/fpga_spice/spice_grid.cpp index c04ed8920..fee98b43f 100644 --- a/openfpga/src/fpga_spice/spice_grid.cpp +++ b/openfpga/src/fpga_spice/spice_grid.cpp @@ -1,14 +1,14 @@ /******************************************************************** * This file includes functions to print SPICE subckts for a Grid - * (CLBs, I/Os, heterogeneous blocks etc.) + * (CLBs, I/Os, heterogeneous blocks etc.) *******************************************************************/ /* System header files */ -#include #include +#include /* Headers from vtrutil library */ -#include "vtr_geometry.h" #include "vtr_assert.h" +#include "vtr_geometry.h" #include "vtr_log.h" /* Headers from readarch library */ @@ -19,19 +19,17 @@ #include "openfpga_side_manager.h" /* Headers from vpr library */ -#include "vpr_utils.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" -#include "openfpga_physical_tile_utils.h" -#include "pb_type_utils.h" #include "circuit_library_utils.h" #include "module_manager_utils.h" - +#include "openfpga_naming.h" +#include "openfpga_physical_tile_utils.h" +#include "openfpga_reserved_words.h" +#include "pb_type_utils.h" #include "spice_constants.h" -#include "spice_writer_utils.h" -#include "spice_subckt_writer.h" #include "spice_grid.h" +#include "spice_subckt_writer.h" +#include "spice_writer_utils.h" +#include "vpr_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -39,7 +37,8 @@ namespace openfpga { /******************************************************************** * Print SPICE subckts of a primitive node in the pb_graph_node graph * This generic function can support all the different types of primitive nodes - * i.e., Look-Up Tables (LUTs), Flip-flops (FFs) and hard logic blocks such as adders. + * i.e., Look-Up Tables (LUTs), Flip-flops (FFs) and hard logic blocks such as + *adders. * * The SPICE subckt will consist of two parts: * 1. Logic module of the primitive node @@ -52,34 +51,32 @@ namespace openfpga { * * Primitive block * +---------------------------------------+ - * | | + * | | * | +---------+ +---------+ | * in |----->| |--->| |<------|configuration lines * | | Logic |... | Memory | | * out|<-----| |--->| | | * | +---------+ +---------+ | - * | | + * | | * +---------------------------------------+ * *******************************************************************/ -static -void print_spice_primitive_block(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const std::string& subckt_dir, - t_pb_graph_node* primitive_pb_graph_node, - const bool& verbose) { - /* Ensure a valid pb_graph_node */ +static void print_spice_primitive_block( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const std::string& subckt_dir, t_pb_graph_node* primitive_pb_graph_node, + const bool& verbose) { + /* Ensure a valid pb_graph_node */ if (nullptr == primitive_pb_graph_node) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid primitive_pb_graph_node!\n"); + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid primitive_pb_graph_node!\n"); exit(1); } /* Give a name to the Verilog netlist */ /* Create the file name for Verilog */ - std::string spice_fname(subckt_dir - + generate_logical_tile_netlist_name(std::string(), primitive_pb_graph_node, std::string(SPICE_NETLIST_FILE_POSTFIX)) - ); + std::string spice_fname(subckt_dir + + generate_logical_tile_netlist_name( + std::string(), primitive_pb_graph_node, + std::string(SPICE_NETLIST_FILE_POSTFIX))); VTR_LOG("Writing SPICE netlist '%s' for primitive pb_type '%s' ...", spice_fname.c_str(), primitive_pb_graph_node->pb_type->name); @@ -91,10 +88,13 @@ void print_spice_primitive_block(NetlistManager& netlist_manager, check_file_stream(spice_fname.c_str(), fp); - print_spice_file_header(fp, std::string("SPICE subckts for primitive pb_type: " + std::string(primitive_pb_graph_node->pb_type->name))); + print_spice_file_header( + fp, std::string("SPICE subckts for primitive pb_type: " + + std::string(primitive_pb_graph_node->pb_type->name))); /* Generate the module name for this primitive pb_graph_node*/ - std::string primitive_module_name = generate_physical_block_module_name(primitive_pb_graph_node->pb_type); + std::string primitive_module_name = + generate_physical_block_module_name(primitive_pb_graph_node->pb_type); /* Create a module of the primitive LUT and register it to module manager */ ModuleId primitive_module = module_manager.find_module(primitive_module_name); @@ -102,9 +102,9 @@ void print_spice_primitive_block(NetlistManager& netlist_manager, VTR_ASSERT(true == module_manager.valid_module_id(primitive_module)); VTR_LOGV(verbose, - "Writing SPICE codes of logical tile primitive block '%s'...", + "Writing SPICE codes of logical tile primitive block '%s'...", module_manager.module_name(primitive_module).c_str()); - + /* Write the spice module */ write_spice_subckt_to_file(fp, module_manager, primitive_module); @@ -114,80 +114,75 @@ void print_spice_primitive_block(NetlistManager& netlist_manager, /* Add fname to the netlist name list */ NetlistId nlist_id = netlist_manager.add_netlist(spice_fname); VTR_ASSERT(NetlistId::INVALID() != nlist_id); - netlist_manager.set_netlist_type(nlist_id, NetlistManager::LOGIC_BLOCK_NETLIST); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::LOGIC_BLOCK_NETLIST); VTR_LOGV(verbose, "Done\n"); } /******************************************************************** * Print SPICE subckts of physical blocks inside a grid (CLB, I/O. etc.) - * This function will traverse the graph of complex logic block (t_pb_graph_node) - * in a recursive way, using a Depth First Search (DFS) algorithm. - * As such, primitive physical blocks (LUTs, FFs, etc.), leaf node of the pb_graph - * will be printed out first, while the top-level will be printed out in the last + * This function will traverse the graph of complex logic block + *(t_pb_graph_node) in a recursive way, using a Depth First Search (DFS) + *algorithm. As such, primitive physical blocks (LUTs, FFs, etc.), leaf node of + *the pb_graph will be printed out first, while the top-level will be printed + *out in the last * - * Note: this function will print a unique SPICE subckt for each type of - * t_pb_graph_node, i.e., t_pb_type, in the graph, in order to enable highly + * Note: this function will print a unique SPICE subckt for each type of + * t_pb_graph_node, i.e., t_pb_type, in the graph, in order to enable highly * hierarchical Verilog organization as well as simplify the Verilog file sizes. * * Note: DFS is the right way. Do NOT use BFS. * DFS can guarantee that all the sub-modules can be registered properly - * to its parent in module manager + * to its parent in module manager *******************************************************************/ -static -void rec_print_spice_logical_tile(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const VprDeviceAnnotation& device_annotation, - const std::string& subckt_dir, - t_pb_graph_node* physical_pb_graph_node, - const bool& verbose) { - +static void rec_print_spice_logical_tile( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const VprDeviceAnnotation& device_annotation, const std::string& subckt_dir, + t_pb_graph_node* physical_pb_graph_node, const bool& verbose) { /* Check cur_pb_graph_node*/ if (nullptr == physical_pb_graph_node) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid physical_pb_graph_node\n"); + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid physical_pb_graph_node\n"); exit(1); } /* Get the pb_type definition related to the node */ - t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; + t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; /* Find the mode that physical implementation of a pb_type */ t_mode* physical_mode = device_annotation.physical_mode(physical_pb_type); - /* For non-leaf node in the pb_type graph: - * Recursively Depth-First Generate all the child pb_type at the level + /* For non-leaf node in the pb_type graph: + * Recursively Depth-First Generate all the child pb_type at the level */ - if (false == is_primitive_pb_type(physical_pb_type)) { + if (false == is_primitive_pb_type(physical_pb_type)) { for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) { /* Go recursive to visit the children */ - rec_print_spice_logical_tile(netlist_manager, - module_manager, device_annotation, - subckt_dir, - &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][0]), - verbose); + rec_print_spice_logical_tile( + netlist_manager, module_manager, device_annotation, subckt_dir, + &(physical_pb_graph_node + ->child_pb_graph_nodes[physical_mode->index][ipb][0]), + verbose); } } /* For leaf node, a primitive SPICE subckt will be generated. - * Note that the primitive may be mapped to a standard cell, we force to use + * Note that the primitive may be mapped to a standard cell, we force to use * explict port mapping. This aims to avoid any port sequence issues!!! */ - if (true == is_primitive_pb_type(physical_pb_type)) { - print_spice_primitive_block(netlist_manager, - module_manager, - subckt_dir, - physical_pb_graph_node, - verbose); + if (true == is_primitive_pb_type(physical_pb_type)) { + print_spice_primitive_block(netlist_manager, module_manager, subckt_dir, + physical_pb_graph_node, verbose); /* Finish for primitive node, return */ return; } /* Give a name to the Verilog netlist */ /* Create the file name for Verilog */ - std::string spice_fname(subckt_dir - + generate_logical_tile_netlist_name(std::string(), physical_pb_graph_node, std::string(SPICE_NETLIST_FILE_POSTFIX)) - ); + std::string spice_fname(subckt_dir + + generate_logical_tile_netlist_name( + std::string(), physical_pb_graph_node, + std::string(SPICE_NETLIST_FILE_POSTFIX))); VTR_LOG("Writing SPICE netlist '%s' for pb_type '%s' ...", spice_fname.c_str(), physical_pb_type->name); @@ -199,26 +194,31 @@ void rec_print_spice_logical_tile(NetlistManager& netlist_manager, check_file_stream(spice_fname.c_str(), fp); - print_spice_file_header(fp, std::string("SPICE subckts for pb_type: " + std::string(physical_pb_type->name))); + print_spice_file_header(fp, std::string("SPICE subckts for pb_type: " + + std::string(physical_pb_type->name))); /* Generate the name of the SPICE subckt for this pb_type */ - std::string pb_module_name = generate_physical_block_module_name(physical_pb_type); + std::string pb_module_name = + generate_physical_block_module_name(physical_pb_type); /* Register the SPICE subckt in module manager */ ModuleId pb_module = module_manager.find_module(pb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); - VTR_LOGV(verbose, - "Writing SPICE codes of pb_type '%s'...", + VTR_LOGV(verbose, "Writing SPICE codes of pb_type '%s'...", module_manager.module_name(pb_module).c_str()); /* Comment lines */ - print_spice_comment(fp, std::string("BEGIN Physical programmable logic block SPICE subckt: " + std::string(physical_pb_type->name))); + print_spice_comment( + fp, std::string("BEGIN Physical programmable logic block SPICE subckt: " + + std::string(physical_pb_type->name))); /* Write the spice module */ write_spice_subckt_to_file(fp, module_manager, pb_module); - print_spice_comment(fp, std::string("END Physical programmable logic block SPICE subckt: " + std::string(physical_pb_type->name))); + print_spice_comment( + fp, std::string("END Physical programmable logic block SPICE subckt: " + + std::string(physical_pb_type->name))); /* Close file handler */ fp.close(); @@ -226,39 +226,34 @@ void rec_print_spice_logical_tile(NetlistManager& netlist_manager, /* Add fname to the netlist name list */ NetlistId nlist_id = netlist_manager.add_netlist(spice_fname); VTR_ASSERT(NetlistId::INVALID() != nlist_id); - netlist_manager.set_netlist_type(nlist_id, NetlistManager::LOGIC_BLOCK_NETLIST); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::LOGIC_BLOCK_NETLIST); VTR_LOGV(verbose, "Done\n"); } /***************************************************************************** - * This function will create a Verilog file and print out a Verilog netlist - * for the logical tile (pb_graph/pb_type) + * This function will create a Verilog file and print out a Verilog netlist + * for the logical tile (pb_graph/pb_type) *****************************************************************************/ -static -void print_spice_logical_tile_netlist(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const VprDeviceAnnotation& device_annotation, - const std::string& subckt_dir, - t_pb_graph_node* pb_graph_head, - const bool& verbose) { - +static void print_spice_logical_tile_netlist( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const VprDeviceAnnotation& device_annotation, const std::string& subckt_dir, + t_pb_graph_node* pb_graph_head, const bool& verbose) { VTR_LOG("Writing Verilog netlists for logic tile '%s' ...", pb_graph_head->pb_type->name); VTR_LOG("\n"); /* Print SPICE subckts for all the pb_types/pb_graph_nodes - * use a Depth-First Search Algorithm to print the sub-modules + * use a Depth-First Search Algorithm to print the sub-modules * Note: DFS is the right way. Do NOT use BFS. * DFS can guarantee that all the sub-modules can be registered properly - * to its parent in module manager + * to its parent in module manager */ - /* Print SPICE subckts starting from the top-level pb_type/pb_graph_node, and traverse the graph in a recursive way */ - rec_print_spice_logical_tile(netlist_manager, - module_manager, - device_annotation, - subckt_dir, - pb_graph_head, + /* Print SPICE subckts starting from the top-level pb_type/pb_graph_node, and + * traverse the graph in a recursive way */ + rec_print_spice_logical_tile(netlist_manager, module_manager, + device_annotation, subckt_dir, pb_graph_head, verbose); VTR_LOG("Done\n"); @@ -266,40 +261,37 @@ void print_spice_logical_tile_netlist(NetlistManager& netlist_manager, } /***************************************************************************** - * This function will create a Verilog file and print out a Verilog netlist - * for a type of physical block + * This function will create a Verilog file and print out a Verilog netlist + * for a type of physical block * - * For IO blocks: + * For IO blocks: * The param 'border_side' is required, which is specify which side of fabric * the I/O block locates at. *****************************************************************************/ -static -void print_spice_physical_tile_netlist(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const std::string& subckt_dir, - t_physical_tile_type_ptr phy_block_type, - const e_side& border_side) { +static void print_spice_physical_tile_netlist( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const std::string& subckt_dir, t_physical_tile_type_ptr phy_block_type, + const e_side& border_side) { /* Check code: if this is an IO block, the border side MUST be valid */ if (true == is_io_type(phy_block_type)) { VTR_ASSERT(NUM_SIDES != border_side); } - + /* Give a name to the Verilog netlist */ /* Create the file name for Verilog */ - std::string spice_fname(subckt_dir - + generate_grid_block_netlist_name(std::string(GRID_MODULE_NAME_PREFIX) + std::string(phy_block_type->name), - is_io_type(phy_block_type), - border_side, - std::string(SPICE_NETLIST_FILE_POSTFIX)) - ); + std::string spice_fname( + subckt_dir + + generate_grid_block_netlist_name( + std::string(GRID_MODULE_NAME_PREFIX) + std::string(phy_block_type->name), + is_io_type(phy_block_type), border_side, + std::string(SPICE_NETLIST_FILE_POSTFIX))); /* Echo status */ if (true == is_io_type(phy_block_type)) { SideManager side_manager(border_side); VTR_LOG("Writing SPICE Netlist '%s' for physical tile '%s' at %s side ...", - spice_fname.c_str(), phy_block_type->name, - side_manager.c_str()); - } else { + spice_fname.c_str(), phy_block_type->name, side_manager.c_str()); + } else { VTR_LOG("Writing SPICE Netlist '%s' for physical_tile '%s'...", spice_fname.c_str(), phy_block_type->name); } @@ -310,18 +302,25 @@ void print_spice_physical_tile_netlist(NetlistManager& netlist_manager, check_file_stream(spice_fname.c_str(), fp); - print_spice_file_header(fp, std::string("SPICE subckts for physical tile: " + std::string(phy_block_type->name) + "]")); + print_spice_file_header(fp, + std::string("SPICE subckts for physical tile: " + + std::string(phy_block_type->name) + "]")); - /* Create a Verilog Module for the top-level physical block, and add to module manager */ - std::string grid_module_name = generate_grid_block_module_name(std::string(GRID_SPICE_FILE_NAME_PREFIX), std::string(phy_block_type->name), is_io_type(phy_block_type), border_side); - ModuleId grid_module = module_manager.find_module(grid_module_name); + /* Create a Verilog Module for the top-level physical block, and add to module + * manager */ + std::string grid_module_name = generate_grid_block_module_name( + std::string(GRID_SPICE_FILE_NAME_PREFIX), std::string(phy_block_type->name), + is_io_type(phy_block_type), border_side); + ModuleId grid_module = module_manager.find_module(grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); /* Write the spice module */ - print_spice_comment(fp, std::string("BEGIN Grid SPICE subckt: " + module_manager.module_name(grid_module))); + print_spice_comment(fp, std::string("BEGIN Grid SPICE subckt: " + + module_manager.module_name(grid_module))); write_spice_subckt_to_file(fp, module_manager, grid_module); - print_spice_comment(fp, std::string("END Grid SPICE subckt: " + module_manager.module_name(grid_module))); + print_spice_comment(fp, std::string("END Grid SPICE subckt: " + + module_manager.module_name(grid_module))); /* Add an empty line as a splitter */ fp << std::endl; @@ -332,7 +331,8 @@ void print_spice_physical_tile_netlist(NetlistManager& netlist_manager, /* Add fname to the netlist name list */ NetlistId nlist_id = netlist_manager.add_netlist(spice_fname); VTR_ASSERT(NetlistId::INVALID() != nlist_id); - netlist_manager.set_netlist_type(nlist_id, NetlistManager::LOGIC_BLOCK_NETLIST); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::LOGIC_BLOCK_NETLIST); VTR_LOG("Done\n"); } @@ -347,31 +347,29 @@ void print_spice_grids(NetlistManager& netlist_manager, const ModuleManager& module_manager, const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, - const std::string& subckt_dir, - const bool& verbose) { - /* Create a vector to contain all the Verilog netlist names that have been generated in this function */ + const std::string& subckt_dir, const bool& verbose) { + /* Create a vector to contain all the Verilog netlist names that have been + * generated in this function */ std::vector netlist_names; - /* Enumerate the types of logical tiles, and build a module for each + /* Enumerate the types of logical tiles, and build a module for each * Write modules for all the pb_types/pb_graph_nodes - * use a Depth-First Search Algorithm to print the sub-modules + * use a Depth-First Search Algorithm to print the sub-modules * Note: DFS is the right way. Do NOT use BFS. * DFS can guarantee that all the sub-modules can be registered properly - * to its parent in module manager + * to its parent in module manager */ VTR_LOG("Writing logical tiles..."); VTR_LOGV(verbose, "\n"); - for (const t_logical_block_type& logical_tile : device_ctx.logical_block_types) { + for (const t_logical_block_type& logical_tile : + device_ctx.logical_block_types) { /* Bypass empty pb_graph */ if (nullptr == logical_tile.pb_graph_head) { continue; } - print_spice_logical_tile_netlist(netlist_manager, - module_manager, - device_annotation, - subckt_dir, - logical_tile.pb_graph_head, - verbose); + print_spice_logical_tile_netlist(netlist_manager, module_manager, + device_annotation, subckt_dir, + logical_tile.pb_graph_head, verbose); } VTR_LOG("Writing logical tiles..."); VTR_LOG("Done\n"); @@ -383,7 +381,8 @@ void print_spice_grids(NetlistManager& netlist_manager, */ VTR_LOG("Building physical tiles..."); VTR_LOGV(verbose, "\n"); - for (const t_physical_tile_type& physical_tile : device_ctx.physical_tile_types) { + for (const t_physical_tile_type& physical_tile : + device_ctx.physical_tile_types) { /* Bypass empty type or nullptr */ if (true == is_empty_type(&physical_tile)) { continue; @@ -392,27 +391,23 @@ void print_spice_grids(NetlistManager& netlist_manager, * We will search the grids and see where the I/O blocks are located: * - If a I/O block locates on border sides of FPGA fabric: * i.e., one or more from {TOP, RIGHT, BOTTOM, LEFT}, - * we will generate one module for each border side + * we will generate one module for each border side * - If a I/O block locates in the center of FPGA fabric: - * we will generate one module with NUM_SIDES (same treatment as regular grids) + * we will generate one module with NUM_SIDES (same treatment as regular + * grids) */ - std::set io_type_sides = find_physical_io_tile_located_sides(device_ctx.grid, - &physical_tile); + std::set io_type_sides = + find_physical_io_tile_located_sides(device_ctx.grid, &physical_tile); for (const e_side& io_type_side : io_type_sides) { - print_spice_physical_tile_netlist(netlist_manager, - module_manager, - subckt_dir, - &physical_tile, + print_spice_physical_tile_netlist(netlist_manager, module_manager, + subckt_dir, &physical_tile, io_type_side); - } + } continue; } else { /* For CLB and heterogenenous blocks */ - print_spice_physical_tile_netlist(netlist_manager, - module_manager, - subckt_dir, - &physical_tile, - NUM_SIDES); + print_spice_physical_tile_netlist(netlist_manager, module_manager, + subckt_dir, &physical_tile, NUM_SIDES); } } VTR_LOG("Building physical tiles..."); diff --git a/openfpga/src/fpga_spice/spice_grid.h b/openfpga/src/fpga_spice/spice_grid.h index 5f45e2d61..8ede2b253 100644 --- a/openfpga/src/fpga_spice/spice_grid.h +++ b/openfpga/src/fpga_spice/spice_grid.h @@ -5,9 +5,10 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "vpr_context.h" + #include "module_manager.h" #include "netlist_manager.h" +#include "vpr_context.h" #include "vpr_device_annotation.h" /******************************************************************** @@ -18,12 +19,10 @@ namespace openfpga { void print_spice_grids(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const std::string& subckt_dir, - const bool& verbose); - + const ModuleManager& module_manager, + const DeviceContext& device_ctx, + const VprDeviceAnnotation& device_annotation, + const std::string& subckt_dir, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_spice/spice_logic_gate.cpp b/openfpga/src/fpga_spice/spice_logic_gate.cpp index 6eba3da7a..a584d8ea0 100644 --- a/openfpga/src/fpga_spice/spice_logic_gate.cpp +++ b/openfpga/src/fpga_spice/spice_logic_gate.cpp @@ -1,11 +1,11 @@ /************************************************ - * This file includes functions on + * This file includes functions on * outputting SPICE netlists for logic gates: * - N-input AND gate * - N-input OR gate ***********************************************/ -#include #include +#include #include /* Headers from vtrutil library */ @@ -16,14 +16,12 @@ #include "command_exit_codes.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - #include "circuit_library_utils.h" - +#include "openfpga_digest.h" #include "spice_constants.h" -#include "spice_writer_utils.h" -#include "spice_transistor_wrapper.h" #include "spice_logic_gate.h" +#include "spice_transistor_wrapper.h" +#include "spice_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -64,64 +62,64 @@ int print_spice_and_gate_subckt(std::fstream& fp, const CircuitModelId& circuit_model, const TechnologyLibrary& tech_lib, const TechnologyModelId& tech_model) { - - if (false == valid_file_stream(fp)) { + if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } /* Find the input and output ports: - * we do NOT support global ports here, + * we do NOT support global ports here, * it should be handled in another type of inverter subckt (power-gated) */ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); /* Make sure: - * There are at least 2 input ports and 1 output port, + * There are at least 2 input ports and 1 output port, * each size of which is 1 */ VTR_ASSERT(2 <= input_ports.size()); for (const auto& input_port : input_ports) { - VTR_ASSERT(1 == circuit_lib.port_size(input_port)); + VTR_ASSERT(1 == circuit_lib.port_size(input_port)); } - VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + VTR_ASSERT((1 == output_ports.size()) && + (1 == circuit_lib.port_size(output_ports[0]))); int status = CMD_EXEC_SUCCESS; /* Print the inverter subckt definition */ - print_spice_subckt_definition(fp, module_manager, module_id); + print_spice_subckt_definition(fp, module_manager, module_id); /* Consider use size/bin to compact layout: * Try to size transistors to the max width for each bin - * The last bin may not reach the max width + * The last bin may not reach the max width */ - float regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); - float total_pmos_width = 1. /* TODO: allow users to define gate strength */ - * tech_lib.model_pn_ratio(tech_model) - * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float regular_pmos_bin_width = + tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float total_pmos_width = + 1. /* TODO: allow users to define gate strength */ + * tech_lib.model_pn_ratio(tech_model) * + tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); int num_pmos_bins = std::ceil(total_pmos_width / regular_pmos_bin_width); - float last_pmos_bin_width = std::fmod(total_pmos_width, regular_pmos_bin_width); - + float last_pmos_bin_width = + std::fmod(total_pmos_width, regular_pmos_bin_width); /* Output the PMOS network */ for (const auto& input_port : input_ports) { - for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { + for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { float curr_bin_width = regular_pmos_bin_width; /* For last bin, we need an irregular width */ - if ((ibin == num_pmos_bins - 1) - && (0. != last_pmos_bin_width)) { + if ((ibin == num_pmos_bins - 1) && (0. != last_pmos_bin_width)) { curr_bin_width = last_pmos_bin_width; } - status = print_spice_generic_pmos_modeling(fp, - std::to_string(ibin), - std::string(SPICE_SUBCKT_VDD_PORT_NAME), - circuit_lib.port_prefix(input_port), - circuit_lib.port_prefix(output_ports[0]), - tech_lib, - tech_model, - curr_bin_width); + status = print_spice_generic_pmos_modeling( + fp, std::to_string(ibin), std::string(SPICE_SUBCKT_VDD_PORT_NAME), + circuit_lib.port_prefix(input_port), + circuit_lib.port_prefix(output_ports[0]), tech_lib, tech_model, + curr_bin_width); if (CMD_EXEC_FATAL_ERROR == status) { return status; } @@ -130,57 +128,61 @@ int print_spice_and_gate_subckt(std::fstream& fp, /* Consider use size/bin to compact layout: * Try to size transistors to the max width for each bin - * The last bin may not reach the max width + * The last bin may not reach the max width */ - float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); - float total_nmos_width = 1. /* TODO: allow users to define gate strength */ - * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float regular_nmos_bin_width = + tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float total_nmos_width = + 1. /* TODO: allow users to define gate strength */ + * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width); - float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width); + float last_nmos_bin_width = + std::fmod(total_nmos_width, regular_nmos_bin_width); /* Output the NMOS network */ for (size_t input_id = 0; input_id < input_ports.size(); ++input_id) { - for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { + for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { float curr_bin_width = regular_nmos_bin_width; /* For last bin, we need an irregular width */ - if ((ibin == num_nmos_bins - 1) - && (0. != last_nmos_bin_width)) { + if ((ibin == num_nmos_bins - 1) && (0. != last_nmos_bin_width)) { curr_bin_width = last_nmos_bin_width; } - /* Depending on the input id, we assign different port names to source/drain */ + /* Depending on the input id, we assign different port names to + * source/drain */ std::string source_port_name; std::string drain_port_name; if (0 == input_id) { - /* First transistor should connect to the output port and an internal node */ + /* First transistor should connect to the output port and an internal + * node */ source_port_name = circuit_lib.port_prefix(output_ports[0]); - drain_port_name = std::string("internal_node") + std::to_string(input_id); + drain_port_name = + std::string("internal_node") + std::to_string(input_id); } else if (input_id == input_ports.size() - 1) { /* Last transistor should connect to an internal node and GND */ - source_port_name = std::string("internal_node") + std::to_string(input_id - 1); + source_port_name = + std::string("internal_node") + std::to_string(input_id - 1); drain_port_name = std::string(SPICE_SUBCKT_GND_PORT_NAME); } else { - /* Other transistors should connect to two internal nodes */ - source_port_name = std::string("internal_node") + std::to_string(input_id - 1); - drain_port_name = std::string("internal_node") + std::to_string(input_id); + /* Other transistors should connect to two internal nodes */ + source_port_name = + std::string("internal_node") + std::to_string(input_id - 1); + drain_port_name = + std::string("internal_node") + std::to_string(input_id); } - status = print_spice_generic_nmos_modeling(fp, - std::to_string(ibin), - source_port_name, - circuit_lib.port_prefix(input_ports[input_id]), - drain_port_name, - tech_lib, - tech_model, - curr_bin_width); + status = print_spice_generic_nmos_modeling( + fp, std::to_string(ibin), source_port_name, + circuit_lib.port_prefix(input_ports[input_id]), drain_port_name, + tech_lib, tech_model, curr_bin_width); if (CMD_EXEC_FATAL_ERROR == status) { return status; } } } - print_spice_subckt_end(fp, module_manager.module_name(module_id)); + print_spice_subckt_end(fp, module_manager.module_name(module_id)); return status; } @@ -222,82 +224,87 @@ int print_spice_or_gate_subckt(std::fstream& fp, const CircuitModelId& circuit_model, const TechnologyLibrary& tech_lib, const TechnologyModelId& tech_model) { - - if (false == valid_file_stream(fp)) { + if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } /* Find the input and output ports: - * we do NOT support global ports here, + * we do NOT support global ports here, * it should be handled in another type of inverter subckt (power-gated) */ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); /* Make sure: - * There are at least 2 input ports and 1 output port, + * There are at least 2 input ports and 1 output port, * each size of which is 1 */ VTR_ASSERT(2 <= input_ports.size()); for (const auto& input_port : input_ports) { - VTR_ASSERT(1 == circuit_lib.port_size(input_port)); + VTR_ASSERT(1 == circuit_lib.port_size(input_port)); } - VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + VTR_ASSERT((1 == output_ports.size()) && + (1 == circuit_lib.port_size(output_ports[0]))); int status = CMD_EXEC_SUCCESS; /* Print the inverter subckt definition */ - print_spice_subckt_definition(fp, module_manager, module_id); + print_spice_subckt_definition(fp, module_manager, module_id); /* Consider use size/bin to compact layout: * Try to size transistors to the max width for each bin - * The last bin may not reach the max width + * The last bin may not reach the max width */ - float regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); - float total_pmos_width = 1. /* TODO: allow users to define gate strength */ - * tech_lib.model_pn_ratio(tech_model) - * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float regular_pmos_bin_width = + tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float total_pmos_width = + 1. /* TODO: allow users to define gate strength */ + * tech_lib.model_pn_ratio(tech_model) * + tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); int num_pmos_bins = std::ceil(total_pmos_width / regular_pmos_bin_width); - float last_pmos_bin_width = std::fmod(total_pmos_width, regular_pmos_bin_width); - + float last_pmos_bin_width = + std::fmod(total_pmos_width, regular_pmos_bin_width); /* Output the PMOS network */ for (size_t input_id = 0; input_id < input_ports.size(); ++input_id) { - for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { + for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { float curr_bin_width = regular_pmos_bin_width; /* For last bin, we need an irregular width */ - if ((ibin == num_pmos_bins - 1) - && (0. != last_pmos_bin_width)) { + if ((ibin == num_pmos_bins - 1) && (0. != last_pmos_bin_width)) { curr_bin_width = last_pmos_bin_width; } - /* Depending on the input id, we assign different port names to source/drain */ + /* Depending on the input id, we assign different port names to + * source/drain */ std::string source_port_name; std::string drain_port_name; if (0 == input_id) { - /* First transistor should connect to the output port and an internal node */ + /* First transistor should connect to the output port and an internal + * node */ source_port_name = circuit_lib.port_prefix(output_ports[0]); - drain_port_name = std::string("internal_node") + std::to_string(input_id); + drain_port_name = + std::string("internal_node") + std::to_string(input_id); } else if (input_id == input_ports.size() - 1) { /* Last transistor should connect to an internal node and GND */ - source_port_name = std::string("internal_node") + std::to_string(input_id - 1); + source_port_name = + std::string("internal_node") + std::to_string(input_id - 1); drain_port_name = std::string(SPICE_SUBCKT_VDD_PORT_NAME); } else { - /* Other transistors should connect to two internal nodes */ - source_port_name = std::string("internal_node") + std::to_string(input_id - 1); - drain_port_name = std::string("internal_node") + std::to_string(input_id); + /* Other transistors should connect to two internal nodes */ + source_port_name = + std::string("internal_node") + std::to_string(input_id - 1); + drain_port_name = + std::string("internal_node") + std::to_string(input_id); } - status = print_spice_generic_pmos_modeling(fp, - std::to_string(ibin), - source_port_name, - circuit_lib.port_prefix(input_ports[input_id]), - drain_port_name, - tech_lib, - tech_model, - curr_bin_width); + status = print_spice_generic_pmos_modeling( + fp, std::to_string(ibin), source_port_name, + circuit_lib.port_prefix(input_ports[input_id]), drain_port_name, + tech_lib, tech_model, curr_bin_width); if (CMD_EXEC_FATAL_ERROR == status) { return status; } @@ -306,39 +313,38 @@ int print_spice_or_gate_subckt(std::fstream& fp, /* Consider use size/bin to compact layout: * Try to size transistors to the max width for each bin - * The last bin may not reach the max width + * The last bin may not reach the max width */ - float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); - float total_nmos_width = 1. /* TODO: allow users to define gate strength */ - * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float regular_nmos_bin_width = + tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float total_nmos_width = + 1. /* TODO: allow users to define gate strength */ + * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width); - float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width); + float last_nmos_bin_width = + std::fmod(total_nmos_width, regular_nmos_bin_width); /* Output the NMOS network */ for (const auto& input_port : input_ports) { - for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { + for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { float curr_bin_width = regular_nmos_bin_width; /* For last bin, we need an irregular width */ - if ((ibin == num_nmos_bins - 1) - && (0. != last_nmos_bin_width)) { + if ((ibin == num_nmos_bins - 1) && (0. != last_nmos_bin_width)) { curr_bin_width = last_nmos_bin_width; } - status = print_spice_generic_nmos_modeling(fp, - std::to_string(ibin), - circuit_lib.port_prefix(output_ports[0]), - circuit_lib.port_prefix(input_port), - std::string(SPICE_SUBCKT_GND_PORT_NAME), - tech_lib, - tech_model, - curr_bin_width); + status = print_spice_generic_nmos_modeling( + fp, std::to_string(ibin), circuit_lib.port_prefix(output_ports[0]), + circuit_lib.port_prefix(input_port), + std::string(SPICE_SUBCKT_GND_PORT_NAME), tech_lib, tech_model, + curr_bin_width); if (CMD_EXEC_FATAL_ERROR == status) { return status; } } } - print_spice_subckt_end(fp, module_manager.module_name(module_id)); + print_spice_subckt_end(fp, module_manager.module_name(module_id)); return status; } diff --git a/openfpga/src/fpga_spice/spice_logic_gate.h b/openfpga/src/fpga_spice/spice_logic_gate.h index 4a72c803f..e9d9ab466 100644 --- a/openfpga/src/fpga_spice/spice_logic_gate.h +++ b/openfpga/src/fpga_spice/spice_logic_gate.h @@ -4,10 +4,11 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include #include -#include "module_manager.h" +#include + #include "circuit_library.h" +#include "module_manager.h" #include "technology_library.h" /******************************************************************** diff --git a/openfpga/src/fpga_spice/spice_lut.cpp b/openfpga/src/fpga_spice/spice_lut.cpp index 2d68d014b..718bdc7cb 100644 --- a/openfpga/src/fpga_spice/spice_lut.cpp +++ b/openfpga/src/fpga_spice/spice_lut.cpp @@ -1,8 +1,8 @@ /******************************************************************** * This file includes functions to generate SPICE subcircuits for LUTs ********************************************************************/ -#include #include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" @@ -13,23 +13,20 @@ /* Headers from openfpgashell library */ #include "command_exit_codes.h" - -#include "mux_graph.h" #include "module_manager.h" +#include "mux_graph.h" #include "mux_utils.h" - #include "openfpga_naming.h" - #include "spice_constants.h" -#include "spice_writer_utils.h" -#include "spice_subckt_writer.h" #include "spice_lut.h" +#include "spice_subckt_writer.h" +#include "spice_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { -/******************************************************************** - * Print SPICE modules for the Look-Up Tables (LUTs) +/******************************************************************** + * Print SPICE modules for the Look-Up Tables (LUTs) * in the circuit library ********************************************************************/ int print_spice_submodule_luts(NetlistManager& netlist_manager, @@ -45,23 +42,23 @@ int print_spice_submodule_luts(NetlistManager& netlist_manager, /* Create the file stream */ fp.open(spice_fname, std::fstream::out | std::fstream::trunc); /* Check if the file stream if valid or not */ - check_file_stream(spice_fname.c_str(), fp); + check_file_stream(spice_fname.c_str(), fp); /* Create file */ - VTR_LOG("Writing SPICE netlist for LUTs '%s'...", - spice_fname.c_str()); + VTR_LOG("Writing SPICE netlist for LUTs '%s'...", spice_fname.c_str()); - print_spice_file_header(fp, "Look-Up Tables"); + print_spice_file_header(fp, "Look-Up Tables"); /* Search for each LUT circuit model */ for (const auto& lut_model : circuit_lib.models()) { /* Bypass user-defined and non-LUT modules */ - if ( (!circuit_lib.model_spice_netlist(lut_model).empty()) - || (CIRCUIT_MODEL_LUT != circuit_lib.model_type(lut_model)) ) { + if ((!circuit_lib.model_spice_netlist(lut_model).empty()) || + (CIRCUIT_MODEL_LUT != circuit_lib.model_type(lut_model))) { continue; } /* Find the module id */ - ModuleId lut_module = module_manager.find_module(circuit_lib.model_name(lut_model)); + ModuleId lut_module = + module_manager.find_module(circuit_lib.model_name(lut_model)); VTR_ASSERT(true == module_manager.valid_module_id(lut_module)); write_spice_subckt_to_file(fp, module_manager, lut_module); } diff --git a/openfpga/src/fpga_spice/spice_memory.cpp b/openfpga/src/fpga_spice/spice_memory.cpp index e1da21d28..373ba7164 100644 --- a/openfpga/src/fpga_spice/spice_memory.cpp +++ b/openfpga/src/fpga_spice/spice_memory.cpp @@ -1,10 +1,10 @@ /********************************************************************* - * This file includes functions to generate SPICE sub-circuits for + * This file includes functions to generate SPICE sub-circuits for * the memories that are affiliated to multiplexers and other programmable * circuit models, such as IOPADs, LUTs, etc. ********************************************************************/ -#include #include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" @@ -14,86 +14,85 @@ #include "openfpga_digest.h" /* Headers from openfpgashell library */ -#include "command_exit_codes.h" - -#include "mux_graph.h" -#include "module_manager.h" #include "circuit_library_utils.h" +#include "command_exit_codes.h" +#include "module_manager.h" +#include "mux_graph.h" #include "mux_utils.h" - #include "openfpga_naming.h" - #include "spice_constants.h" -#include "spice_writer_utils.h" -#include "spice_subckt_writer.h" #include "spice_memory.h" +#include "spice_subckt_writer.h" +#include "spice_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { /********************************************************************* * Generate Verilog modules for the memories that are used - * by multiplexers + * by multiplexers * * +----------------+ * mem_in --->| Memory Module |---> mem_out * +----------------+ - * | | ... | | + * | | ... | | * v v v v SRAM ports of multiplexer * +---------------------+ * in--->| Multiplexer Module |---> out * +---------------------+ ********************************************************************/ -static -void print_spice_mux_memory_module(const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - std::fstream& fp, - const CircuitModelId& mux_model, - const MuxGraph& mux_graph) { - /* Multiplexers built with different technology is in different organization */ +static void print_spice_mux_memory_module(const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + std::fstream& fp, + const CircuitModelId& mux_model, + const MuxGraph& mux_graph) { + /* Multiplexers built with different technology is in different organization + */ switch (circuit_lib.design_tech_type(mux_model)) { - case CIRCUIT_MODEL_DESIGN_CMOS: { - /* Generate module name */ - std::string module_name = generate_mux_subckt_name(circuit_lib, mux_model, - find_mux_num_datapath_inputs(circuit_lib, mux_model, mux_graph.num_inputs()), - std::string(SPICE_MEM_POSTFIX)); - ModuleId mem_module = module_manager.find_module(module_name); - VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); - /* Write the module content in Verilog format */ - write_spice_subckt_to_file(fp, module_manager, mem_module); + case CIRCUIT_MODEL_DESIGN_CMOS: { + /* Generate module name */ + std::string module_name = generate_mux_subckt_name( + circuit_lib, mux_model, + find_mux_num_datapath_inputs(circuit_lib, mux_model, + mux_graph.num_inputs()), + std::string(SPICE_MEM_POSTFIX)); + ModuleId mem_module = module_manager.find_module(module_name); + VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); + /* Write the module content in Verilog format */ + write_spice_subckt_to_file(fp, module_manager, mem_module); - /* Add an empty line as a splitter */ - fp << std::endl; - break; - } - case CIRCUIT_MODEL_DESIGN_RRAM: - /* We do not need a memory submodule for RRAM MUX, - * RRAM are embedded in the datapath - * TODO: generate local encoders for RRAM-based multiplexers here!!! - */ - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid design technology of multiplexer '%s'\n", - circuit_lib.model_name(mux_model).c_str()); - exit(1); + /* Add an empty line as a splitter */ + fp << std::endl; + break; + } + case CIRCUIT_MODEL_DESIGN_RRAM: + /* We do not need a memory submodule for RRAM MUX, + * RRAM are embedded in the datapath + * TODO: generate local encoders for RRAM-based multiplexers here!!! + */ + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid design technology of multiplexer '%s'\n", + circuit_lib.model_name(mux_model).c_str()); + exit(1); } } /********************************************************************* - * Generate Verilog modules for + * Generate Verilog modules for * the memories that are affiliated to multiplexers and other programmable * circuit models, such as IOPADs, LUTs, etc. * - * We keep the memory modules separated from the multiplexers and other + * We keep the memory modules separated from the multiplexers and other * programmable circuit models, for the sake of supporting * various configuration schemes. * By following such organiztion, the Verilog modules of the circuit models * implements the functionality (circuit logic) only, while the memory Verilog * modules implements the memory circuits as well as configuration protocols. * For example, the local decoders of multiplexers are implemented in the - * memory modules. - * Take another example, the memory circuit can implement the scan-chain or + * memory modules. + * Take another example, the memory circuit can implement the scan-chain or * memory-bank organization for the memories. ********************************************************************/ int print_spice_submodule_memories(NetlistManager& netlist_manager, @@ -104,7 +103,8 @@ int print_spice_submodule_memories(NetlistManager& netlist_manager, int status = CMD_EXEC_SUCCESS; /* Plug in with the mux subckt */ - std::string spice_fname(submodule_dir + std::string(MEMORIES_SPICE_FILE_NAME)); + std::string spice_fname(submodule_dir + + std::string(MEMORIES_SPICE_FILE_NAME)); /* Create the file stream */ std::fstream fp; @@ -112,30 +112,31 @@ int print_spice_submodule_memories(NetlistManager& netlist_manager, check_file_stream(spice_fname.c_str(), fp); - /* Print out debugging information for if the file is not opened/created properly */ - VTR_LOG("Writing SPICE netlist for memories '%s' ...", - spice_fname.c_str()); + /* Print out debugging information for if the file is not opened/created + * properly */ + VTR_LOG("Writing SPICE netlist for memories '%s' ...", spice_fname.c_str()); - print_spice_file_header(fp, "Memories used in FPGA"); + print_spice_file_header(fp, "Memories used in FPGA"); /* Create the memory circuits for the multiplexer */ for (auto mux : mux_lib.muxes()) { const MuxGraph& mux_graph = mux_lib.mux_graph(mux); - CircuitModelId mux_model = mux_lib.mux_circuit_model(mux); - /* Bypass the non-MUX circuit models (i.e., LUTs). - * They should be handled in a different way + CircuitModelId mux_model = mux_lib.mux_circuit_model(mux); + /* Bypass the non-MUX circuit models (i.e., LUTs). + * They should be handled in a different way * Memory circuits of LUT includes both regular and mode-select ports */ if (CIRCUIT_MODEL_MUX != circuit_lib.model_type(mux_model)) { continue; } /* Create a Verilog module for the memories used by the multiplexer */ - print_spice_mux_memory_module(module_manager, circuit_lib, fp, mux_model, mux_graph); + print_spice_mux_memory_module(module_manager, circuit_lib, fp, mux_model, + mux_graph); } /* Create the memory circuits for non-MUX circuit models. * In this case, the memory modules are designed to interface - * the mode-select ports + * the mode-select ports */ for (const auto& model : circuit_lib.models()) { /* Bypass MUXes, they have already been considered */ @@ -143,13 +144,14 @@ int print_spice_submodule_memories(NetlistManager& netlist_manager, continue; } /* Bypass those modules without any SRAM ports */ - std::vector sram_ports = circuit_lib.model_ports_by_type(model, CIRCUIT_MODEL_PORT_SRAM, true); + std::vector sram_ports = + circuit_lib.model_ports_by_type(model, CIRCUIT_MODEL_PORT_SRAM, true); if (0 == sram_ports.size()) { continue; } /* Find the name of memory module */ /* Get the total number of SRAMs */ - size_t num_mems = 0; + size_t num_mems = 0; for (const auto& port : sram_ports) { num_mems += circuit_lib.port_size(port); } @@ -159,17 +161,19 @@ int print_spice_submodule_memories(NetlistManager& netlist_manager, CircuitModelId sram_model = circuit_lib.port_tri_state_model(port); VTR_ASSERT(CircuitModelId::INVALID() != sram_model); /* Found in the vector of sram_models, do not update and go to the next */ - if (sram_models.end() != std::find(sram_models.begin(), sram_models.end(), sram_model)) { + if (sram_models.end() != + std::find(sram_models.begin(), sram_models.end(), sram_model)) { continue; } /* sram_model not found in the vector, update the sram_models */ sram_models.push_back(sram_model); } /* Should have only 1 SRAM model */ - VTR_ASSERT( 1 == sram_models.size() ); - + VTR_ASSERT(1 == sram_models.size()); + /* Create the module name for the memory block */ - std::string module_name = generate_memory_module_name(circuit_lib, model, sram_models[0], std::string(SPICE_MEM_POSTFIX)); + std::string module_name = generate_memory_module_name( + circuit_lib, model, sram_models[0], std::string(SPICE_MEM_POSTFIX)); ModuleId mem_module = module_manager.find_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); diff --git a/openfpga/src/fpga_spice/spice_memory.h b/openfpga/src/fpga_spice/spice_memory.h index 48eaf5651..2b4011ad2 100644 --- a/openfpga/src/fpga_spice/spice_memory.h +++ b/openfpga/src/fpga_spice/spice_memory.h @@ -7,9 +7,9 @@ #include #include "circuit_library.h" +#include "module_manager.h" #include "mux_graph.h" #include "mux_library.h" -#include "module_manager.h" #include "netlist_manager.h" /******************************************************************** diff --git a/openfpga/src/fpga_spice/spice_mux.cpp b/openfpga/src/fpga_spice/spice_mux.cpp index 147387848..f72209b75 100644 --- a/openfpga/src/fpga_spice/spice_mux.cpp +++ b/openfpga/src/fpga_spice/spice_mux.cpp @@ -2,12 +2,12 @@ * This file includes functions to generate * SPICE subcircuits for multiplexers. * including both fundamental submodules - * such as a branch in a multiplexer + * such as a branch in a multiplexer * and the full multiplexer **********************************************/ -#include -#include #include +#include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" @@ -23,74 +23,73 @@ #include "openfpga_digest.h" /* Headers from openfpgashell library */ -#include "command_exit_codes.h" - -#include "mux_graph.h" -#include "module_manager.h" -#include "mux_utils.h" #include "circuit_library_utils.h" +#include "command_exit_codes.h" #include "decoder_library_utils.h" - +#include "module_manager.h" +#include "mux_graph.h" +#include "mux_utils.h" #include "openfpga_naming.h" - #include "spice_constants.h" -#include "spice_writer_utils.h" -#include "spice_subckt_writer.h" #include "spice_mux.h" +#include "spice_subckt_writer.h" +#include "spice_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { /*********************************************** - * Generate SPICE modeling for an branch circuit - * for a multiplexer with the given size + * Generate SPICE modeling for an branch circuit + * for a multiplexer with the given size **********************************************/ -static -void generate_spice_mux_branch_subckt(const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - std::fstream& fp, - const CircuitModelId& mux_model, - const MuxGraph& mux_graph, - std::map& branch_mux_module_is_outputted) { - std::string module_name = generate_mux_branch_subckt_name(circuit_lib, mux_model, mux_graph.num_inputs(), mux_graph.num_memory_bits(), SPICE_MUX_BASIS_POSTFIX); +static void generate_spice_mux_branch_subckt( + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + std::fstream& fp, const CircuitModelId& mux_model, const MuxGraph& mux_graph, + std::map& branch_mux_module_is_outputted) { + std::string module_name = generate_mux_branch_subckt_name( + circuit_lib, mux_model, mux_graph.num_inputs(), mux_graph.num_memory_bits(), + SPICE_MUX_BASIS_POSTFIX); /* Skip outputting if the module has already been outputted */ auto result = branch_mux_module_is_outputted.find(module_name); - if ((result != branch_mux_module_is_outputted.end()) - && (true == result->second)) { + if ((result != branch_mux_module_is_outputted.end()) && + (true == result->second)) { return; } - /* Multiplexers built with different technology is in different organization */ + /* Multiplexers built with different technology is in different organization + */ switch (circuit_lib.design_tech_type(mux_model)) { - case CIRCUIT_MODEL_DESIGN_CMOS: { - /* Skip module writing if the branch subckt is a standard cell! */ - if (true == circuit_lib.valid_model_id(circuit_lib.model(module_name))) { - /* This model must be a MUX2 gate */ - VTR_ASSERT(CIRCUIT_MODEL_GATE == circuit_lib.model_type(circuit_lib.model(module_name))); - VTR_ASSERT(CIRCUIT_MODEL_GATE_MUX2 == circuit_lib.gate_type(circuit_lib.model(module_name))); + case CIRCUIT_MODEL_DESIGN_CMOS: { + /* Skip module writing if the branch subckt is a standard cell! */ + if (true == circuit_lib.valid_model_id(circuit_lib.model(module_name))) { + /* This model must be a MUX2 gate */ + VTR_ASSERT(CIRCUIT_MODEL_GATE == + circuit_lib.model_type(circuit_lib.model(module_name))); + VTR_ASSERT(CIRCUIT_MODEL_GATE_MUX2 == + circuit_lib.gate_type(circuit_lib.model(module_name))); + break; + } + /* Structural verilog can be easily generated by module writer */ + ModuleId mux_module = module_manager.find_module(module_name); + VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); + write_spice_subckt_to_file(fp, module_manager, mux_module); + /* Add an empty line as a splitter */ + fp << std::endl; break; } - /* Structural verilog can be easily generated by module writer */ - ModuleId mux_module = module_manager.find_module(module_name); - VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); - write_spice_subckt_to_file(fp, module_manager, mux_module); - /* Add an empty line as a splitter */ - fp << std::endl; - break; - } - case CIRCUIT_MODEL_DESIGN_RRAM: - /* TODO: RRAM-based Multiplexer SPICE module generation */ - VTR_LOGF_ERROR(__FILE__, __LINE__, - "RRAM multiplexer '%s' is not supported yet\n", - circuit_lib.model_name(mux_model).c_str()); - exit(1); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid design technology of multiplexer '%s'\n", - circuit_lib.model_name(mux_model).c_str()); - exit(1); + case CIRCUIT_MODEL_DESIGN_RRAM: + /* TODO: RRAM-based Multiplexer SPICE module generation */ + VTR_LOGF_ERROR(__FILE__, __LINE__, + "RRAM multiplexer '%s' is not supported yet\n", + circuit_lib.model_name(mux_model).c_str()); + exit(1); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid design technology of multiplexer '%s'\n", + circuit_lib.model_name(mux_model).c_str()); + exit(1); } /* Record that this branch module has been outputted */ @@ -98,42 +97,44 @@ void generate_spice_mux_branch_subckt(const ModuleManager& module_manager, } /*********************************************** - * Generate SPICE modeling for a multiplexer + * Generate SPICE modeling for a multiplexer * with the given graph-level description **********************************************/ -static -void generate_spice_mux_subckt(const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - std::fstream& fp, - const CircuitModelId& mux_model, - const MuxGraph& mux_graph) { - std::string module_name = generate_mux_subckt_name(circuit_lib, mux_model, - find_mux_num_datapath_inputs(circuit_lib, mux_model, mux_graph.num_inputs()), - std::string("")); - - /* Multiplexers built with different technology is in different organization */ +static void generate_spice_mux_subckt(const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + std::fstream& fp, + const CircuitModelId& mux_model, + const MuxGraph& mux_graph) { + std::string module_name = + generate_mux_subckt_name(circuit_lib, mux_model, + find_mux_num_datapath_inputs( + circuit_lib, mux_model, mux_graph.num_inputs()), + std::string("")); + + /* Multiplexers built with different technology is in different organization + */ switch (circuit_lib.design_tech_type(mux_model)) { - case CIRCUIT_MODEL_DESIGN_CMOS: { - /* Use Verilog writer to print the module to file */ - ModuleId mux_module = module_manager.find_module(module_name); - VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); - write_spice_subckt_to_file(fp, module_manager, mux_module); - /* Add an empty line as a splitter */ - fp << std::endl; - break; - } - case CIRCUIT_MODEL_DESIGN_RRAM: - /* TODO: RRAM-based Multiplexer SPICE module generation */ - VTR_LOGF_ERROR(__FILE__, __LINE__, - "RRAM multiplexer '%s' is not supported yet\n", - circuit_lib.model_name(mux_model).c_str()); - exit(1); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid design technology of multiplexer '%s'\n", - circuit_lib.model_name(mux_model).c_str()); - exit(1); + case CIRCUIT_MODEL_DESIGN_CMOS: { + /* Use Verilog writer to print the module to file */ + ModuleId mux_module = module_manager.find_module(module_name); + VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); + write_spice_subckt_to_file(fp, module_manager, mux_module); + /* Add an empty line as a splitter */ + fp << std::endl; + break; + } + case CIRCUIT_MODEL_DESIGN_RRAM: + /* TODO: RRAM-based Multiplexer SPICE module generation */ + VTR_LOGF_ERROR(__FILE__, __LINE__, + "RRAM multiplexer '%s' is not supported yet\n", + circuit_lib.model_name(mux_model).c_str()); + exit(1); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid design technology of multiplexer '%s'\n", + circuit_lib.model_name(mux_model).c_str()); + exit(1); } } @@ -141,15 +142,14 @@ void generate_spice_mux_subckt(const ModuleManager& module_manager, * Generate primitive SPICE subcircuits for all the unique * multiplexers in the FPGA device **********************************************/ -static -int print_spice_submodule_mux_primitives(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const std::string& submodule_dir) { +static int print_spice_submodule_mux_primitives( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, + const std::string& submodule_dir) { int status = CMD_EXEC_SUCCESS; - std::string spice_fname(submodule_dir + std::string(MUX_PRIMITIVES_SPICE_FILE_NAME)); + std::string spice_fname(submodule_dir + + std::string(MUX_PRIMITIVES_SPICE_FILE_NAME)); /* Create the file stream */ std::fstream fp; @@ -157,27 +157,31 @@ int print_spice_submodule_mux_primitives(NetlistManager& netlist_manager, check_file_stream(spice_fname.c_str(), fp); - /* Print out debugging information for if the file is not opened/created properly */ + /* Print out debugging information for if the file is not opened/created + * properly */ VTR_LOG("Writing SPICE netlist for Multiplexer primitives '%s' ...", - spice_fname.c_str()); + spice_fname.c_str()); - print_spice_file_header(fp, "Multiplexer primitives"); + print_spice_file_header(fp, "Multiplexer primitives"); /* Record if the branch module has been outputted - * since different sizes of routing multiplexers may share the same branch module + * since different sizes of routing multiplexers may share the same branch + * module */ std::map branch_mux_module_is_outputted; - /* Generate basis sub-circuit for unique branches shared by the multiplexers */ + /* Generate basis sub-circuit for unique branches shared by the multiplexers + */ for (auto mux : mux_lib.muxes()) { const MuxGraph& mux_graph = mux_lib.mux_graph(mux); - CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); + CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); /* Create a mux graph for the branch circuit */ - std::vector branch_mux_graphs = mux_graph.build_mux_branch_graphs(); + std::vector branch_mux_graphs = + mux_graph.build_mux_branch_graphs(); /* Create branch circuits, which are N:1 one-level or 2:1 tree-like MUXes */ for (auto branch_mux_graph : branch_mux_graphs) { - generate_spice_mux_branch_subckt(module_manager, circuit_lib, fp, mux_circuit_model, - branch_mux_graph, + generate_spice_mux_branch_subckt(module_manager, circuit_lib, fp, + mux_circuit_model, branch_mux_graph, branch_mux_module_is_outputted); } } @@ -199,12 +203,10 @@ int print_spice_submodule_mux_primitives(NetlistManager& netlist_manager, * Generate top-level SPICE subcircuits for all the unique * multiplexers in the FPGA device **********************************************/ -static -int print_spice_submodule_mux_top_subckt(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const std::string& submodule_dir) { +static int print_spice_submodule_mux_top_subckt( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, + const std::string& submodule_dir) { int status = CMD_EXEC_SUCCESS; std::string spice_fname(submodule_dir + std::string(MUXES_SPICE_FILE_NAME)); @@ -215,18 +217,20 @@ int print_spice_submodule_mux_top_subckt(NetlistManager& netlist_manager, check_file_stream(spice_fname.c_str(), fp); - /* Print out debugging information for if the file is not opened/created properly */ + /* Print out debugging information for if the file is not opened/created + * properly */ VTR_LOG("Writing SPICE netlist for Multiplexers '%s' ...", - spice_fname.c_str()); + spice_fname.c_str()); - print_spice_file_header(fp, "Multiplexers"); + print_spice_file_header(fp, "Multiplexers"); /* Generate unique Verilog modules for the multiplexers */ for (auto mux : mux_lib.muxes()) { const MuxGraph& mux_graph = mux_lib.mux_graph(mux); - CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); + CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); /* Create MUX circuits */ - generate_spice_mux_subckt(module_manager, circuit_lib, fp, mux_circuit_model, mux_graph); + generate_spice_mux_subckt(module_manager, circuit_lib, fp, + mux_circuit_model, mux_graph); } /* Close the file stream */ @@ -258,21 +262,20 @@ int print_spice_submodule_muxes(NetlistManager& netlist_manager, const std::string& submodule_dir) { int status = CMD_EXEC_SUCCESS; - status = print_spice_submodule_mux_primitives(netlist_manager, module_manager, - mux_lib, circuit_lib, submodule_dir); + status = print_spice_submodule_mux_primitives( + netlist_manager, module_manager, mux_lib, circuit_lib, submodule_dir); if (CMD_EXEC_FATAL_ERROR == status) { return status; } - status = print_spice_submodule_mux_top_subckt(netlist_manager, module_manager, - mux_lib, circuit_lib, submodule_dir); + status = print_spice_submodule_mux_top_subckt( + netlist_manager, module_manager, mux_lib, circuit_lib, submodule_dir); if (CMD_EXEC_FATAL_ERROR == status) { return status; } - return status; } diff --git a/openfpga/src/fpga_spice/spice_mux.h b/openfpga/src/fpga_spice/spice_mux.h index a7658667e..0ce34ded4 100644 --- a/openfpga/src/fpga_spice/spice_mux.h +++ b/openfpga/src/fpga_spice/spice_mux.h @@ -8,9 +8,9 @@ #include #include "circuit_library.h" +#include "module_manager.h" #include "mux_graph.h" #include "mux_library.h" -#include "module_manager.h" #include "netlist_manager.h" /******************************************************************** diff --git a/openfpga/src/fpga_spice/spice_passgate.cpp b/openfpga/src/fpga_spice/spice_passgate.cpp index cf3702ba7..177da68d8 100644 --- a/openfpga/src/fpga_spice/spice_passgate.cpp +++ b/openfpga/src/fpga_spice/spice_passgate.cpp @@ -1,9 +1,9 @@ /************************************************ - * This file includes functions on + * This file includes functions on * outputting SPICE netlists for transmission-gates ***********************************************/ -#include #include +#include #include /* Headers from vtrutil library */ @@ -14,14 +14,12 @@ #include "command_exit_codes.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - #include "circuit_library_utils.h" - +#include "openfpga_digest.h" #include "spice_constants.h" -#include "spice_writer_utils.h" -#include "spice_transistor_wrapper.h" #include "spice_passgate.h" +#include "spice_transistor_wrapper.h" +#include "spice_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -38,73 +36,72 @@ namespace openfpga { * in -- ---out * *******************************************************************/ -static -int print_spice_pass_transistor_subckt(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& tech_model) { +static int print_spice_pass_transistor_subckt( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, const TechnologyLibrary& tech_lib, + const TechnologyModelId& tech_model) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } /* Find the input and output ports: - * we do NOT support global ports here, + * we do NOT support global ports here, * it should be handled in another type of inverter subckt (power-gated) */ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); /* Make sure: - * There is only 2 input port and 1 output port, + * There is only 2 input port and 1 output port, * each size of which is 1 */ VTR_ASSERT(2 == input_ports.size()); for (const auto& input_port : input_ports) { - VTR_ASSERT(1 == circuit_lib.port_size(input_port)); + VTR_ASSERT(1 == circuit_lib.port_size(input_port)); } - VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + VTR_ASSERT((1 == output_ports.size()) && + (1 == circuit_lib.port_size(output_ports[0]))); int status = CMD_EXEC_SUCCESS; /* Print the inverter subckt definition */ - print_spice_subckt_definition(fp, module_manager, module_id); + print_spice_subckt_definition(fp, module_manager, module_id); /* Consider use size/bin to compact layout: * Try to size transistors to the max width for each bin - * The last bin may not reach the max width + * The last bin may not reach the max width */ - float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); - float total_nmos_width = circuit_lib.pass_gate_logic_nmos_size(circuit_model) - * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float regular_nmos_bin_width = + tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float total_nmos_width = + circuit_lib.pass_gate_logic_nmos_size(circuit_model) * + tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width); - float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width); + float last_nmos_bin_width = + std::fmod(total_nmos_width, regular_nmos_bin_width); - for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { + for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { float curr_bin_width = regular_nmos_bin_width; /* For last bin, we need an irregular width */ - if ((ibin == num_nmos_bins - 1) - && (0. != last_nmos_bin_width)) { + if ((ibin == num_nmos_bins - 1) && (0. != last_nmos_bin_width)) { curr_bin_width = last_nmos_bin_width; } - status = print_spice_generic_nmos_modeling(fp, - std::to_string(ibin), - circuit_lib.port_prefix(input_ports[0]), - circuit_lib.port_prefix(input_ports[1]), - circuit_lib.port_prefix(output_ports[0]), - tech_lib, - tech_model, - curr_bin_width); + status = print_spice_generic_nmos_modeling( + fp, std::to_string(ibin), circuit_lib.port_prefix(input_ports[0]), + circuit_lib.port_prefix(input_ports[1]), + circuit_lib.port_prefix(output_ports[0]), tech_lib, tech_model, + curr_bin_width); if (CMD_EXEC_FATAL_ERROR == status) { return status; } } - print_spice_subckt_end(fp, module_manager.module_name(module_id)); + print_spice_subckt_end(fp, module_manager.module_name(module_id)); return status; } @@ -113,7 +110,7 @@ int print_spice_pass_transistor_subckt(std::fstream& fp, * Generate the SPICE subckt for a transmission gate * * Schematic - * + * * selb * | * o @@ -126,66 +123,65 @@ int print_spice_pass_transistor_subckt(std::fstream& fp, * sel * *******************************************************************/ -static -int print_spice_transmission_gate_subckt(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& tech_model) { +static int print_spice_transmission_gate_subckt( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, const TechnologyLibrary& tech_lib, + const TechnologyModelId& tech_model) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } /* Find the input and output ports: - * we do NOT support global ports here, + * we do NOT support global ports here, * it should be handled in another type of inverter subckt (power-gated) */ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); /* Make sure: - * There is only 3 input port and 1 output port, + * There is only 3 input port and 1 output port, * each size of which is 1 */ VTR_ASSERT(3 == input_ports.size()); for (const auto& input_port : input_ports) { - VTR_ASSERT(1 == circuit_lib.port_size(input_port)); + VTR_ASSERT(1 == circuit_lib.port_size(input_port)); } - VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + VTR_ASSERT((1 == output_ports.size()) && + (1 == circuit_lib.port_size(output_ports[0]))); int status = CMD_EXEC_SUCCESS; /* Print the inverter subckt definition */ - print_spice_subckt_definition(fp, module_manager, module_id); + print_spice_subckt_definition(fp, module_manager, module_id); /* Consider use size/bin to compact layout: * Try to size transistors to the max width for each bin - * The last bin may not reach the max width + * The last bin may not reach the max width */ - float regular_pmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); - float total_pmos_width = circuit_lib.pass_gate_logic_pmos_size(circuit_model) - * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float regular_pmos_bin_width = + tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); + float total_pmos_width = + circuit_lib.pass_gate_logic_pmos_size(circuit_model) * + tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_PMOS); int num_pmos_bins = std::ceil(total_pmos_width / regular_pmos_bin_width); - float last_pmos_bin_width = std::fmod(total_pmos_width, regular_pmos_bin_width); - for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { + float last_pmos_bin_width = + std::fmod(total_pmos_width, regular_pmos_bin_width); + for (int ibin = 0; ibin < num_pmos_bins; ++ibin) { float curr_bin_width = regular_pmos_bin_width; /* For last bin, we need an irregular width */ - if ((ibin == num_pmos_bins - 1) - && (0. != last_pmos_bin_width)) { + if ((ibin == num_pmos_bins - 1) && (0. != last_pmos_bin_width)) { curr_bin_width = last_pmos_bin_width; } - status = print_spice_generic_pmos_modeling(fp, - std::to_string(ibin), - circuit_lib.port_prefix(input_ports[0]), - circuit_lib.port_prefix(input_ports[2]), - circuit_lib.port_prefix(output_ports[0]), - tech_lib, - tech_model, - curr_bin_width); + status = print_spice_generic_pmos_modeling( + fp, std::to_string(ibin), circuit_lib.port_prefix(input_ports[0]), + circuit_lib.port_prefix(input_ports[2]), + circuit_lib.port_prefix(output_ports[0]), tech_lib, tech_model, + curr_bin_width); if (CMD_EXEC_FATAL_ERROR == status) { return status; } @@ -193,36 +189,35 @@ int print_spice_transmission_gate_subckt(std::fstream& fp, /* Consider use size/bin to compact layout: * Try to size transistors to the max width for each bin - * The last bin may not reach the max width + * The last bin may not reach the max width */ - float regular_nmos_bin_width = tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); - float total_nmos_width = circuit_lib.pass_gate_logic_nmos_size(circuit_model) - * tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float regular_nmos_bin_width = + tech_lib.transistor_model_max_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); + float total_nmos_width = + circuit_lib.pass_gate_logic_nmos_size(circuit_model) * + tech_lib.transistor_model_min_width(tech_model, TECH_LIB_TRANSISTOR_NMOS); int num_nmos_bins = std::ceil(total_nmos_width / regular_nmos_bin_width); - float last_nmos_bin_width = std::fmod(total_nmos_width, regular_nmos_bin_width); + float last_nmos_bin_width = + std::fmod(total_nmos_width, regular_nmos_bin_width); - for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { + for (int ibin = 0; ibin < num_nmos_bins; ++ibin) { float curr_bin_width = regular_nmos_bin_width; /* For last bin, we need an irregular width */ - if ((ibin == num_nmos_bins - 1) - && (0. != last_nmos_bin_width)) { + if ((ibin == num_nmos_bins - 1) && (0. != last_nmos_bin_width)) { curr_bin_width = last_nmos_bin_width; } - status = print_spice_generic_nmos_modeling(fp, - std::to_string(ibin), - circuit_lib.port_prefix(input_ports[0]), - circuit_lib.port_prefix(input_ports[1]), - circuit_lib.port_prefix(output_ports[0]), - tech_lib, - tech_model, - curr_bin_width); + status = print_spice_generic_nmos_modeling( + fp, std::to_string(ibin), circuit_lib.port_prefix(input_ports[0]), + circuit_lib.port_prefix(input_ports[1]), + circuit_lib.port_prefix(output_ports[0]), tech_lib, tech_model, + curr_bin_width); if (CMD_EXEC_FATAL_ERROR == status) { return status; } } - print_spice_subckt_end(fp, module_manager.module_name(module_id)); + print_spice_subckt_end(fp, module_manager.module_name(module_id)); return status; } @@ -230,7 +225,7 @@ int print_spice_transmission_gate_subckt(std::fstream& fp, /******************************************************************** * Generate the SPICE subckt for a pass-gate * - * Note: + * Note: * - This function supports both pass-transistor * and transmission gates *******************************************************************/ @@ -243,18 +238,18 @@ int print_spice_passgate_subckt(std::fstream& fp, const TechnologyModelId& tech_model) { int status = CMD_EXEC_SUCCESS; - if (CIRCUIT_MODEL_PASS_GATE_TRANSISTOR == circuit_lib.pass_gate_logic_type(circuit_model)) { - status = print_spice_pass_transistor_subckt(fp, - module_manager, module_id, + if (CIRCUIT_MODEL_PASS_GATE_TRANSISTOR == + circuit_lib.pass_gate_logic_type(circuit_model)) { + status = print_spice_pass_transistor_subckt(fp, module_manager, module_id, circuit_lib, circuit_model, tech_lib, tech_model); - } else if (CIRCUIT_MODEL_PASS_GATE_TRANSMISSION == circuit_lib.pass_gate_logic_type(circuit_model)) { - status = print_spice_transmission_gate_subckt(fp, - module_manager, module_id, + } else if (CIRCUIT_MODEL_PASS_GATE_TRANSMISSION == + circuit_lib.pass_gate_logic_type(circuit_model)) { + status = print_spice_transmission_gate_subckt(fp, module_manager, module_id, circuit_lib, circuit_model, tech_lib, tech_model); } - + return status; } diff --git a/openfpga/src/fpga_spice/spice_passgate.h b/openfpga/src/fpga_spice/spice_passgate.h index 96a292809..e89b5a344 100644 --- a/openfpga/src/fpga_spice/spice_passgate.h +++ b/openfpga/src/fpga_spice/spice_passgate.h @@ -4,10 +4,11 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include #include -#include "module_manager.h" +#include + #include "circuit_library.h" +#include "module_manager.h" #include "technology_library.h" /******************************************************************** diff --git a/openfpga/src/fpga_spice/spice_routing.cpp b/openfpga/src/fpga_spice/spice_routing.cpp index 9c83aef3c..ec29dbfd2 100644 --- a/openfpga/src/fpga_spice/spice_routing.cpp +++ b/openfpga/src/fpga_spice/spice_routing.cpp @@ -1,11 +1,11 @@ /********************************************************************* - * This file includes functions that are used for - * SPICE generation of FPGA routing architecture (global routing) + * This file includes functions that are used for + * SPICE generation of FPGA routing architecture (global routing) *********************************************************************/ /* Headers from vtrutil library */ #include "vtr_assert.h" -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgautil library */ #include "openfpga_digest.h" @@ -13,23 +13,23 @@ /* Include FPGA-Verilog header files*/ #include "openfpga_naming.h" #include "spice_constants.h" -#include "spice_writer_utils.h" -#include "spice_subckt_writer.h" #include "spice_routing.h" +#include "spice_subckt_writer.h" +#include "spice_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { -/******************************************************************** +/******************************************************************** * Print the sub-circuit of a connection Box (Type: [CHANX|CHANY]) * Actually it is very similiar to switch box but * the difference is connection boxes connect Grid INPUT Pins to channels * NOTE: direct connection between CLBs should NOT be included inside this - * module! They should be added in the top-level module as their connection - * is not limited to adjacent CLBs!!! + * module! They should be added in the top-level module as their + *connection is not limited to adjacent CLBs!!! * * Location of a X- and Y-direction Connection Block in FPGA fabric - * +------------+ +-------------+ + * +------------+ +-------------+ * | |------>| | * | CLB |<------| Y-direction | * | | ... | Connection | @@ -39,15 +39,16 @@ namespace openfpga { * v | v v | v * +-------------------+ +-------------+ * --->| |--->| | - * <---| X-direction |<---| Switch | + * <---| X-direction |<---| Switch | * ...| Connection block |... | Block | * --->| |--->| | * +-------------------+ +-------------+ * * Internal structure: - * This is an example of a X-direction connection block - * Note that middle output ports are shorted wire from inputs of routing tracks, - * which are also the inputs of routing multiplexer of the connection block + * This is an example of a X-direction connection block + * Note that middle output ports are shorted wire from inputs of routing + *tracks, which are also the inputs of routing multiplexer of the connection + *block * * CLB Input Pins * (IPINs) @@ -55,11 +56,11 @@ namespace openfpga { * | | ... | * +--------------------------+ * | ^ ^ ^ | - * | | | ... | | - * | +--------------------+ | + * | | | ... | | + * | +--------------------+ | * | | routing | | * | | multiplexers | | - * | +--------------------+ | + * | +--------------------+ | * | middle outputs | * | of routing channel | * | ^ ^ ^ ^ ^ ^ ^ ^ | @@ -72,17 +73,19 @@ namespace openfpga { * +--------------------------+ * * W: routing channel width - * + * ********************************************************************/ -static -void print_spice_routing_connection_box_unique_module(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const std::string& subckt_dir, - const RRGSB& rr_gsb, - const t_rr_type& cb_type) { +static void print_spice_routing_connection_box_unique_module( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const std::string& subckt_dir, const RRGSB& rr_gsb, + const t_rr_type& cb_type) { /* Create the netlist */ - vtr::Point gsb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); - std::string spice_fname(subckt_dir + generate_connection_block_netlist_name(cb_type, gsb_coordinate, std::string(SPICE_NETLIST_FILE_POSTFIX))); + vtr::Point gsb_coordinate(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); + std::string spice_fname( + subckt_dir + + generate_connection_block_netlist_name( + cb_type, gsb_coordinate, std::string(SPICE_NETLIST_FILE_POSTFIX))); /* Create the file stream */ std::fstream fp; @@ -90,15 +93,20 @@ void print_spice_routing_connection_box_unique_module(NetlistManager& netlist_ma check_file_stream(spice_fname.c_str(), fp); - print_spice_file_header(fp, std::string("SPICE modules for Unique Connection Blocks[" + std::to_string(rr_gsb.get_cb_x(cb_type)) + "]["+ std::to_string(rr_gsb.get_cb_y(cb_type)) + "]")); + print_spice_file_header( + fp, std::string("SPICE modules for Unique Connection Blocks[" + + std::to_string(rr_gsb.get_cb_x(cb_type)) + "][" + + std::to_string(rr_gsb.get_cb_y(cb_type)) + "]")); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId cb_module = module_manager.find_module(generate_connection_block_module_name(cb_type, gsb_coordinate)); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId cb_module = module_manager.find_module( + generate_connection_block_module_name(cb_type, gsb_coordinate)); VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); /* Write the spice module */ write_spice_subckt_to_file(fp, module_manager, cb_module); - + /* Add an empty line as a splitter */ fp << std::endl; @@ -108,13 +116,14 @@ void print_spice_routing_connection_box_unique_module(NetlistManager& netlist_ma /* Add fname to the netlist name list */ NetlistId nlist_id = netlist_manager.add_netlist(spice_fname); VTR_ASSERT(NetlistId::INVALID() != nlist_id); - netlist_manager.set_netlist_type(nlist_id, NetlistManager::ROUTING_MODULE_NETLIST); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::ROUTING_MODULE_NETLIST); } /********************************************************************* * Generate the SPICE module for a Switch Box. * A Switch Box module consists of following ports: - * 1. Channel Y [x][y] inputs + * 1. Channel Y [x][y] inputs * 2. Channel X [x+1][y] inputs * 3. Channel Y [x][y-1] outputs * 4. Channel X [x][y] outputs @@ -136,7 +145,7 @@ void print_spice_routing_connection_box_unique_module(NetlistManager& netlist_ma * | | | | * -------------- -------------- * ---------- - * ChanX | Switch | ChanX + * ChanX | Switch | ChanX * [x][y] | Box | [x+1][y] * | [x][y] | * ---------- @@ -149,39 +158,37 @@ void print_spice_routing_connection_box_unique_module(NetlistManager& netlist_ma * * Switch Block pin location map * - * Grid[x][y+1] ChanY[x][y+1] Grid[x+1][y+1] + * Grid[x][y+1] ChanY[x][y+1] Grid[x+1][y+1] * right_pins inputs/outputs left_pins * | ^ | * | | | * v v v * +-----------------------------------------------+ * | | - * Grid[x][y+1] | | Grid[x+1][y+1] - * bottom_pins---->| |<---- bottom_pins - * | | - * ChanX[x][y] | Switch Box [x][y] | ChanX[x+1][y] - * inputs/outputs<--->| |<---> inputs/outputs - * | | - * Grid[x][y+1] | | Grid[x+1][y+1] - * top_pins---->| |<---- top_pins - * | | + * Grid[x][y+1] | | + *Grid[x+1][y+1] bottom_pins---->| |<---- bottom_pins | | ChanX[x][y] | + *Switch Box [x][y] | ChanX[x+1][y] inputs/outputs<--->| + *|<---> inputs/outputs | | + * Grid[x][y+1] | | + *Grid[x+1][y+1] top_pins---->| |<---- top_pins | | * +-----------------------------------------------+ * ^ ^ ^ * | | | * | v | - * Grid[x][y] ChanY[x][y] Grid[x+1][y] + * Grid[x][y] ChanY[x][y] Grid[x+1][y] * right_pins inputs/outputs left_pins * * ********************************************************************/ -static -void print_spice_routing_switch_box_unique_module(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const std::string& subckt_dir, - const RRGSB& rr_gsb) { +static void print_spice_routing_switch_box_unique_module( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const std::string& subckt_dir, const RRGSB& rr_gsb) { /* Create the netlist */ vtr::Point gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); - std::string spice_fname(subckt_dir + generate_routing_block_netlist_name(SB_SPICE_FILE_NAME_PREFIX, gsb_coordinate, std::string(SPICE_NETLIST_FILE_POSTFIX))); + std::string spice_fname(subckt_dir + + generate_routing_block_netlist_name( + SB_SPICE_FILE_NAME_PREFIX, gsb_coordinate, + std::string(SPICE_NETLIST_FILE_POSTFIX))); /* Create the file stream */ std::fstream fp; @@ -189,51 +196,53 @@ void print_spice_routing_switch_box_unique_module(NetlistManager& netlist_manage check_file_stream(spice_fname.c_str(), fp); - print_spice_file_header(fp, std::string("SPICE subcircuits for Unique Switch Blocks[" + std::to_string(rr_gsb.get_sb_x()) + "]["+ std::to_string(rr_gsb.get_sb_y()) + "]")); + print_spice_file_header( + fp, std::string("SPICE subcircuits for Unique Switch Blocks[" + + std::to_string(rr_gsb.get_sb_x()) + "][" + + std::to_string(rr_gsb.get_sb_y()) + "]")); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId sb_module = module_manager.find_module(generate_switch_block_module_name(gsb_coordinate)); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId sb_module = module_manager.find_module( + generate_switch_block_module_name(gsb_coordinate)); VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); /* Write the spice module */ write_spice_subckt_to_file(fp, module_manager, sb_module); - + /* Close file handler */ fp.close(); /* Add fname to the netlist name list */ NetlistId nlist_id = netlist_manager.add_netlist(spice_fname); VTR_ASSERT(NetlistId::INVALID() != nlist_id); - netlist_manager.set_netlist_type(nlist_id, NetlistManager::ROUTING_MODULE_NETLIST); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::ROUTING_MODULE_NETLIST); } /******************************************************************** * Iterate over all the connection blocks in a device - * and build a module for each of them + * and build a module for each of them *******************************************************************/ -static -void print_spice_flatten_connection_block_modules(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const DeviceRRGSB& device_rr_gsb, - const std::string& subckt_dir, - const t_rr_type& cb_type) { +static void print_spice_flatten_connection_block_modules( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const DeviceRRGSB& device_rr_gsb, const std::string& subckt_dir, + const t_rr_type& cb_type) { /* Build unique X-direction connection block modules */ vtr::Point cb_range = device_rr_gsb.get_gsb_range(); for (size_t ix = 0; ix < cb_range.x(); ++ix) { for (size_t iy = 0; iy < cb_range.y(); ++iy) { /* Check if the connection block exists in the device! - * Some of them do NOT exist due to heterogeneous blocks (height > 1) + * Some of them do NOT exist due to heterogeneous blocks (height > 1) * We will skip those modules */ const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); if (true != rr_gsb.is_cb_exist(cb_type)) { continue; } - print_spice_routing_connection_box_unique_module(netlist_manager, - module_manager, - subckt_dir, - rr_gsb, cb_type); + print_spice_routing_connection_box_unique_module( + netlist_manager, module_manager, subckt_dir, rr_gsb, cb_type); } } } @@ -251,7 +260,8 @@ void print_spice_flatten_routing_modules(NetlistManager& netlist_manager, const ModuleManager& module_manager, const DeviceRRGSB& device_rr_gsb, const std::string& subckt_dir) { - /* Create a vector to contain all the Verilog netlist names that have been generated in this function */ + /* Create a vector to contain all the Verilog netlist names that have been + * generated in this function */ std::vector netlist_names; vtr::Point sb_range = device_rr_gsb.get_gsb_range(); @@ -263,16 +273,16 @@ void print_spice_flatten_routing_modules(NetlistManager& netlist_manager, if (true != rr_gsb.is_sb_exist()) { continue; } - print_spice_routing_switch_box_unique_module(netlist_manager, - module_manager, - subckt_dir, - rr_gsb); + print_spice_routing_switch_box_unique_module( + netlist_manager, module_manager, subckt_dir, rr_gsb); } } - print_spice_flatten_connection_block_modules(netlist_manager, module_manager, device_rr_gsb, subckt_dir, CHANX); + print_spice_flatten_connection_block_modules( + netlist_manager, module_manager, device_rr_gsb, subckt_dir, CHANX); - print_spice_flatten_connection_block_modules(netlist_manager, module_manager, device_rr_gsb, subckt_dir, CHANY); + print_spice_flatten_connection_block_modules( + netlist_manager, module_manager, device_rr_gsb, subckt_dir, CHANY); /* VTR_LOG("Writing header file for routing submodules '%s'...", @@ -285,51 +295,47 @@ void print_spice_flatten_routing_modules(NetlistManager& netlist_manager, */ } - /******************************************************************** * A top-level function of this file * Print all the unique modules for global routing architecture of a FPGA fabric - * in Verilog format, including: + * in Verilog format, including: * 1. Connection blocks * 2. Switch blocks * - * Note: this function SHOULD be called only when + * Note: this function SHOULD be called only when * the option compact_routing_hierarchy is turned on!!! *******************************************************************/ void print_spice_unique_routing_modules(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const DeviceRRGSB& device_rr_gsb, - const std::string& subckt_dir) { - /* Create a vector to contain all the Verilog netlist names that have been generated in this function */ + const ModuleManager& module_manager, + const DeviceRRGSB& device_rr_gsb, + const std::string& subckt_dir) { + /* Create a vector to contain all the Verilog netlist names that have been + * generated in this function */ std::vector netlist_names; /* Build unique switch block modules */ for (size_t isb = 0; isb < device_rr_gsb.get_num_sb_unique_module(); ++isb) { const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(isb); - print_spice_routing_switch_box_unique_module(netlist_manager, - module_manager, - subckt_dir, - unique_mirror); + print_spice_routing_switch_box_unique_module( + netlist_manager, module_manager, subckt_dir, unique_mirror); } /* Build unique X-direction connection block modules */ - for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANX); ++icb) { + for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANX); + ++icb) { const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(CHANX, icb); - print_spice_routing_connection_box_unique_module(netlist_manager, - module_manager, - subckt_dir, - unique_mirror, CHANX); + print_spice_routing_connection_box_unique_module( + netlist_manager, module_manager, subckt_dir, unique_mirror, CHANX); } /* Build unique X-direction connection block modules */ - for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANY); ++icb) { + for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANY); + ++icb) { const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(CHANY, icb); - print_spice_routing_connection_box_unique_module(netlist_manager, - module_manager, - subckt_dir, - unique_mirror, CHANY); + print_spice_routing_connection_box_unique_module( + netlist_manager, module_manager, subckt_dir, unique_mirror, CHANY); } /* diff --git a/openfpga/src/fpga_spice/spice_routing.h b/openfpga/src/fpga_spice/spice_routing.h index 3d2e499cc..c14a3d68b 100644 --- a/openfpga/src/fpga_spice/spice_routing.h +++ b/openfpga/src/fpga_spice/spice_routing.h @@ -5,10 +5,10 @@ * Include header files that are required by function declaration *******************************************************************/ -#include "mux_library.h" -#include "module_manager.h" -#include "netlist_manager.h" #include "device_rr_gsb.h" +#include "module_manager.h" +#include "mux_library.h" +#include "netlist_manager.h" /******************************************************************** * Function declaration diff --git a/openfpga/src/fpga_spice/spice_subckt_writer.cpp b/openfpga/src/fpga_spice/spice_subckt_writer.cpp index 291404ec6..6152b41ec 100644 --- a/openfpga/src/fpga_spice/spice_subckt_writer.cpp +++ b/openfpga/src/fpga_spice/spice_subckt_writer.cpp @@ -3,7 +3,7 @@ * based on its definition in Module Manager * * Note that SPICE writer functions are just an outputter for the - * module definition. + * module definition. * You should NOT modify any content of the module manager * Please use const keyword to restrict this! *******************************************************************/ @@ -13,121 +13,133 @@ #include "vtr_assert.h" /* Headers from openfpgautil library */ -#include "openfpga_port.h" -#include "openfpga_digest.h" - -#include "openfpga_naming.h" - #include "module_manager_utils.h" - - +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" #include "spice_constants.h" -#include "spice_writer_utils.h" #include "spice_subckt_writer.h" +#include "spice_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * Generate the name of a local wire for a undriven port inside SPICE - * module + * Generate the name of a local wire for a undriven port inside SPICE + * module *******************************************************************/ -static -std::string generate_spice_undriven_local_wire_name(const ModuleManager& module_manager, - const ModuleId& parent, - const ModuleId& child, - const size_t& instance_id, - const ModulePortId& child_port_id) { +static std::string generate_spice_undriven_local_wire_name( + const ModuleManager& module_manager, const ModuleId& parent, + const ModuleId& child, const size_t& instance_id, + const ModulePortId& child_port_id) { std::string wire_name; if (!module_manager.instance_name(parent, child, instance_id).empty()) { wire_name = module_manager.instance_name(parent, child, instance_id); } else { - wire_name = module_manager.module_name(parent) + std::string("_") + std::to_string(instance_id); + wire_name = module_manager.module_name(parent) + std::string("_") + + std::to_string(instance_id); wire_name += std::string("_"); } - + wire_name += std::string("_undriven_"); wire_name += module_manager.module_port(child, child_port_id).get_name(); - + return wire_name; } - /******************************************************************** * Name a net for a local wire for a SPICE subckt - * 1. If this is a local wire, name it after the __ - * 2. If this is not a local wire, name it after the port name of parent module + * 1. If this is a local wire, name it after the + *__ + * 2. If this is not a local wire, name it after the port name of parent module * - * In addition, it will assign the pin index as well + * In addition, it will assign the pin index as well * * Restriction: this function requires each net has single driver * which is definitely always true in circuits. *******************************************************************/ -static -BasicPort generate_spice_port_for_module_net(const ModuleManager& module_manager, - const ModuleId& module_id, - const ModuleNetId& module_net) { - /* Check all the sink modules of the net, - * if we have a source module is the current module, this is not local wire +static BasicPort generate_spice_port_for_module_net( + const ModuleManager& module_manager, const ModuleId& module_id, + const ModuleNetId& module_net) { + /* Check all the sink modules of the net, + * if we have a source module is the current module, this is not local wire */ - for (ModuleNetSrcId src_id : module_manager.module_net_sources(module_id, module_net)) { - if (module_id == module_manager.net_source_modules(module_id, module_net)[src_id]) { + for (ModuleNetSrcId src_id : + module_manager.module_net_sources(module_id, module_net)) { + if (module_id == + module_manager.net_source_modules(module_id, module_net)[src_id]) { /* Here, this is not a local wire, return the port name of the src_port */ - ModulePortId net_src_port = module_manager.net_source_ports(module_id, module_net)[src_id]; - size_t src_pin_index = module_manager.net_source_pins(module_id, module_net)[src_id]; - return BasicPort(module_manager.module_port(module_id, net_src_port).get_name(), src_pin_index, src_pin_index); + ModulePortId net_src_port = + module_manager.net_source_ports(module_id, module_net)[src_id]; + size_t src_pin_index = + module_manager.net_source_pins(module_id, module_net)[src_id]; + return BasicPort( + module_manager.module_port(module_id, net_src_port).get_name(), + src_pin_index, src_pin_index); } } /* Check all the sink modules of the net */ - for (ModuleNetSinkId sink_id : module_manager.module_net_sinks(module_id, module_net)) { - if (module_id == module_manager.net_sink_modules(module_id, module_net)[sink_id]) { - /* Here, this is not a local wire, return the port name of the sink_port */ - ModulePortId net_sink_port = module_manager.net_sink_ports(module_id, module_net)[sink_id]; - size_t sink_pin_index = module_manager.net_sink_pins(module_id, module_net)[sink_id]; - return BasicPort(module_manager.module_port(module_id, net_sink_port).get_name(), sink_pin_index, sink_pin_index); + for (ModuleNetSinkId sink_id : + module_manager.module_net_sinks(module_id, module_net)) { + if (module_id == + module_manager.net_sink_modules(module_id, module_net)[sink_id]) { + /* Here, this is not a local wire, return the port name of the sink_port + */ + ModulePortId net_sink_port = + module_manager.net_sink_ports(module_id, module_net)[sink_id]; + size_t sink_pin_index = + module_manager.net_sink_pins(module_id, module_net)[sink_id]; + return BasicPort( + module_manager.module_port(module_id, net_sink_port).get_name(), + sink_pin_index, sink_pin_index); } } /* Reach here, this is a local wire */ std::string net_name; - /* Each net must only one 1 source */ - VTR_ASSERT(1 == module_manager.net_source_modules(module_id, module_net).size()); + /* Each net must only one 1 source */ + VTR_ASSERT(1 == + module_manager.net_source_modules(module_id, module_net).size()); /* Get the source module */ - ModuleId net_src_module = module_manager.net_source_modules(module_id, module_net)[ModuleNetSrcId(0)]; + ModuleId net_src_module = + module_manager.net_source_modules(module_id, module_net)[ModuleNetSrcId(0)]; /* Get the instance id */ - size_t net_src_instance = module_manager.net_source_instances(module_id, module_net)[ModuleNetSrcId(0)]; + size_t net_src_instance = module_manager.net_source_instances( + module_id, module_net)[ModuleNetSrcId(0)]; /* Get the port id */ - ModulePortId net_src_port = module_manager.net_source_ports(module_id, module_net)[ModuleNetSrcId(0)]; + ModulePortId net_src_port = + module_manager.net_source_ports(module_id, module_net)[ModuleNetSrcId(0)]; /* Get the pin id */ - size_t net_src_pin = module_manager.net_source_pins(module_id, module_net)[ModuleNetSrcId(0)]; + size_t net_src_pin = + module_manager.net_source_pins(module_id, module_net)[ModuleNetSrcId(0)]; /* Load user-defined name if we have it */ if (false == module_manager.net_name(module_id, module_net).empty()) { net_name = module_manager.net_name(module_id, module_net); } else { - net_name = module_manager.module_name(net_src_module); - net_name += std::string("_") + std::to_string(net_src_instance) + std::string("_"); - net_name += module_manager.module_port(net_src_module, net_src_port).get_name(); + net_name = module_manager.module_name(net_src_module); + net_name += + std::string("_") + std::to_string(net_src_instance) + std::string("_"); + net_name += + module_manager.module_port(net_src_module, net_src_port).get_name(); } - + return BasicPort(net_name, net_src_pin, net_src_pin); } /******************************************************************** - * Print a SPICE wire connection - * We search all the sinks of the net, - * if we find a module output, we try to find the next module output + * Print a SPICE wire connection + * We search all the sinks of the net, + * if we find a module output, we try to find the next module output * among the sinks of the net - * For each module output (except the first one), we print a wire connection + * For each module output (except the first one), we print a wire connection *******************************************************************/ -static -void print_spice_subckt_output_short_connection(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const ModuleNetId& module_net) { +static void print_spice_subckt_output_short_connection( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const ModuleNetId& module_net) { /* Ensure a valid file stream */ VTR_ASSERT(true == valid_file_stream(fp)); @@ -135,18 +147,25 @@ void print_spice_subckt_output_short_connection(std::fstream& fp, BasicPort src_port; /* We have found a module input, now check all the sink modules of the net */ - for (ModuleNetSinkId net_sink : module_manager.module_net_sinks(module_id, module_net)) { - ModuleId sink_module = module_manager.net_sink_modules(module_id, module_net)[net_sink]; + for (ModuleNetSinkId net_sink : + module_manager.module_net_sinks(module_id, module_net)) { + ModuleId sink_module = + module_manager.net_sink_modules(module_id, module_net)[net_sink]; if (module_id != sink_module) { continue; } /* Find the sink port and pin information */ - ModulePortId sink_port_id = module_manager.net_sink_ports(module_id, module_net)[net_sink]; - size_t sink_pin = module_manager.net_sink_pins(module_id, module_net)[net_sink]; - BasicPort sink_port(module_manager.module_port(module_id, sink_port_id).get_name(), sink_pin, sink_pin); + ModulePortId sink_port_id = + module_manager.net_sink_ports(module_id, module_net)[net_sink]; + size_t sink_pin = + module_manager.net_sink_pins(module_id, module_net)[net_sink]; + BasicPort sink_port( + module_manager.module_port(module_id, sink_port_id).get_name(), sink_pin, + sink_pin); - /* For the first module output, this is the source port, we do nothing and go to the next */ + /* For the first module output, this is the source port, we do nothing and + * go to the next */ if (true == first_port) { src_port = sink_port; /* Flip the flag */ @@ -157,62 +176,76 @@ void print_spice_subckt_output_short_connection(std::fstream& fp, /* We need to print a wire connection here */ VTR_ASSERT(src_port.get_width() == sink_port.get_width()); for (size_t ipin = 0; ipin < src_port.pins().size(); ++ipin) { - BasicPort src_spice_pin(src_port.get_name(), src_port.pins()[ipin], src_port.pins()[ipin]); - BasicPort sink_spice_pin(sink_port.get_name(), sink_port.pins()[ipin], sink_port.pins()[ipin]); - print_spice_short_connection(fp, - generate_spice_port(src_spice_pin), + BasicPort src_spice_pin(src_port.get_name(), src_port.pins()[ipin], + src_port.pins()[ipin]); + BasicPort sink_spice_pin(sink_port.get_name(), sink_port.pins()[ipin], + sink_port.pins()[ipin]); + print_spice_short_connection(fp, generate_spice_port(src_spice_pin), generate_spice_port(sink_spice_pin)); } } } - /******************************************************************** - * Print a SPICE wire connection - * We search all the sources of the net, - * if we find a module input, we try to find a module output + * Print a SPICE wire connection + * We search all the sources of the net, + * if we find a module input, we try to find a module output * among the sinks of the net - * If we find such a pair, we print a wire connection + * If we find such a pair, we print a wire connection *******************************************************************/ -static -void print_spice_subckt_local_short_connection(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const ModuleNetId& module_net) { +static void print_spice_subckt_local_short_connection( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const ModuleNetId& module_net) { /* Ensure a valid file stream */ VTR_ASSERT(true == valid_file_stream(fp)); - for (ModuleNetSrcId net_src : module_manager.module_net_sources(module_id, module_net)) { - ModuleId src_module = module_manager.net_source_modules(module_id, module_net)[net_src]; + for (ModuleNetSrcId net_src : + module_manager.module_net_sources(module_id, module_net)) { + ModuleId src_module = + module_manager.net_source_modules(module_id, module_net)[net_src]; if (module_id != src_module) { continue; } /* Find the source port and pin information */ - print_spice_comment(fp, std::string("Net source id " + std::to_string(size_t(net_src)))); - ModulePortId src_port_id = module_manager.net_source_ports(module_id, module_net)[net_src]; - size_t src_pin = module_manager.net_source_pins(module_id, module_net)[net_src]; - BasicPort src_port(module_manager.module_port(module_id, src_port_id).get_name(), src_pin, src_pin); + print_spice_comment( + fp, std::string("Net source id " + std::to_string(size_t(net_src)))); + ModulePortId src_port_id = + module_manager.net_source_ports(module_id, module_net)[net_src]; + size_t src_pin = + module_manager.net_source_pins(module_id, module_net)[net_src]; + BasicPort src_port( + module_manager.module_port(module_id, src_port_id).get_name(), src_pin, + src_pin); - /* We have found a module input, now check all the sink modules of the net */ - for (ModuleNetSinkId net_sink : module_manager.module_net_sinks(module_id, module_net)) { - ModuleId sink_module = module_manager.net_sink_modules(module_id, module_net)[net_sink]; + /* We have found a module input, now check all the sink modules of the net + */ + for (ModuleNetSinkId net_sink : + module_manager.module_net_sinks(module_id, module_net)) { + ModuleId sink_module = + module_manager.net_sink_modules(module_id, module_net)[net_sink]; if (module_id != sink_module) { continue; } /* Find the sink port and pin information */ - print_spice_comment(fp, std::string("Net sink id " + std::to_string(size_t(net_sink)))); - ModulePortId sink_port_id = module_manager.net_sink_ports(module_id, module_net)[net_sink]; - size_t sink_pin = module_manager.net_sink_pins(module_id, module_net)[net_sink]; - BasicPort sink_port(module_manager.module_port(module_id, sink_port_id).get_name(), sink_pin, sink_pin); + print_spice_comment( + fp, std::string("Net sink id " + std::to_string(size_t(net_sink)))); + ModulePortId sink_port_id = + module_manager.net_sink_ports(module_id, module_net)[net_sink]; + size_t sink_pin = + module_manager.net_sink_pins(module_id, module_net)[net_sink]; + BasicPort sink_port( + module_manager.module_port(module_id, sink_port_id).get_name(), + sink_pin, sink_pin); /* We need to print a wire connection here */ VTR_ASSERT(src_port.get_width() == sink_port.get_width()); for (size_t ipin = 0; ipin < src_port.pins().size(); ++ipin) { - BasicPort src_spice_pin(src_port.get_name(), src_port.pins()[ipin], src_port.pins()[ipin]); - BasicPort sink_spice_pin(sink_port.get_name(), sink_port.pins()[ipin], sink_port.pins()[ipin]); - print_spice_short_connection(fp, - generate_spice_port(src_spice_pin), + BasicPort src_spice_pin(src_port.get_name(), src_port.pins()[ipin], + src_port.pins()[ipin]); + BasicPort sink_spice_pin(sink_port.get_name(), sink_port.pins()[ipin], + sink_port.pins()[ipin]); + print_spice_short_connection(fp, generate_spice_port(src_spice_pin), generate_spice_port(sink_spice_pin)); } } @@ -224,7 +257,7 @@ void print_spice_subckt_local_short_connection(std::fstream& fp, * The short connection is defined as the direct connection * between an input port of the module and an output port of the module * This type of connection is not covered when printing SPICE instances - * Therefore, they are covered in this function + * Therefore, they are covered in this function * * module * +-----------------------------+ @@ -235,18 +268,20 @@ void print_spice_subckt_local_short_connection(std::fstream& fp, * | | * +-----------------------------+ *******************************************************************/ -static -void print_spice_subckt_local_short_connections(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id) { +static void print_spice_subckt_local_short_connections( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id) { /* Local wires come from the child modules */ for (ModuleNetId module_net : module_manager.module_nets(module_id)) { - /* We only care the nets that indicate short connections */ - if (false == module_net_include_local_short_connection(module_manager, module_id, module_net)) { + /* We only care the nets that indicate short connections */ + if (false == module_net_include_local_short_connection( + module_manager, module_id, module_net)) { continue; } - print_spice_comment(fp, std::string("Local connection due to Wire " + std::to_string(size_t(module_net)))); - print_spice_subckt_local_short_connection(fp, module_manager, module_id, module_net); + print_spice_comment(fp, std::string("Local connection due to Wire " + + std::to_string(size_t(module_net)))); + print_spice_subckt_local_short_connection(fp, module_manager, module_id, + module_net); } } @@ -255,7 +290,7 @@ void print_spice_subckt_local_short_connections(std::fstream& fp, * The output short connection is defined as the direct connection * between two output ports of the module * This type of connection is not covered when printing SPICE instances - * Therefore, they are covered in this function + * Therefore, they are covered in this function * * module * +-----------------------------+ @@ -266,17 +301,18 @@ void print_spice_subckt_local_short_connections(std::fstream& fp, * +--------------->|--->outputB * +-----------------------------+ *******************************************************************/ -static -void print_spice_subckt_output_short_connections(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id) { +static void print_spice_subckt_output_short_connections( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id) { /* Local wires come from the child modules */ for (ModuleNetId module_net : module_manager.module_nets(module_id)) { - /* We only care the nets that indicate short connections */ - if (false == module_net_include_output_short_connection(module_manager, module_id, module_net)) { + /* We only care the nets that indicate short connections */ + if (false == module_net_include_output_short_connection( + module_manager, module_id, module_net)) { continue; } - print_spice_subckt_output_short_connection(fp, module_manager, module_id, module_net); + print_spice_subckt_output_short_connection(fp, module_manager, module_id, + module_net); } } @@ -284,7 +320,7 @@ void print_spice_subckt_output_short_connections(std::fstream& fp, * Write a SPICE instance to a file * This function will name the input and output connections to * the inputs/output or local wires available in the parent module - * + * * Parent_module * +-----------------------------+ * | | @@ -297,24 +333,27 @@ void print_spice_subckt_output_short_connections(std::fstream& fp, * +-----------------------------+ * *******************************************************************/ -static -void write_spice_instance_to_file(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const ModuleId& child_module, - const size_t& instance_id) { +static void write_spice_instance_to_file(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& parent_module, + const ModuleId& child_module, + const size_t& instance_id) { /* Ensure a valid file stream */ VTR_ASSERT(true == valid_file_stream(fp)); - /* Print instance name: + /* Print instance name: * if we have an instance name, use it; - * if not, we use a default name _ + * if not, we use a default name _ */ std::string instance_head_line = "X "; - if (true == module_manager.instance_name(parent_module, child_module, instance_id).empty()) { - instance_head_line += generate_instance_name(module_manager.module_name(child_module), instance_id); + if (true == + module_manager.instance_name(parent_module, child_module, instance_id) + .empty()) { + instance_head_line += generate_instance_name( + module_manager.module_name(child_module), instance_id); } else { - instance_head_line += module_manager.instance_name(parent_module, child_module, instance_id); + instance_head_line += + module_manager.instance_name(parent_module, child_module, instance_id); } instance_head_line += " "; fp << instance_head_line; @@ -324,45 +363,50 @@ void write_spice_instance_to_file(std::fstream& fp, bool new_line = false; size_t pin_cnt = 0; for (int port_type = ModuleManager::MODULE_GLOBAL_PORT; - port_type < ModuleManager::NUM_MODULE_PORT_TYPES; - ++port_type) { - for (const auto& child_port_id : module_manager.module_port_ids_by_type(child_module, static_cast(port_type))) { - - BasicPort child_port = module_manager.module_port(child_module, child_port_id); + port_type < ModuleManager::NUM_MODULE_PORT_TYPES; ++port_type) { + for (const auto& child_port_id : module_manager.module_port_ids_by_type( + child_module, + static_cast(port_type))) { + BasicPort child_port = + module_manager.module_port(child_module, child_port_id); /* Create the port name and width to be used by the instance */ - std::vector instance_ports; + std::vector instance_ports; for (size_t child_pin : child_port.pins()) { /* Find the net linked to the pin */ - ModuleNetId net = module_manager.module_instance_port_net(parent_module, child_module, instance_id, - child_port_id, child_pin); + ModuleNetId net = module_manager.module_instance_port_net( + parent_module, child_module, instance_id, child_port_id, child_pin); BasicPort instance_port; if (ModuleNetId::INVALID() == net) { - /* We give the same port name as child module, this case happens to global ports */ - instance_port.set_name(generate_spice_undriven_local_wire_name(module_manager, parent_module, child_module, instance_id, child_port_id)); - instance_port.set_width(child_pin, child_pin); + /* We give the same port name as child module, this case happens to + * global ports */ + instance_port.set_name(generate_spice_undriven_local_wire_name( + module_manager, parent_module, child_module, instance_id, + child_port_id)); + instance_port.set_width(child_pin, child_pin); } else { /* Find the name for this child port */ - instance_port = generate_spice_port_for_module_net(module_manager, parent_module, net); + instance_port = generate_spice_port_for_module_net( + module_manager, parent_module, net); } if (true == new_line) { std::string port_whitespace(instance_head_line.length() - 2, ' '); fp << "+ " << port_whitespace; } - + if (0 != pin_cnt) { write_space_to_file(fp, 1); } - + VTR_ASSERT(1 == instance_port.get_width()); /* For single-bit port, * we can print the port name directly */ bool omit_pin_zero = false; - if ((1 == instance_port.pins().size()) - && (0 == instance_port.get_lsb())) { + if ((1 == instance_port.pins().size()) && + (0 == instance_port.get_lsb())) { omit_pin_zero = true; } @@ -379,7 +423,7 @@ void write_spice_instance_to_file(std::fstream& fp, new_line = true; fit_one_line = false; } - } + } } } @@ -406,8 +450,9 @@ void write_spice_instance_to_file(std::fstream& fp, fit_one_line = false; } - /* Print module name: - * if port print cannot fit one line, we create a new line for the module for a clean format + /* Print module name: + * if port print cannot fit one line, we create a new line for the module for + * a clean format */ if (false == fit_one_line) { fp << std::endl; @@ -415,7 +460,7 @@ void write_spice_instance_to_file(std::fstream& fp, } write_space_to_file(fp, 1); fp << module_manager.module_name(child_module); - + /* Print an end to the instance */ fp << std::endl; } @@ -423,16 +468,15 @@ void write_spice_instance_to_file(std::fstream& fp, /******************************************************************** * Write a SPICE sub-circuit to a file * This is a key function, maybe most frequently called in our SPICE writer - * Note that file stream must be valid + * Note that file stream must be valid *******************************************************************/ void write_spice_subckt_to_file(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id) { - + const ModuleManager& module_manager, + const ModuleId& module_id) { VTR_ASSERT(true == valid_file_stream(fp)); /* Ensure we have a valid module_id */ - VTR_ASSERT(module_manager.valid_module_id(module_id)); + VTR_ASSERT(module_manager.valid_module_id(module_id)); /* Print module declaration */ print_spice_subckt_definition(fp, module_manager, module_id); @@ -450,23 +494,25 @@ void write_spice_subckt_to_file(std::fstream& fp, print_spice_comment(fp, std::string("BEGIN Local output short connections")); print_spice_subckt_output_short_connections(fp, module_manager, module_id); - + print_spice_comment(fp, std::string("END Local output short connections")); /* Print an empty line as splitter */ fp << std::endl; /* Print instances */ for (ModuleId child_module : module_manager.child_modules(module_id)) { - for (size_t instance : module_manager.child_module_instances(module_id, child_module)) { + for (size_t instance : + module_manager.child_module_instances(module_id, child_module)) { /* Print an instance */ - write_spice_instance_to_file(fp, module_manager, module_id, child_module, instance); + write_spice_instance_to_file(fp, module_manager, module_id, child_module, + instance); /* Print an empty line as splitter */ fp << std::endl; } } /* Print an end for the module */ - print_spice_subckt_end(fp, module_manager.module_name(module_id)); + print_spice_subckt_end(fp, module_manager.module_name(module_id)); /* Print an empty line as splitter */ fp << std::endl; diff --git a/openfpga/src/fpga_spice/spice_subckt_writer.h b/openfpga/src/fpga_spice/spice_subckt_writer.h index f47e3915f..7e4b8e1b9 100644 --- a/openfpga/src/fpga_spice/spice_subckt_writer.h +++ b/openfpga/src/fpga_spice/spice_subckt_writer.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "module_manager.h" /******************************************************************** diff --git a/openfpga/src/fpga_spice/spice_submodule.cpp b/openfpga/src/fpga_spice/spice_submodule.cpp index 26b166a59..e7e7efb29 100644 --- a/openfpga/src/fpga_spice/spice_submodule.cpp +++ b/openfpga/src/fpga_spice/spice_submodule.cpp @@ -9,15 +9,13 @@ /* Headers from openfpgashell library */ #include "command_exit_codes.h" - -#include "spice_transistor_wrapper.h" +#include "spice_constants.h" #include "spice_essential_gates.h" -#include "spice_mux.h" #include "spice_lut.h" #include "spice_memory.h" - -#include "spice_constants.h" +#include "spice_mux.h" #include "spice_submodule.h" +#include "spice_transistor_wrapper.h" /* begin namespace openfpga */ namespace openfpga { @@ -25,7 +23,8 @@ namespace openfpga { /********************************************************************* * Top-level function to generate primitive modules: * 1. Transistor wrapper - * 2. Logic gates: AND/OR, inverter, buffer and transmission-gate/pass-transistor + * 2. Logic gates: AND/OR, inverter, buffer and + *transmission-gate/pass-transistor * 3. Routing multiplexers * 4. TODO: Local encoders for routing multiplexers * 5. Wires @@ -33,16 +32,13 @@ namespace openfpga { ********************************************************************/ int print_spice_submodule(NetlistManager& netlist_manager, const ModuleManager& module_manager, - const Arch& openfpga_arch, - const MuxLibrary& mux_lib, + const Arch& openfpga_arch, const MuxLibrary& mux_lib, const std::string& submodule_dir) { - int status = CMD_EXEC_SUCCESS; /* Transistor wrapper */ - status = print_spice_transistor_wrapper(netlist_manager, - openfpga_arch.tech_lib, - submodule_dir); + status = print_spice_transistor_wrapper( + netlist_manager, openfpga_arch.tech_lib, submodule_dir); /* Error out if fatal errors have been reported */ if (CMD_EXEC_SUCCESS != status) { @@ -50,27 +46,23 @@ int print_spice_submodule(NetlistManager& netlist_manager, } /* Constant modules: VDD and GND */ - status = print_spice_supply_wrappers(netlist_manager, - module_manager, - submodule_dir); + status = + print_spice_supply_wrappers(netlist_manager, module_manager, submodule_dir); /* Error out if fatal errors have been reported */ if (CMD_EXEC_SUCCESS != status) { return CMD_EXEC_FATAL_ERROR; } - /* Logic gates: - * - AND/OR, + /* Logic gates: + * - AND/OR, * - inverter, buffer * - transmission-gate/pass-transistor * - wires */ - status = print_spice_essential_gates(netlist_manager, - module_manager, - openfpga_arch.circuit_lib, - openfpga_arch.tech_lib, - openfpga_arch.circuit_tech_binding, - submodule_dir); + status = print_spice_essential_gates( + netlist_manager, module_manager, openfpga_arch.circuit_lib, + openfpga_arch.tech_lib, openfpga_arch.circuit_tech_binding, submodule_dir); /* Error out if fatal errors have been reported */ if (CMD_EXEC_SUCCESS != status) { @@ -80,11 +72,9 @@ int print_spice_submodule(NetlistManager& netlist_manager, /* TODO: local decoders for routing multiplexers */ /* Routing multiplexers */ - status = print_spice_submodule_muxes(netlist_manager, - module_manager, - mux_lib, - openfpga_arch.circuit_lib, - submodule_dir); + status = + print_spice_submodule_muxes(netlist_manager, module_manager, mux_lib, + openfpga_arch.circuit_lib, submodule_dir); /* Error out if fatal errors have been reported */ if (CMD_EXEC_SUCCESS != status) { @@ -92,10 +82,8 @@ int print_spice_submodule(NetlistManager& netlist_manager, } /* Look-Up Tables */ - status = print_spice_submodule_luts(netlist_manager, - module_manager, - openfpga_arch.circuit_lib, - submodule_dir); + status = print_spice_submodule_luts(netlist_manager, module_manager, + openfpga_arch.circuit_lib, submodule_dir); /* Error out if fatal errors have been reported */ if (CMD_EXEC_SUCCESS != status) { @@ -103,11 +91,9 @@ int print_spice_submodule(NetlistManager& netlist_manager, } /* Memories */ - status = print_spice_submodule_memories(netlist_manager, - module_manager, - mux_lib, - openfpga_arch.circuit_lib, - submodule_dir); + status = + print_spice_submodule_memories(netlist_manager, module_manager, mux_lib, + openfpga_arch.circuit_lib, submodule_dir); /* Error out if fatal errors have been reported */ if (CMD_EXEC_SUCCESS != status) { diff --git a/openfpga/src/fpga_spice/spice_submodule.h b/openfpga/src/fpga_spice/spice_submodule.h index 551fd772e..5611a0c1d 100644 --- a/openfpga/src/fpga_spice/spice_submodule.h +++ b/openfpga/src/fpga_spice/spice_submodule.h @@ -4,10 +4,10 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "netlist_manager.h" #include "module_manager.h" -#include "openfpga_arch.h" #include "mux_library.h" +#include "netlist_manager.h" +#include "openfpga_arch.h" /******************************************************************** * Function declaration @@ -18,8 +18,7 @@ namespace openfpga { int print_spice_submodule(NetlistManager& netlist_manager, const ModuleManager& module_manager, - const Arch& openfpga_arch, - const MuxLibrary& mux_lib, + const Arch& openfpga_arch, const MuxLibrary& mux_lib, const std::string& submodule_dir); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_spice/spice_top_module.cpp b/openfpga/src/fpga_spice/spice_top_module.cpp index d153d9ef7..f0467861e 100644 --- a/openfpga/src/fpga_spice/spice_top_module.cpp +++ b/openfpga/src/fpga_spice/spice_top_module.cpp @@ -2,9 +2,9 @@ * This file includes functions that are used to print the top-level * module for the FPGA fabric in SPICE format *******************************************************************/ +#include #include #include -#include /* Headers from vtrutil library */ #include "vtr_assert.h" @@ -12,22 +12,20 @@ /* Headers from openfpgautil library */ #include "openfpga_digest.h" - #include "openfpga_naming.h" - #include "spice_constants.h" -#include "spice_writer_utils.h" #include "spice_subckt_writer.h" #include "spice_top_module.h" +#include "spice_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** * Print the top-level module for the FPGA fabric in SPICE format - * This function will + * This function will * 1. name the top-level module - * 2. include dependent netlists + * 2. include dependent netlists * - User defined netlists * - Auto-generated netlists * 3. Add the submodules to the top-level graph @@ -37,13 +35,16 @@ namespace openfpga { void print_spice_top_module(NetlistManager& netlist_manager, const ModuleManager& module_manager, const std::string& spice_dir) { - /* Create a module as the top-level fabric, and add it to the module manager */ + /* Create a module as the top-level fabric, and add it to the module manager + */ std::string top_module_name = generate_fpga_top_module_name(); ModuleId top_module = module_manager.find_module(top_module_name); VTR_ASSERT(true == module_manager.valid_module_id(top_module)); /* Create the file name for SPICE netlist */ - std::string spice_fname(spice_dir + generate_fpga_top_netlist_name(std::string(SPICE_NETLIST_FILE_POSTFIX))); + std::string spice_fname( + spice_dir + + generate_fpga_top_netlist_name(std::string(SPICE_NETLIST_FILE_POSTFIX))); VTR_LOG("Writing SPICE netlist for top-level module of FPGA fabric '%s'...", spice_fname.c_str()); @@ -54,7 +55,7 @@ void print_spice_top_module(NetlistManager& netlist_manager, check_file_stream(spice_fname.c_str(), fp); - print_spice_file_header(fp, std::string("Top-level SPICE subckt for FPGA")); + print_spice_file_header(fp, std::string("Top-level SPICE subckt for FPGA")); /* Write the module content in Verilog format */ write_spice_subckt_to_file(fp, module_manager, top_module); @@ -68,7 +69,8 @@ void print_spice_top_module(NetlistManager& netlist_manager, /* Add fname to the netlist name list */ NetlistId nlist_id = netlist_manager.add_netlist(spice_fname); VTR_ASSERT(NetlistId::INVALID() != nlist_id); - netlist_manager.set_netlist_type(nlist_id, NetlistManager::TOP_MODULE_NETLIST); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::TOP_MODULE_NETLIST); VTR_LOG("Done\n"); } diff --git a/openfpga/src/fpga_spice/spice_top_module.h b/openfpga/src/fpga_spice/spice_top_module.h index 9cea104cc..89c332279 100644 --- a/openfpga/src/fpga_spice/spice_top_module.h +++ b/openfpga/src/fpga_spice/spice_top_module.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "module_manager.h" #include "netlist_manager.h" diff --git a/openfpga/src/fpga_spice/spice_transistor_wrapper.cpp b/openfpga/src/fpga_spice/spice_transistor_wrapper.cpp index 6a90b0c96..721fe9faa 100644 --- a/openfpga/src/fpga_spice/spice_transistor_wrapper.cpp +++ b/openfpga/src/fpga_spice/spice_transistor_wrapper.cpp @@ -1,9 +1,9 @@ /************************************************ - * This file includes functions on + * This file includes functions on * outputting wrapper SPICE netlists for transistor ***********************************************/ -#include #include +#include #include /* Headers from vtrutil library */ @@ -14,13 +14,11 @@ #include "command_exit_codes.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - #include "circuit_library_utils.h" - +#include "openfpga_digest.h" #include "spice_constants.h" -#include "spice_writer_utils.h" #include "spice_transistor_wrapper.h" +#include "spice_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -28,30 +26,31 @@ namespace openfpga { /******************************************************************** * Print a SPICE model wrapper for a transistor model *******************************************************************/ -static -int print_spice_transistor_model_wrapper(std::fstream& fp, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& model) { - +static int print_spice_transistor_model_wrapper( + std::fstream& fp, const TechnologyLibrary& tech_lib, + const TechnologyModelId& model) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } /* Transistor model followed a fixed port mapping - * [X|M] + * [X|M] * which is a standard in SPICE modeling * We will output the pmos and nmos transistors wrappers * which are defined in this model */ for (int itype = TECH_LIB_TRANSISTOR_PMOS; - itype < NUM_TECH_LIB_TRANSISTOR_TYPES; - ++itype) { - const e_tech_lib_transistor_type& trans_type = static_cast(itype); + itype < NUM_TECH_LIB_TRANSISTOR_TYPES; ++itype) { + const e_tech_lib_transistor_type& trans_type = + static_cast(itype); fp << ".subckt "; - fp << tech_lib.transistor_model_name(model, trans_type) << TRANSISTOR_WRAPPER_POSTFIX; + fp << tech_lib.transistor_model_name(model, trans_type) + << TRANSISTOR_WRAPPER_POSTFIX; fp << " drain gate source bulk"; - fp << " L=" << std::setprecision(10) << tech_lib.transistor_model_chan_length(model, trans_type); - fp << " W=" << std::setprecision(10) << tech_lib.transistor_model_min_width(model, trans_type); + fp << " L=" << std::setprecision(10) + << tech_lib.transistor_model_chan_length(model, trans_type); + fp << " W=" << std::setprecision(10) + << tech_lib.transistor_model_min_width(model, trans_type); fp << "\n"; fp << tech_lib.model_ref(model); @@ -74,18 +73,19 @@ int print_spice_transistor_model_wrapper(std::fstream& fp, int print_spice_transistor_wrapper(NetlistManager& netlist_manager, const TechnologyLibrary& tech_lib, const std::string& submodule_dir) { - std::string spice_fname = submodule_dir + std::string(TRANSISTORS_SPICE_FILE_NAME); + std::string spice_fname = + submodule_dir + std::string(TRANSISTORS_SPICE_FILE_NAME); std::fstream fp; /* Create the file stream */ fp.open(spice_fname, std::fstream::out | std::fstream::trunc); /* Check if the file stream if valid or not */ - check_file_stream(spice_fname.c_str(), fp); + check_file_stream(spice_fname.c_str(), fp); /* Create file */ VTR_LOG("Generating SPICE netlist '%s' for transistors...", - spice_fname.c_str()); + spice_fname.c_str()); print_spice_file_header(fp, std::string("Transistor wrappers")); @@ -96,10 +96,11 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager, continue; } /* Write a wrapper for the transistor model */ - if (CMD_EXEC_SUCCESS != print_spice_transistor_model_wrapper(fp, tech_lib, model)) { + if (CMD_EXEC_SUCCESS != + print_spice_transistor_model_wrapper(fp, tech_lib, model)) { return CMD_EXEC_FATAL_ERROR; } - } + } /* Close file handler*/ fp.close(); @@ -120,32 +121,29 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager, * This function is created to be shared by pass-transistor and * transmission-gate SPICE netlist writer * - * Note: + * Note: * - This function does NOT create a file * but requires a file stream created - * - This function only output SPICE modeling for + * - This function only output SPICE modeling for * a PMOS. Any preprocessing or subckt definition should not be included! *******************************************************************/ -int print_spice_generic_pmos_modeling(std::fstream& fp, - const std::string& trans_name_postfix, - const std::string& input_port_name, - const std::string& gate_port_name, - const std::string& output_port_name, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& tech_model, - const float& trans_width) { - +int print_spice_generic_pmos_modeling( + std::fstream& fp, const std::string& trans_name_postfix, + const std::string& input_port_name, const std::string& gate_port_name, + const std::string& output_port_name, const TechnologyLibrary& tech_lib, + const TechnologyModelId& tech_model, const float& trans_width) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } /* Write transistor pairs using the technology model */ fp << "Xpmos_" << trans_name_postfix << " "; - fp << input_port_name << " "; - fp << gate_port_name << " "; - fp << output_port_name << " "; - fp << SPICE_SUBCKT_VDD_PORT_NAME << " "; - fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX; + fp << input_port_name << " "; + fp << gate_port_name << " "; + fp << output_port_name << " "; + fp << SPICE_SUBCKT_VDD_PORT_NAME << " "; + fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) + << TRANSISTOR_WRAPPER_POSTFIX; fp << " W=" << std::setprecision(10) << trans_width; fp << "\n"; @@ -155,36 +153,32 @@ int print_spice_generic_pmos_modeling(std::fstream& fp, /******************************************************************** * Generate the SPICE modeling for the NMOS part of a logic gate * - * Note: + * Note: * - This function does NOT create a file * but requires a file stream created - * - This function only output SPICE modeling for + * - This function only output SPICE modeling for * a NMOS. Any preprocessing or subckt definition should not be included! *******************************************************************/ -int print_spice_generic_nmos_modeling(std::fstream& fp, - const std::string& trans_name_postfix, - const std::string& input_port_name, - const std::string& gate_port_name, - const std::string& output_port_name, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& tech_model, - const float& trans_width) { - +int print_spice_generic_nmos_modeling( + std::fstream& fp, const std::string& trans_name_postfix, + const std::string& input_port_name, const std::string& gate_port_name, + const std::string& output_port_name, const TechnologyLibrary& tech_lib, + const TechnologyModelId& tech_model, const float& trans_width) { if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } fp << "Xnmos_" << trans_name_postfix << " "; - fp << input_port_name << " "; - fp << gate_port_name << " "; - fp << output_port_name << " "; - fp << SPICE_SUBCKT_GND_PORT_NAME << " "; - fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX; + fp << input_port_name << " "; + fp << gate_port_name << " "; + fp << output_port_name << " "; + fp << SPICE_SUBCKT_GND_PORT_NAME << " "; + fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) + << TRANSISTOR_WRAPPER_POSTFIX; fp << " W=" << std::setprecision(10) << trans_width; fp << "\n"; return CMD_EXEC_SUCCESS; } - } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_spice/spice_transistor_wrapper.h b/openfpga/src/fpga_spice/spice_transistor_wrapper.h index 7b3bef199..7fa298140 100644 --- a/openfpga/src/fpga_spice/spice_transistor_wrapper.h +++ b/openfpga/src/fpga_spice/spice_transistor_wrapper.h @@ -4,8 +4,9 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include #include +#include + #include "netlist_manager.h" #include "technology_library.h" @@ -20,23 +21,17 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager, const TechnologyLibrary& tech_lib, const std::string& submodule_dir); -int print_spice_generic_pmos_modeling(std::fstream& fp, - const std::string& trans_name_postfix, - const std::string& input_port_name, - const std::string& gate_port_name, - const std::string& output_port_name, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& tech_model, - const float& trans_width); +int print_spice_generic_pmos_modeling( + std::fstream& fp, const std::string& trans_name_postfix, + const std::string& input_port_name, const std::string& gate_port_name, + const std::string& output_port_name, const TechnologyLibrary& tech_lib, + const TechnologyModelId& tech_model, const float& trans_width); -int print_spice_generic_nmos_modeling(std::fstream& fp, - const std::string& trans_name_postfix, - const std::string& input_port_name, - const std::string& gate_port_name, - const std::string& output_port_name, - const TechnologyLibrary& tech_lib, - const TechnologyModelId& tech_model, - const float& trans_width); +int print_spice_generic_nmos_modeling( + std::fstream& fp, const std::string& trans_name_postfix, + const std::string& input_port_name, const std::string& gate_port_name, + const std::string& output_port_name, const TechnologyLibrary& tech_lib, + const TechnologyModelId& tech_model, const float& trans_width); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_spice/spice_wire.cpp b/openfpga/src/fpga_spice/spice_wire.cpp index 097515899..d3eb8635f 100644 --- a/openfpga/src/fpga_spice/spice_wire.cpp +++ b/openfpga/src/fpga_spice/spice_wire.cpp @@ -1,11 +1,11 @@ /************************************************ - * This file includes functions on + * This file includes functions on * outputting SPICE netlists for routing wires: * - regular wires (1 input and 1 output) * - routing track wires (1 input and 2 outputs) ***********************************************/ -#include #include +#include #include /* Headers from vtrutil library */ @@ -16,14 +16,12 @@ #include "command_exit_codes.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - -#include "circuit_library_utils.h" #include "build_module_graph_utils.h" - +#include "circuit_library_utils.h" +#include "openfpga_digest.h" #include "spice_constants.h" -#include "spice_writer_utils.h" #include "spice_wire.h" +#include "spice_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -34,35 +32,34 @@ namespace openfpga { * Schematic * middle out * | - * in ---wwww----wwww--- ... --wwww---out + * in ---wwww----wwww--- ... --wwww---out * | | | | * = = = = * | | | | * GND GND GND GND *******************************************************************/ -static -int print_spice_wire_pi_type_rc_modeling(std::fstream& fp, - const std::string& input_port_name, - const std::string& output_port_name, - const std::string& middle_output_port_name, - const float& res_total, - const float& cap_total, - const size_t& num_levels) { - +static int print_spice_wire_pi_type_rc_modeling( + std::fstream& fp, const std::string& input_port_name, + const std::string& output_port_name, + const std::string& middle_output_port_name, const float& res_total, + const float& cap_total, const size_t& num_levels) { /* Determine the resistance and capacitance of each level*/ float res_per_level = res_total / ((float)(2 * num_levels)); float cap_per_level = cap_total / ((float)(2 * num_levels)); - /* All the resistance and capacitance value should be larger than or equal to zero*/ + /* All the resistance and capacitance value should be larger than or equal to + * zero*/ VTR_ASSERT(0. <= res_per_level); VTR_ASSERT(0. <= cap_per_level); for (size_t ilvl = 0; ilvl < num_levels; ++ilvl) { /* Print the first capacitor if this is the first level */ if ((0 == ilvl) && (0. < cap_per_level)) { - print_spice_capacitor(fp, input_port_name, std::string(SPICE_SUBCKT_GND_PORT_NAME), cap_per_level); + print_spice_capacitor(fp, input_port_name, + std::string(SPICE_SUBCKT_GND_PORT_NAME), + cap_per_level); } - /* Output a regular RC pair + /* Output a regular RC pair * * midnode * ^ @@ -74,20 +71,25 @@ int print_spice_wire_pi_type_rc_modeling(std::fstream& fp, * GND GND */ - std::string lvl_input_port_name = std::string("rc_network_node") + std::to_string(ilvl); + std::string lvl_input_port_name = + std::string("rc_network_node") + std::to_string(ilvl); if (0 == ilvl) { lvl_input_port_name = input_port_name; - } + } - std::string lvl_middle_port_name = std::string("rc_network_midnode") + std::to_string(ilvl); + std::string lvl_middle_port_name = + std::string("rc_network_midnode") + std::to_string(ilvl); - std::string lvl_output_port_name = std::string("rc_network_node") + std::to_string(ilvl + 1); + std::string lvl_output_port_name = + std::string("rc_network_node") + std::to_string(ilvl + 1); if (ilvl == num_levels - 1) { lvl_output_port_name = output_port_name; } - print_spice_resistor(fp, lvl_input_port_name, lvl_middle_port_name, res_per_level); - print_spice_resistor(fp, lvl_middle_port_name, lvl_output_port_name, res_per_level); + print_spice_resistor(fp, lvl_input_port_name, lvl_middle_port_name, + res_per_level); + print_spice_resistor(fp, lvl_middle_port_name, lvl_output_port_name, + res_per_level); /* Last level only require 1 unit of cap_per_level */ float cap_curr_level = 2. * cap_per_level; @@ -96,7 +98,9 @@ int print_spice_wire_pi_type_rc_modeling(std::fstream& fp, } if (0. < cap_curr_level) { - print_spice_capacitor(fp, lvl_output_port_name, std::string(SPICE_SUBCKT_GND_PORT_NAME), cap_curr_level); + print_spice_capacitor(fp, lvl_output_port_name, + std::string(SPICE_SUBCKT_GND_PORT_NAME), + cap_curr_level); } } @@ -113,7 +117,7 @@ int print_spice_wire_pi_type_rc_modeling(std::fstream& fp, * GND GND * * - when the number of levels is even: - * + * * middle_output * ^ * | @@ -122,15 +126,17 @@ int print_spice_wire_pi_type_rc_modeling(std::fstream& fp, * = = = * | | | * GND GND GND - * + * */ if (!middle_output_port_name.empty()) { print_spice_comment(fp, std::string("Connect to the middle output")); - std::string rc_midnode_name = std::string("rc_network_node") + std::to_string(num_levels / 2 + 1); + std::string rc_midnode_name = + std::string("rc_network_node") + std::to_string(num_levels / 2 + 1); if (1 == num_levels % 2) { - rc_midnode_name = std::string("rc_network_midnode") + std::to_string(num_levels / 2); + rc_midnode_name = + std::string("rc_network_midnode") + std::to_string(num_levels / 2); } - print_spice_short_connection(fp, rc_midnode_name, middle_output_port_name); + print_spice_short_connection(fp, rc_midnode_name, middle_output_port_name); } return CMD_EXEC_SUCCESS; @@ -142,59 +148,63 @@ int print_spice_wire_pi_type_rc_modeling(std::fstream& fp, * Schematic * middle out * | - * in ---ww-+--ww--+--ww--+--ww--- ... --ww--+--ww--- out + * in ---ww-+--ww--+--ww--+--ww--- ... --ww--+--ww--- out * | | | | * = = = = * | | | | * GND GND GND GND *******************************************************************/ -static -int print_spice_wire_t_type_rc_modeling(std::fstream& fp, - const std::string& input_port_name, - const std::string& output_port_name, - const std::string& middle_output_port_name, - const float& res_total, - const float& cap_total, - const size_t& num_levels) { - +static int print_spice_wire_t_type_rc_modeling( + std::fstream& fp, const std::string& input_port_name, + const std::string& output_port_name, + const std::string& middle_output_port_name, const float& res_total, + const float& cap_total, const size_t& num_levels) { /* Determine the resistance and capacitance of each level*/ float res_per_level = res_total / ((float)(2 * num_levels)); float cap_per_level = cap_total / ((float)(num_levels)); - /* All the resistance and capacitance value should be larger than or equal to zero*/ + /* All the resistance and capacitance value should be larger than or equal to + * zero*/ VTR_ASSERT(0. <= res_per_level); VTR_ASSERT(0. <= cap_per_level); for (size_t ilvl = 0; ilvl < num_levels; ++ilvl) { - /* Output a regular RC pair + /* Output a regular RC pair * * midnode * ^ * | * --------ww-+-ww-------- - * | - * = - * | - * GND + * | + * = + * | + * GND */ - std::string lvl_input_port_name = std::string("rc_network_node") + std::to_string(ilvl); + std::string lvl_input_port_name = + std::string("rc_network_node") + std::to_string(ilvl); if (0 == ilvl) { lvl_input_port_name = input_port_name; - } + } - std::string lvl_middle_port_name = std::string("rc_network_midnode") + std::to_string(ilvl); + std::string lvl_middle_port_name = + std::string("rc_network_midnode") + std::to_string(ilvl); - std::string lvl_output_port_name = std::string("rc_network_node") + std::to_string(ilvl + 1); + std::string lvl_output_port_name = + std::string("rc_network_node") + std::to_string(ilvl + 1); if (ilvl == num_levels - 1) { lvl_output_port_name = output_port_name; } - print_spice_resistor(fp, lvl_input_port_name, lvl_middle_port_name, res_per_level); - print_spice_resistor(fp, lvl_middle_port_name, lvl_output_port_name, res_per_level); + print_spice_resistor(fp, lvl_input_port_name, lvl_middle_port_name, + res_per_level); + print_spice_resistor(fp, lvl_middle_port_name, lvl_output_port_name, + res_per_level); if (0. < cap_per_level) { - print_spice_capacitor(fp, lvl_middle_port_name, std::string(SPICE_SUBCKT_GND_PORT_NAME), cap_per_level); + print_spice_capacitor(fp, lvl_middle_port_name, + std::string(SPICE_SUBCKT_GND_PORT_NAME), + cap_per_level); } } @@ -211,7 +221,7 @@ int print_spice_wire_t_type_rc_modeling(std::fstream& fp, * GND GND * * - when the number of levels is odd: - * + * * middle_output * ^ * | @@ -220,21 +230,22 @@ int print_spice_wire_t_type_rc_modeling(std::fstream& fp, * = = = * | | | * GND GND GND - * + * */ if (!middle_output_port_name.empty()) { print_spice_comment(fp, std::string("Connect to the middle output")); - std::string rc_midnode_name = std::string("rc_network_midnode") + std::to_string(num_levels / 2); + std::string rc_midnode_name = + std::string("rc_network_midnode") + std::to_string(num_levels / 2); if (0 == num_levels % 2) { - rc_midnode_name = std::string("rc_network_node") + std::to_string(num_levels / 2 + 1); + rc_midnode_name = + std::string("rc_network_node") + std::to_string(num_levels / 2 + 1); } - print_spice_short_connection(fp, rc_midnode_name, middle_output_port_name); + print_spice_short_connection(fp, rc_midnode_name, middle_output_port_name); } return CMD_EXEC_SUCCESS; } - /******************************************************************** * Generate the SPICE subckt for a regular wire * @@ -244,39 +255,42 @@ int print_spice_wire_t_type_rc_modeling(std::fstream& fp, * ^ * | * +--------------------+ +---------------+ +--------------------+ - * in ->| Inverter or buffer |--->| RC Network |---->| Inverter or buffer |---> out - * | Optional | | | | Optional | + * in ->| Inverter or buffer |--->| RC Network |---->| Inverter or buffer + *|---> out | Optional | | | | Optional | * +--------------------- +---------------+ +--------------------+ - * + * *******************************************************************/ int print_spice_wire_subckt(std::fstream& fp, const ModuleManager& module_manager, const ModuleId& module_id, const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model) { - - if (false == valid_file_stream(fp)) { + if (false == valid_file_stream(fp)) { return CMD_EXEC_FATAL_ERROR; } /* Find the input and output ports: - * we do NOT support global ports here, + * we do NOT support global ports here, * it should be handled in another type of inverter subckt (power-gated) */ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); /* Make sure: - * There are 1 input ports and 1 output port, + * There are 1 input ports and 1 output port, * each size of which is 1 */ - VTR_ASSERT( (1 == input_ports.size()) && (1 == circuit_lib.port_size(input_ports[0])) ); - VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + VTR_ASSERT((1 == input_ports.size()) && + (1 == circuit_lib.port_size(input_ports[0]))); + VTR_ASSERT((1 == output_ports.size()) && + (1 == circuit_lib.port_size(output_ports[0]))); int status = CMD_EXEC_SUCCESS; /* Print the inverter subckt definition */ - print_spice_subckt_definition(fp, module_manager, module_id); + print_spice_subckt_definition(fp, module_manager, module_id); std::string input_port_name = circuit_lib.port_prefix(input_ports[0]); std::string output_port_name = circuit_lib.port_prefix(output_ports[0]); @@ -285,18 +299,25 @@ int print_spice_wire_subckt(std::fstream& fp, middle_output_port_name = std::string("middle") + output_port_name; } - std::string rc_ntwk_input_port_name = std::string("rc_network_node") + std::to_string(0); - std::string rc_ntwk_output_port_name = std::string("rc_network_node") + std::to_string(circuit_lib.wire_num_level(circuit_model) - 1); + std::string rc_ntwk_input_port_name = + std::string("rc_network_node") + std::to_string(0); + std::string rc_ntwk_output_port_name = + std::string("rc_network_node") + + std::to_string(circuit_lib.wire_num_level(circuit_model) - 1); std::string rc_ntwk_middle_output_port_name; if (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(circuit_model)) { - rc_ntwk_middle_output_port_name = std::string("middle") + rc_ntwk_output_port_name; + rc_ntwk_middle_output_port_name = + std::string("middle") + rc_ntwk_output_port_name; } - - ModulePortId wire_module_input_port = module_manager.find_module_port(module_id, input_port_name); - ModulePortId wire_module_output_port = module_manager.find_module_port(module_id, output_port_name); + + ModulePortId wire_module_input_port = + module_manager.find_module_port(module_id, input_port_name); + ModulePortId wire_module_output_port = + module_manager.find_module_port(module_id, output_port_name); ModulePortId wire_module_middle_output_port = ModulePortId::INVALID(); if (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(circuit_model)) { - wire_module_middle_output_port = module_manager.find_module_port(module_id, output_port_name); + wire_module_middle_output_port = + module_manager.find_module_port(module_id, output_port_name); } /* Add input buffer: @@ -307,54 +328,62 @@ int print_spice_wire_subckt(std::fstream& fp, std::string instance_name = std::string("input_buffer"); std::map port2port_name_map; - ModuleId buffer_module = module_manager.find_module(circuit_lib.model_name(circuit_lib.input_buffer_model(circuit_model))); + ModuleId buffer_module = module_manager.find_module( + circuit_lib.model_name(circuit_lib.input_buffer_model(circuit_model))); VTR_ASSERT(true == module_manager.valid_module_id(buffer_module)); - - ModulePortId module_input_port_id = find_inverter_buffer_module_port(module_manager, buffer_module, circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_INPUT); - ModulePortId module_output_port_id = find_inverter_buffer_module_port(module_manager, buffer_module, circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_OUTPUT); + + ModulePortId module_input_port_id = find_inverter_buffer_module_port( + module_manager, buffer_module, circuit_lib, circuit_model, + CIRCUIT_MODEL_PORT_INPUT); + ModulePortId module_output_port_id = find_inverter_buffer_module_port( + module_manager, buffer_module, circuit_lib, circuit_model, + CIRCUIT_MODEL_PORT_OUTPUT); /* Port size should be 1 ! */ - VTR_ASSERT(1 == module_manager.module_port(buffer_module, module_input_port_id).get_width()); - VTR_ASSERT(1 == module_manager.module_port(buffer_module, module_output_port_id).get_width()); + VTR_ASSERT(1 == + module_manager.module_port(buffer_module, module_input_port_id) + .get_width()); + VTR_ASSERT(1 == + module_manager.module_port(buffer_module, module_output_port_id) + .get_width()); - port2port_name_map[module_manager.module_port(buffer_module, module_input_port_id).get_name()] = module_manager.module_port(module_id, wire_module_input_port); - port2port_name_map[module_manager.module_port(buffer_module, module_output_port_id).get_name()] = BasicPort(rc_ntwk_input_port_name, 1); + port2port_name_map[module_manager + .module_port(buffer_module, module_input_port_id) + .get_name()] = + module_manager.module_port(module_id, wire_module_input_port); + port2port_name_map[module_manager + .module_port(buffer_module, module_output_port_id) + .get_name()] = BasicPort(rc_ntwk_input_port_name, 1); - print_spice_subckt_instance(fp, - module_manager, - buffer_module, - instance_name, - port2port_name_map); + print_spice_subckt_instance(fp, module_manager, buffer_module, + instance_name, port2port_name_map); } else { - print_spice_short_connection(fp, circuit_lib.port_prefix(input_ports[0]), rc_ntwk_input_port_name); + print_spice_short_connection(fp, circuit_lib.port_prefix(input_ports[0]), + rc_ntwk_input_port_name); } /* Determine which type of model to print*/ switch (circuit_lib.wire_type(circuit_model)) { - case WIRE_MODEL_PI: - status = print_spice_wire_pi_type_rc_modeling(fp, - rc_ntwk_input_port_name, - rc_ntwk_output_port_name, - rc_ntwk_middle_output_port_name, - circuit_lib.wire_r(circuit_model), - circuit_lib.wire_c(circuit_model), - circuit_lib.wire_num_level(circuit_model)); - break; - case WIRE_MODEL_T: - status = print_spice_wire_t_type_rc_modeling(fp, - rc_ntwk_input_port_name, - rc_ntwk_output_port_name, - rc_ntwk_middle_output_port_name, - circuit_lib.wire_r(circuit_model), - circuit_lib.wire_c(circuit_model), - circuit_lib.wire_num_level(circuit_model)); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Unsupport wire model type for circuit model '%s.\n", - circuit_lib.model_name(circuit_model).c_str()); - return CMD_EXEC_FATAL_ERROR; - } + case WIRE_MODEL_PI: + status = print_spice_wire_pi_type_rc_modeling( + fp, rc_ntwk_input_port_name, rc_ntwk_output_port_name, + rc_ntwk_middle_output_port_name, circuit_lib.wire_r(circuit_model), + circuit_lib.wire_c(circuit_model), + circuit_lib.wire_num_level(circuit_model)); + break; + case WIRE_MODEL_T: + status = print_spice_wire_t_type_rc_modeling( + fp, rc_ntwk_input_port_name, rc_ntwk_output_port_name, + rc_ntwk_middle_output_port_name, circuit_lib.wire_r(circuit_model), + circuit_lib.wire_c(circuit_model), + circuit_lib.wire_num_level(circuit_model)); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Unsupport wire model type for circuit model '%s.\n", + circuit_lib.model_name(circuit_model).c_str()); + return CMD_EXEC_FATAL_ERROR; + } /* Add output buffer: * - There is a valid buffer model, instanciate it @@ -364,43 +393,56 @@ int print_spice_wire_subckt(std::fstream& fp, std::string instance_name = std::string("output_buffer"); std::map port2port_name_map; - ModuleId buffer_module = module_manager.find_module(circuit_lib.model_name(circuit_lib.output_buffer_model(circuit_model))); + ModuleId buffer_module = module_manager.find_module( + circuit_lib.model_name(circuit_lib.output_buffer_model(circuit_model))); VTR_ASSERT(true == module_manager.valid_module_id(buffer_module)); - - ModulePortId module_input_port_id = find_inverter_buffer_module_port(module_manager, buffer_module, circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_INPUT); - ModulePortId module_output_port_id = find_inverter_buffer_module_port(module_manager, buffer_module, circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_OUTPUT); + + ModulePortId module_input_port_id = find_inverter_buffer_module_port( + module_manager, buffer_module, circuit_lib, circuit_model, + CIRCUIT_MODEL_PORT_INPUT); + ModulePortId module_output_port_id = find_inverter_buffer_module_port( + module_manager, buffer_module, circuit_lib, circuit_model, + CIRCUIT_MODEL_PORT_OUTPUT); /* Port size should be 1 ! */ - VTR_ASSERT(1 == module_manager.module_port(buffer_module, module_input_port_id).get_width()); - VTR_ASSERT(1 == module_manager.module_port(buffer_module, module_output_port_id).get_width()); + VTR_ASSERT(1 == + module_manager.module_port(buffer_module, module_input_port_id) + .get_width()); + VTR_ASSERT(1 == + module_manager.module_port(buffer_module, module_output_port_id) + .get_width()); - port2port_name_map[module_manager.module_port(buffer_module, module_input_port_id).get_name()] = BasicPort(rc_ntwk_output_port_name, 1); - port2port_name_map[module_manager.module_port(buffer_module, module_output_port_id).get_name()] = module_manager.module_port(module_id, wire_module_output_port); + port2port_name_map[module_manager + .module_port(buffer_module, module_input_port_id) + .get_name()] = BasicPort(rc_ntwk_output_port_name, 1); + port2port_name_map[module_manager + .module_port(buffer_module, module_output_port_id) + .get_name()] = + module_manager.module_port(module_id, wire_module_output_port); - print_spice_subckt_instance(fp, - module_manager, - buffer_module, - instance_name, - port2port_name_map); + print_spice_subckt_instance(fp, module_manager, buffer_module, + instance_name, port2port_name_map); if (!rc_ntwk_middle_output_port_name.empty()) { instance_name = std::string("middle_output_buffer"); - port2port_name_map[module_manager.module_port(buffer_module, module_output_port_id).get_name()] = module_manager.module_port(module_id, wire_module_middle_output_port); + port2port_name_map[module_manager + .module_port(buffer_module, module_output_port_id) + .get_name()] = + module_manager.module_port(module_id, wire_module_middle_output_port); - print_spice_subckt_instance(fp, - module_manager, - buffer_module, - instance_name, - port2port_name_map); + print_spice_subckt_instance(fp, module_manager, buffer_module, + instance_name, port2port_name_map); } } else { - print_spice_short_connection(fp, rc_ntwk_output_port_name, circuit_lib.port_prefix(output_ports[0])); + print_spice_short_connection(fp, rc_ntwk_output_port_name, + circuit_lib.port_prefix(output_ports[0])); if (!rc_ntwk_middle_output_port_name.empty()) { - print_spice_short_connection(fp, rc_ntwk_middle_output_port_name, circuit_lib.port_prefix(output_ports[0])); + print_spice_short_connection(fp, rc_ntwk_middle_output_port_name, + circuit_lib.port_prefix(output_ports[0])); } } - print_spice_subckt_end(fp, module_manager.module_name(module_id)); + print_spice_subckt_end(fp, module_manager.module_name(module_id)); return status; } diff --git a/openfpga/src/fpga_spice/spice_wire.h b/openfpga/src/fpga_spice/spice_wire.h index 5af9542a0..4e733a004 100644 --- a/openfpga/src/fpga_spice/spice_wire.h +++ b/openfpga/src/fpga_spice/spice_wire.h @@ -4,10 +4,11 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include #include -#include "module_manager.h" +#include + #include "circuit_library.h" +#include "module_manager.h" /******************************************************************** * Function declaration diff --git a/openfpga/src/fpga_spice/spice_writer_utils.cpp b/openfpga/src/fpga_spice/spice_writer_utils.cpp index 68d3360b1..8acf73fb7 100644 --- a/openfpga/src/fpga_spice/spice_writer_utils.cpp +++ b/openfpga/src/fpga_spice/spice_writer_utils.cpp @@ -1,12 +1,12 @@ /************************************************ * Include functions for most frequently - * used Spice writers + * used Spice writers ***********************************************/ #include #include -#include #include #include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" @@ -17,7 +17,6 @@ /* Headers from openfpgautil library */ #include "openfpga_digest.h" - #include "spice_constants.h" #include "spice_writer_utils.h" @@ -26,13 +25,12 @@ namespace openfpga { /************************************************ * Generate header comments for a Spice netlist - * include the description + * include the description ***********************************************/ -void print_spice_file_header(std::fstream& fp, - const std::string& usage) { +void print_spice_file_header(std::fstream& fp, const std::string& usage) { VTR_ASSERT(true == valid_file_stream(fp)); - - auto end = std::chrono::system_clock::now(); + + auto end = std::chrono::system_clock::now(); std::time_t end_time = std::chrono::system_clock::to_time_t(end); fp << "*********************************************" << std::endl; @@ -40,26 +38,25 @@ void print_spice_file_header(std::fstream& fp, fp << "*\tDescription: " << usage << std::endl; fp << "*\tAuthor: Xifan TANG" << std::endl; fp << "*\tOrganization: University of Utah" << std::endl; - fp << "*\tDate: " << std::ctime(&end_time) ; + fp << "*\tDate: " << std::ctime(&end_time); fp << "*********************************************" << std::endl; fp << std::endl; } /******************************************************************** - * Print Spice codes to include a netlist + * Print Spice codes to include a netlist *******************************************************************/ -void print_spice_include_netlist(std::fstream& fp, +void print_spice_include_netlist(std::fstream& fp, const std::string& netlist_name) { VTR_ASSERT(true == valid_file_stream(fp)); - fp << ".include \"" << netlist_name << "\"" << std::endl; + fp << ".include \"" << netlist_name << "\"" << std::endl; } /************************************************ * Print a Spice comment line ***********************************************/ -void print_spice_comment(std::fstream& fp, - const std::string& comment) { +void print_spice_comment(std::fstream& fp, const std::string& comment) { VTR_ASSERT(true == valid_file_stream(fp)); std::string comment_cover(comment.length() + 4, '*'); @@ -68,7 +65,6 @@ void print_spice_comment(std::fstream& fp, fp << comment_cover << std::endl; } - /************************************************ * Generate a string for a port in SPICE format * If the pin id is zero, e.g., A[0], the option @@ -81,8 +77,7 @@ std::string generate_spice_port(const BasicPort& port, std::string ret = port.get_name(); - if ((true == omit_pin_zero) - && (0 == port.get_lsb())) { + if ((true == omit_pin_zero) && (0 == port.get_lsb())) { return ret; } @@ -98,47 +93,49 @@ std::string generate_spice_port(const BasicPort& port, * We use the following format: * module (); ***********************************************/ -void print_spice_subckt_definition(std::fstream& fp, +void print_spice_subckt_definition(std::fstream& fp, const ModuleManager& module_manager, const ModuleId& module_id, const bool& include_supply_ports) { VTR_ASSERT(true == valid_file_stream(fp)); - print_spice_comment(fp, std::string("SPICE module for " + module_manager.module_name(module_id))); + print_spice_comment(fp, std::string("SPICE module for " + + module_manager.module_name(module_id))); - std::string module_head_line = ".subckt " + module_manager.module_name(module_id) + " "; + std::string module_head_line = + ".subckt " + module_manager.module_name(module_id) + " "; fp << module_head_line; /* Port sequence: global, inout, input, output and clock ports, */ bool new_line = false; size_t pin_cnt = 0; for (int port_type = ModuleManager::MODULE_GLOBAL_PORT; - port_type < ModuleManager::NUM_MODULE_PORT_TYPES; - ++port_type) { - for (const auto& port : module_manager.module_ports_by_type(module_id, static_cast(port_type))) { - ModulePortId port_id = module_manager.find_module_port(module_id, port.get_name()); + port_type < ModuleManager::NUM_MODULE_PORT_TYPES; ++port_type) { + for (const auto& port : module_manager.module_ports_by_type( + module_id, + static_cast(port_type))) { + ModulePortId port_id = + module_manager.find_module_port(module_id, port.get_name()); VTR_ASSERT(ModulePortId::INVALID() != port_id); /* Print port: only the port name is enough */ for (const auto& pin : port.pins()) { - if (true == new_line) { std::string port_whitespace(module_head_line.length() - 2, ' '); fp << "+ " << port_whitespace; } - + if (0 != pin_cnt) { write_space_to_file(fp, 1); } - + BasicPort port_pin(port.get_name(), pin, pin); /* For single-bit port, * we can print the port name directly */ bool omit_pin_zero = false; - if ((1 == port.pins().size()) - && (0 == pin)) { + if ((1 == port.pins().size()) && (0 == pin)) { omit_pin_zero = true; } fp << generate_spice_port(port_pin, omit_pin_zero); @@ -156,7 +153,7 @@ void print_spice_subckt_definition(std::fstream& fp, } } } - + /* Add supply ports if specified */ if (true == include_supply_ports) { /* Print VDD and VSS ports @@ -178,26 +175,25 @@ void print_spice_subckt_definition(std::fstream& fp, /************************************************ * Print an end line for a Spice module ***********************************************/ -void print_spice_subckt_end(std::fstream& fp, - const std::string& module_name) { +void print_spice_subckt_end(std::fstream& fp, const std::string& module_name) { VTR_ASSERT(true == valid_file_stream(fp)); fp << ".ends" << std::endl; - print_spice_comment(fp, std::string("***** END SPICE module for " + module_name + " *****")); + print_spice_comment( + fp, std::string("***** END SPICE module for " + module_name + " *****")); fp << std::endl; } /************************************************ * Print a resistor in SPICE syntax ***********************************************/ -void print_spice_resistor(std::fstream& fp, - const std::string& input_port, +void print_spice_resistor(std::fstream& fp, const std::string& input_port, const std::string& output_port, const float& resistance) { VTR_ASSERT(true == valid_file_stream(fp)); /* Set an unique name to the resistor */ - fp << "R" << input_port << "_to_" << output_port; + fp << "R" << input_port << "_to_" << output_port; fp << " " << input_port; fp << " " << output_port; fp << " " << std::setprecision(10) << resistance; @@ -207,14 +203,13 @@ void print_spice_resistor(std::fstream& fp, /************************************************ * Print a capacitor in SPICE syntax ***********************************************/ -void print_spice_capacitor(std::fstream& fp, - const std::string& input_port, - const std::string& output_port, - const float& capacitance) { +void print_spice_capacitor(std::fstream& fp, const std::string& input_port, + const std::string& output_port, + const float& capacitance) { VTR_ASSERT(true == valid_file_stream(fp)); /* Set an unique name to the capacitor */ - fp << "C" << input_port << "_to_" << output_port; + fp << "C" << input_port << "_to_" << output_port; fp << " " << input_port; fp << " " << output_port; fp << " " << std::setprecision(10) << capacitance; @@ -234,80 +229,82 @@ void print_spice_short_connection(std::fstream& fp, * Print an instance in SPICE format (a generic version) * This function will require user to provide an instance name * - * This function will output the port map by referring to a port-to-port + * This function will output the port map by referring to a port-to-port * mapping: * -> - * The key of the port-to-port mapping is the port name of the module: + * The key of the port-to-port mapping is the port name of the module: * The value of the port-to-port mapping is the port information of the instance - * With link between module and instance, the function can output a SPICE + * With link between module and instance, the function can output a SPICE * instance easily, by following the define port sequence of the module * - * Note that, it is not necessary that the port-to-port mapping + * Note that, it is not necessary that the port-to-port mapping * covers all the module ports. - * Any instance/module port which are not specified in the port-to-port + * Any instance/module port which are not specified in the port-to-port * mapping will be output by the module port name. *******************************************************************/ -void print_spice_subckt_instance(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const std::string& instance_name, - const std::map& port2port_name_map) { - +void print_spice_subckt_instance( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const std::string& instance_name, + const std::map& port2port_name_map) { VTR_ASSERT(true == valid_file_stream(fp)); - /* Check: all the key ports in the port2port_name_map does exist in the child module */ + /* Check: all the key ports in the port2port_name_map does exist in the child + * module */ for (const auto& kv : port2port_name_map) { - ModulePortId module_port_id = module_manager.find_module_port(module_id, kv.first); + ModulePortId module_port_id = + module_manager.find_module_port(module_id, kv.first); VTR_ASSERT(ModulePortId::INVALID() != module_port_id); } /* Print instance name */ std::string instance_head_line = "X " + instance_name + " "; fp << instance_head_line; - + /* Port sequence: global, inout, input, output and clock ports, */ bool fit_one_line = true; bool new_line = false; size_t pin_cnt = 0; for (int port_type = ModuleManager::MODULE_GLOBAL_PORT; - port_type < ModuleManager::NUM_MODULE_PORT_TYPES; - ++port_type) { - for (const auto& port : module_manager.module_ports_by_type(module_id, static_cast(port_type))) { + port_type < ModuleManager::NUM_MODULE_PORT_TYPES; ++port_type) { + for (const auto& port : module_manager.module_ports_by_type( + module_id, + static_cast(port_type))) { /* Deposit a default port name */ BasicPort port_to_print = port; /* Try to find the instanced port name in the name map */ auto port_search_result = port2port_name_map.find(port.get_name()); if (port_search_result != port2port_name_map.end()) { - /* Found it, we assign the port name */ + /* Found it, we assign the port name */ /* TODO: make sure the port width matches! */ - ModulePortId module_port_id = module_manager.find_module_port(module_id, port.get_name()); + ModulePortId module_port_id = + module_manager.find_module_port(module_id, port.get_name()); /* Get the port from module */ - BasicPort module_port = module_manager.module_port(module_id, module_port_id); - VTR_ASSERT(module_port.get_width() == port_search_result->second.get_width()); + BasicPort module_port = + module_manager.module_port(module_id, module_port_id); + VTR_ASSERT(module_port.get_width() == + port_search_result->second.get_width()); port_to_print = port_search_result->second; } /* Print port: only the port name is enough */ for (const auto& pin : port_to_print.pins()) { - if (true == new_line) { std::string port_whitespace(instance_head_line.length() - 2, ' '); fp << "+ " << port_whitespace; } - + if (0 != pin_cnt) { write_space_to_file(fp, 1); } - + BasicPort port_pin(port.get_name(), pin, pin); /* For single-bit port, * we can print the port name directly */ bool omit_pin_zero = false; - if ((1 == port.pins().size()) - && (0 == pin)) { + if ((1 == port.pins().size()) && (0 == pin)) { omit_pin_zero = true; } @@ -351,8 +348,9 @@ void print_spice_subckt_instance(std::fstream& fp, fit_one_line = false; } - /* Print module name: - * if port print cannot fit one line, we create a new line for the module for a clean format + /* Print module name: + * if port print cannot fit one line, we create a new line for the module for + * a clean format */ if (false == fit_one_line) { fp << std::endl; @@ -360,7 +358,7 @@ void print_spice_subckt_instance(std::fstream& fp, } write_space_to_file(fp, 1); fp << module_manager.module_name(module_id); - + /* Print an end to the instance */ fp << std::endl; } diff --git a/openfpga/src/fpga_spice/spice_writer_utils.h b/openfpga/src/fpga_spice/spice_writer_utils.h index a3617a43a..d454f9a02 100644 --- a/openfpga/src/fpga_spice/spice_writer_utils.h +++ b/openfpga/src/fpga_spice/spice_writer_utils.h @@ -1,20 +1,21 @@ /************************************************ * Header file for spice_writer_utils.cpp * Include function declaration for most frequently - * used Verilog writers + * used Verilog writers ***********************************************/ -#ifndef SPICE_WRITER_UTILS_H -#define SPICE_WRITER_UTILS_H +#ifndef SPICE_WRITER_UTILS_H +#define SPICE_WRITER_UTILS_H /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ #include -#include #include -#include "openfpga_port.h" +#include + #include "circuit_library.h" #include "module_manager.h" +#include "openfpga_port.h" /******************************************************************** * Function declaration @@ -25,50 +26,45 @@ namespace openfpga { /* Tips: for naming your function in this header/source file * If a function outputs to a file, its name should begin with "print_spice" - * If a function creates a string without outputting to a file, its name should begin with "generate_spice" - * Please show respect to this naming convention, in order to keep a clean header/source file - * as well maintain a easy way to identify the functions + * If a function creates a string without outputting to a file, its name should + * begin with "generate_spice" Please show respect to this naming convention, in + * order to keep a clean header/source file as well maintain a easy way to + * identify the functions */ -void print_spice_file_header(std::fstream& fp, - const std::string& usage); +void print_spice_file_header(std::fstream& fp, const std::string& usage); -void print_spice_include_netlist(std::fstream& fp, +void print_spice_include_netlist(std::fstream& fp, const std::string& netlist_name); -void print_spice_comment(std::fstream& fp, - const std::string& comment); +void print_spice_comment(std::fstream& fp, const std::string& comment); std::string generate_spice_port(const BasicPort& port, const bool& omit_pin_zero = false); -void print_spice_subckt_definition(std::fstream& fp, +void print_spice_subckt_definition(std::fstream& fp, const ModuleManager& module_manager, const ModuleId& module_id, const bool& include_supply_ports = true); -void print_spice_subckt_end(std::fstream& fp, - const std::string& module_name); +void print_spice_subckt_end(std::fstream& fp, const std::string& module_name); -void print_spice_resistor(std::fstream& fp, - const std::string& input_port, +void print_spice_resistor(std::fstream& fp, const std::string& input_port, const std::string& output_port, const float& resistance); -void print_spice_capacitor(std::fstream& fp, - const std::string& input_port, - const std::string& output_port, - const float& capacitance); +void print_spice_capacitor(std::fstream& fp, const std::string& input_port, + const std::string& output_port, + const float& capacitance); void print_spice_short_connection(std::fstream& fp, const std::string& input_port, const std::string& output_port); -void print_spice_subckt_instance(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const std::string& instance_name, - const std::map& port2port_name_map); +void print_spice_subckt_instance( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const std::string& instance_name, + const std::map& port2port_name_map); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/fabric_verilog_options.cpp b/openfpga/src/fpga_verilog/fabric_verilog_options.cpp index e97fe7a98..17fdad397 100644 --- a/openfpga/src/fpga_verilog/fabric_verilog_options.cpp +++ b/openfpga/src/fpga_verilog/fabric_verilog_options.cpp @@ -1,11 +1,11 @@ /****************************************************************************** * Memember functions for data structure FabricVerilogOption ******************************************************************************/ +#include "fabric_verilog_options.h" + #include "vtr_assert.h" #include "vtr_log.h" -#include "fabric_verilog_options.h" - /* begin namespace openfpga */ namespace openfpga { @@ -25,19 +25,15 @@ FabricVerilogOption::FabricVerilogOption() { } /************************************************** - * Public Accessors + * Public Accessors *************************************************/ std::string FabricVerilogOption::output_directory() const { return output_directory_; } -bool FabricVerilogOption::include_timing() const { - return include_timing_; -} +bool FabricVerilogOption::include_timing() const { return include_timing_; } -bool FabricVerilogOption::time_stamp() const { - return time_stamp_; -} +bool FabricVerilogOption::time_stamp() const { return time_stamp_; } bool FabricVerilogOption::use_relative_path() const { return use_relative_path_; @@ -47,9 +43,7 @@ bool FabricVerilogOption::explicit_port_mapping() const { return explicit_port_mapping_; } -bool FabricVerilogOption::compress_routing() const { - return compress_routing_; -} +bool FabricVerilogOption::compress_routing() const { return compress_routing_; } bool FabricVerilogOption::print_user_defined_template() const { return print_user_defined_template_; @@ -59,9 +53,7 @@ e_verilog_default_net_type FabricVerilogOption::default_net_type() const { return default_net_type_; } -bool FabricVerilogOption::verbose_output() const { - return verbose_output_; -} +bool FabricVerilogOption::verbose_output() const { return verbose_output_; } /****************************************************************************** * Private Mutators @@ -94,17 +86,23 @@ void FabricVerilogOption::set_print_user_defined_template(const bool& enabled) { print_user_defined_template_ = enabled; } -void FabricVerilogOption::set_default_net_type(const std::string& default_net_type) { +void FabricVerilogOption::set_default_net_type( + const std::string& default_net_type) { /* Decode from net type string */; - if (default_net_type == std::string(VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_NONE])) { + if (default_net_type == + std::string( + VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_NONE])) { default_net_type_ = VERILOG_DEFAULT_NET_TYPE_NONE; - } else if (default_net_type == std::string(VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_WIRE])) { + } else if (default_net_type == + std::string(VERILOG_DEFAULT_NET_TYPE_STRING + [VERILOG_DEFAULT_NET_TYPE_WIRE])) { default_net_type_ = VERILOG_DEFAULT_NET_TYPE_WIRE; } else { - VTR_LOG_WARN("Invalid default net type: '%s'! Expect ['%s'|'%s']\n", - default_net_type.c_str(), - VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_NONE], - VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_WIRE]); + VTR_LOG_WARN( + "Invalid default net type: '%s'! Expect ['%s'|'%s']\n", + default_net_type.c_str(), + VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_NONE], + VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_WIRE]); } } diff --git a/openfpga/src/fpga_verilog/fabric_verilog_options.h b/openfpga/src/fpga_verilog/fabric_verilog_options.h index 46174a135..dfa7844e9 100644 --- a/openfpga/src/fpga_verilog/fabric_verilog_options.h +++ b/openfpga/src/fpga_verilog/fabric_verilog_options.h @@ -5,6 +5,7 @@ * Include header files required by the data structure definition *******************************************************************/ #include + #include "verilog_port_types.h" /* Begin namespace openfpga */ @@ -14,39 +15,42 @@ namespace openfpga { * Options for Fabric Verilog generator *******************************************************************/ class FabricVerilogOption { - public: /* Public constructor */ - /* Set default options */ - FabricVerilogOption(); - public: /* Public accessors */ - std::string output_directory() const; - bool time_stamp() const; - bool use_relative_path() const; - bool include_timing() const; - bool explicit_port_mapping() const; - bool compress_routing() const; - e_verilog_default_net_type default_net_type() const; - bool print_user_defined_template() const; - bool verbose_output() const; - public: /* Public mutators */ - void set_output_directory(const std::string& output_dir); - void set_use_relative_path(const bool& enabled); - void set_time_stamp(const bool& enabled); - void set_include_timing(const bool& enabled); - void set_explicit_port_mapping(const bool& enabled); - void set_compress_routing(const bool& enabled); - void set_print_user_defined_template(const bool& enabled); - void set_default_net_type(const std::string& default_net_type); - void set_verbose_output(const bool& enabled); - private: /* Internal Data */ - std::string output_directory_; - bool include_timing_; - bool explicit_port_mapping_; - bool compress_routing_; - bool print_user_defined_template_; - e_verilog_default_net_type default_net_type_; - bool time_stamp_; - bool use_relative_path_; - bool verbose_output_; + public: /* Public constructor */ + /* Set default options */ + FabricVerilogOption(); + + public: /* Public accessors */ + std::string output_directory() const; + bool time_stamp() const; + bool use_relative_path() const; + bool include_timing() const; + bool explicit_port_mapping() const; + bool compress_routing() const; + e_verilog_default_net_type default_net_type() const; + bool print_user_defined_template() const; + bool verbose_output() const; + + public: /* Public mutators */ + void set_output_directory(const std::string& output_dir); + void set_use_relative_path(const bool& enabled); + void set_time_stamp(const bool& enabled); + void set_include_timing(const bool& enabled); + void set_explicit_port_mapping(const bool& enabled); + void set_compress_routing(const bool& enabled); + void set_print_user_defined_template(const bool& enabled); + void set_default_net_type(const std::string& default_net_type); + void set_verbose_output(const bool& enabled); + + private: /* Internal Data */ + std::string output_directory_; + bool include_timing_; + bool explicit_port_mapping_; + bool compress_routing_; + bool print_user_defined_template_; + e_verilog_default_net_type default_net_type_; + bool time_stamp_; + bool use_relative_path_; + bool verbose_output_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index 56086b6cf..3fa929afc 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -3,30 +3,26 @@ ********************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" +#include "circuit_library_utils.h" +#include "command_exit_codes.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" -#include "command_exit_codes.h" - -#include "circuit_library_utils.h" - /* Headers from openfpgautil library */ +#include "device_rr_gsb.h" #include "openfpga_digest.h" #include "openfpga_reserved_words.h" - -#include "device_rr_gsb.h" -#include "verilog_constants.h" #include "verilog_auxiliary_netlists.h" -#include "verilog_submodule.h" -#include "verilog_routing.h" -#include "verilog_grid.h" -#include "verilog_top_module.h" - -#include "verilog_preconfig_top_module.h" +#include "verilog_constants.h" #include "verilog_formal_random_top_testbench.h" -#include "verilog_top_testbench.h" +#include "verilog_grid.h" +#include "verilog_preconfig_top_module.h" +#include "verilog_routing.h" #include "verilog_simulation_info_writer.h" +#include "verilog_submodule.h" +#include "verilog_top_module.h" +#include "verilog_top_testbench.h" /* Header file for this source file */ #include "verilog_api.h" @@ -35,8 +31,8 @@ namespace openfpga { /******************************************************************** - * A top-level function of FPGA-Verilog which focuses on fabric Verilog generation - * This function will generate + * A top-level function of FPGA-Verilog which focuses on fabric Verilog + *generation This function will generate * - primitive modules required by the full fabric * - which are LUTs, routing multiplexer, logic gates, transmission-gates etc. * - Routing modules, which are Switch Blocks (SBs) and Connection Blocks (CBs) @@ -46,24 +42,22 @@ namespace openfpga { * Note: * - Please do NOT include ANY testbench generation in this function!!! * It is about the fabric itself, independent from any implementation - * All the testbench generation should be in the function fpga_testbench_verilog() + * All the testbench generation should be in the function + *fpga_testbench_verilog() * * TODO: We should use module manager as a constant here. * All the modification should be done before this writer! * The only exception now is the user-defined modules. - * We should think clearly about how to handle them for both Verilog and SPICE generators! + * We should think clearly about how to handle them for both Verilog and SPICE + *generators! ********************************************************************/ -void fpga_fabric_verilog(ModuleManager &module_manager, - NetlistManager &netlist_manager, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const CircuitLibrary &circuit_lib, - const MuxLibrary &mux_lib, - const DecoderLibrary &decoder_lib, - const DeviceContext &device_ctx, - const VprDeviceAnnotation &device_annotation, - const DeviceRRGSB &device_rr_gsb, - const FabricVerilogOption &options) { - +void fpga_fabric_verilog( + ModuleManager &module_manager, NetlistManager &netlist_manager, + const MemoryBankShiftRegisterBanks &blwl_sr_banks, + const CircuitLibrary &circuit_lib, const MuxLibrary &mux_lib, + const DecoderLibrary &decoder_lib, const DeviceContext &device_ctx, + const VprDeviceAnnotation &device_annotation, + const DeviceRRGSB &device_rr_gsb, const FabricVerilogOption &options) { vtr::ScopedStartFinishTimer timer("Write Verilog netlists for FPGA fabric\n"); std::string src_dir_path = format_dir_path(options.output_directory()); @@ -71,105 +65,92 @@ void fpga_fabric_verilog(ModuleManager &module_manager, /* Create directories */ create_directory(src_dir_path); - /* Sub directory under SRC directory to contain all the primitive block netlists */ - std::string submodule_dir_path = src_dir_path + std::string(DEFAULT_SUBMODULE_DIR_NAME); + /* Sub directory under SRC directory to contain all the primitive block + * netlists */ + std::string submodule_dir_path = + src_dir_path + std::string(DEFAULT_SUBMODULE_DIR_NAME); create_directory(submodule_dir_path); - /* Sub directory under SRC directory to contain all the logic block netlists */ + /* Sub directory under SRC directory to contain all the logic block netlists + */ std::string lb_dir_path = src_dir_path + std::string(DEFAULT_LB_DIR_NAME); create_directory(lb_dir_path); - /* Sub directory under SRC directory to contain all the routing block netlists */ + /* Sub directory under SRC directory to contain all the routing block netlists + */ std::string rr_dir_path = src_dir_path + std::string(DEFAULT_RR_DIR_NAME); create_directory(rr_dir_path); /* Print Verilog files containing preprocessing flags */ - print_verilog_preprocessing_flags_netlist(std::string(src_dir_path), - options); + print_verilog_preprocessing_flags_netlist(std::string(src_dir_path), options); /* Generate primitive Verilog modules, which are corner stones of FPGA fabric * Note that this function MUST be called before Verilog generation of * core logic (i.e., logic blocks and routing resources) !!! - * This is because that this function will add the primitive Verilog modules to - * the module manager. - * Without the modules in the module manager, core logic generation is not possible!!! + * This is because that this function will add the primitive Verilog modules + * to the module manager. Without the modules in the module manager, core + * logic generation is not possible!!! */ - print_verilog_submodule(module_manager, netlist_manager, - blwl_sr_banks, - mux_lib, decoder_lib, circuit_lib, - submodule_dir_path, - std::string(DEFAULT_SUBMODULE_DIR_NAME), - options); + print_verilog_submodule(module_manager, netlist_manager, blwl_sr_banks, + mux_lib, decoder_lib, circuit_lib, submodule_dir_path, + std::string(DEFAULT_SUBMODULE_DIR_NAME), options); /* Generate routing blocks */ if (true == options.compress_routing()) { - print_verilog_unique_routing_modules(netlist_manager, - const_cast(module_manager), - device_rr_gsb, - rr_dir_path, - std::string(DEFAULT_RR_DIR_NAME), - options); + print_verilog_unique_routing_modules( + netlist_manager, const_cast(module_manager), + device_rr_gsb, rr_dir_path, std::string(DEFAULT_RR_DIR_NAME), options); } else { VTR_ASSERT(false == options.compress_routing()); - print_verilog_flatten_routing_modules(netlist_manager, - const_cast(module_manager), - device_rr_gsb, - rr_dir_path, - std::string(DEFAULT_RR_DIR_NAME), - options); + print_verilog_flatten_routing_modules( + netlist_manager, const_cast(module_manager), + device_rr_gsb, rr_dir_path, std::string(DEFAULT_RR_DIR_NAME), options); } /* Generate grids */ - print_verilog_grids(netlist_manager, - const_cast(module_manager), - device_ctx, device_annotation, - lb_dir_path, - std::string(DEFAULT_LB_DIR_NAME), - options, - options.verbose_output()); + print_verilog_grids( + netlist_manager, const_cast(module_manager), + device_ctx, device_annotation, lb_dir_path, + std::string(DEFAULT_LB_DIR_NAME), options, options.verbose_output()); /* Generate FPGA fabric */ print_verilog_top_module(netlist_manager, const_cast(module_manager), - src_dir_path, - options); + src_dir_path, options); /* Generate an netlist including all the fabric-related netlists */ - print_verilog_fabric_include_netlist(const_cast(netlist_manager), - src_dir_path, - circuit_lib, - options.use_relative_path(), - options.time_stamp()); + print_verilog_fabric_include_netlist( + const_cast(netlist_manager), src_dir_path, + circuit_lib, options.use_relative_path(), options.time_stamp()); - /* Given a brief stats on how many Verilog modules have been written to files */ - VTR_LOGV(options.verbose_output(), - "Written %lu Verilog modules in total\n", + /* Given a brief stats on how many Verilog modules have been written to files + */ + VTR_LOGV(options.verbose_output(), "Written %lu Verilog modules in total\n", module_manager.num_modules()); } /******************************************************************** - * A top-level function of FPGA-Verilog which focuses on full testbench generation - * This function will generate - * - Verilog netlist including preprocessing flags and all the Verilog netlists that have been generated + * A top-level function of FPGA-Verilog which focuses on full testbench + *generation This function will generate + * - Verilog netlist including preprocessing flags and all the Verilog netlists + *that have been generated ********************************************************************/ -int fpga_verilog_full_testbench(const ModuleManager &module_manager, - const BitstreamManager &bitstream_manager, - const FabricBitstream &fabric_bitstream, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const AtomContext &atom_ctx, - const PlacementContext &place_ctx, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const std::string& bitstream_file, - const IoLocationMap &io_location_map, - const FabricGlobalPortInfo &fabric_global_port_info, - const VprNetlistAnnotation &netlist_annotation, - const CircuitLibrary &circuit_lib, - const SimulationSetting &simulation_setting, - const ConfigProtocol &config_protocol, - const VerilogTestbenchOption &options) { - - vtr::ScopedStartFinishTimer timer("Write Verilog full testbenches for FPGA fabric\n"); +int fpga_verilog_full_testbench( + const ModuleManager &module_manager, + const BitstreamManager &bitstream_manager, + const FabricBitstream &fabric_bitstream, + const MemoryBankShiftRegisterBanks &blwl_sr_banks, + const AtomContext &atom_ctx, const PlacementContext &place_ctx, + const PinConstraints &pin_constraints, const BusGroup &bus_group, + const std::string &bitstream_file, const IoLocationMap &io_location_map, + const FabricGlobalPortInfo &fabric_global_port_info, + const VprNetlistAnnotation &netlist_annotation, + const CircuitLibrary &circuit_lib, + const SimulationSetting &simulation_setting, + const ConfigProtocol &config_protocol, + const VerilogTestbenchOption &options) { + vtr::ScopedStartFinishTimer timer( + "Write Verilog full testbenches for FPGA fabric\n"); std::string src_dir_path = format_dir_path(options.output_directory()); @@ -180,51 +161,43 @@ int fpga_verilog_full_testbench(const ModuleManager &module_manager, /* Create directories */ create_directory(src_dir_path); - /* Generate full testbench for verification, including configuration phase and operating phase */ - std::string top_testbench_file_path = src_dir_path + netlist_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX); - print_verilog_full_testbench(module_manager, - bitstream_manager, fabric_bitstream, blwl_sr_banks, - circuit_lib, - config_protocol, - fabric_global_port_info, - atom_ctx, place_ctx, - pin_constraints, - bus_group, - bitstream_file, - io_location_map, - netlist_annotation, - netlist_name, - top_testbench_file_path, - simulation_setting, - options); + /* Generate full testbench for verification, including configuration phase and + * operating phase */ + std::string top_testbench_file_path = + src_dir_path + netlist_name + + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX); + print_verilog_full_testbench( + module_manager, bitstream_manager, fabric_bitstream, blwl_sr_banks, + circuit_lib, config_protocol, fabric_global_port_info, atom_ctx, place_ctx, + pin_constraints, bus_group, bitstream_file, io_location_map, + netlist_annotation, netlist_name, top_testbench_file_path, + simulation_setting, options); - /* Generate a Verilog file including all the netlists that have been generated */ - print_verilog_full_testbench_include_netlists(src_dir_path, - netlist_name, + /* Generate a Verilog file including all the netlists that have been generated + */ + print_verilog_full_testbench_include_netlists(src_dir_path, netlist_name, options); return status; } /******************************************************************** - * A top-level function of FPGA-Verilog which focuses on full testbench generation - * This function will generate - * - A wrapper module, which encapsulate the FPGA module in a Verilog module which have the same port as the input benchmark + * A top-level function of FPGA-Verilog which focuses on full testbench + *generation This function will generate + * - A wrapper module, which encapsulate the FPGA module in a Verilog module + *which have the same port as the input benchmark ********************************************************************/ -int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manager, - const BitstreamManager &bitstream_manager, - const AtomContext &atom_ctx, - const PlacementContext &place_ctx, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const IoLocationMap &io_location_map, - const FabricGlobalPortInfo &fabric_global_port_info, - const VprNetlistAnnotation &netlist_annotation, - const CircuitLibrary &circuit_lib, - const ConfigProtocol &config_protocol, - const VerilogTestbenchOption &options) { - - vtr::ScopedStartFinishTimer timer("Write a wrapper module for a preconfigured FPGA fabric\n"); +int fpga_verilog_preconfigured_fabric_wrapper( + const ModuleManager &module_manager, + const BitstreamManager &bitstream_manager, const AtomContext &atom_ctx, + const PlacementContext &place_ctx, const PinConstraints &pin_constraints, + const BusGroup &bus_group, const IoLocationMap &io_location_map, + const FabricGlobalPortInfo &fabric_global_port_info, + const VprNetlistAnnotation &netlist_annotation, + const CircuitLibrary &circuit_lib, const ConfigProtocol &config_protocol, + const VerilogTestbenchOption &options) { + vtr::ScopedStartFinishTimer timer( + "Write a wrapper module for a preconfigured FPGA fabric\n"); std::string src_dir_path = format_dir_path(options.output_directory()); @@ -235,39 +208,36 @@ int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manage /* Create directories */ create_directory(src_dir_path); - /* Generate wrapper module for FPGA fabric (mapped by the input benchmark and pre-configured testbench for verification */ - std::string formal_verification_top_netlist_file_path = src_dir_path + netlist_name + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX); - status = print_verilog_preconfig_top_module(module_manager, bitstream_manager, - config_protocol, - circuit_lib, fabric_global_port_info, - atom_ctx, place_ctx, - pin_constraints, - bus_group, - io_location_map, - netlist_annotation, - netlist_name, - formal_verification_top_netlist_file_path, - options); + /* Generate wrapper module for FPGA fabric (mapped by the input benchmark and + * pre-configured testbench for verification */ + std::string formal_verification_top_netlist_file_path = + src_dir_path + netlist_name + + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX); + status = print_verilog_preconfig_top_module( + module_manager, bitstream_manager, config_protocol, circuit_lib, + fabric_global_port_info, atom_ctx, place_ctx, pin_constraints, bus_group, + io_location_map, netlist_annotation, netlist_name, + formal_verification_top_netlist_file_path, options); return status; } /******************************************************************** - * A top-level function of FPGA-Verilog which focuses on fabric Verilog generation - * This function will generate - * - Pre-configured testbench, which can skip the configuration phase and pre-configure the FPGA module. - * This testbench is created for quick verification and formal verification purpose. + * A top-level function of FPGA-Verilog which focuses on fabric Verilog + *generation This function will generate + * - Pre-configured testbench, which can skip the configuration phase and + *pre-configure the FPGA module. This testbench is created for quick + *verification and formal verification purpose. ********************************************************************/ -int fpga_verilog_preconfigured_testbench(const ModuleManager &module_manager, - const AtomContext &atom_ctx, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const FabricGlobalPortInfo &fabric_global_port_info, - const VprNetlistAnnotation &netlist_annotation, - const SimulationSetting &simulation_setting, - const VerilogTestbenchOption &options) { - - vtr::ScopedStartFinishTimer timer("Write Verilog testbenches for a preconfigured FPGA fabric\n"); +int fpga_verilog_preconfigured_testbench( + const ModuleManager &module_manager, const AtomContext &atom_ctx, + const PinConstraints &pin_constraints, const BusGroup &bus_group, + const FabricGlobalPortInfo &fabric_global_port_info, + const VprNetlistAnnotation &netlist_annotation, + const SimulationSetting &simulation_setting, + const VerilogTestbenchOption &options) { + vtr::ScopedStartFinishTimer timer( + "Write Verilog testbenches for a preconfigured FPGA fabric\n"); std::string src_dir_path = format_dir_path(options.output_directory()); @@ -279,41 +249,36 @@ int fpga_verilog_preconfigured_testbench(const ModuleManager &module_manager, create_directory(src_dir_path); /* Generate top-level testbench using random vectors */ - std::string random_top_testbench_file_path = src_dir_path + netlist_name + std::string(RANDOM_TOP_TESTBENCH_VERILOG_FILE_POSTFIX); - print_verilog_random_top_testbench(netlist_name, - random_top_testbench_file_path, - atom_ctx, - netlist_annotation, - module_manager, - fabric_global_port_info, - pin_constraints, - bus_group, - simulation_setting, - options); + std::string random_top_testbench_file_path = + src_dir_path + netlist_name + + std::string(RANDOM_TOP_TESTBENCH_VERILOG_FILE_POSTFIX); + print_verilog_random_top_testbench( + netlist_name, random_top_testbench_file_path, atom_ctx, netlist_annotation, + module_manager, fabric_global_port_info, pin_constraints, bus_group, + simulation_setting, options); - /* Generate a Verilog file including all the netlists that have been generated */ + /* Generate a Verilog file including all the netlists that have been generated + */ print_verilog_preconfigured_testbench_include_netlists(src_dir_path, - netlist_name, - options); + netlist_name, options); return status; } /******************************************************************** - * A top-level function of FPGA-Verilog which focuses on fabric Verilog generation - * This function will generate + * A top-level function of FPGA-Verilog which focuses on fabric Verilog + *generation This function will generate * - An interchangable file containing simulation task configuration ********************************************************************/ -int fpga_verilog_simulation_task_info(const ModuleManager &module_manager, - const BitstreamManager &bitstream_manager, - const AtomContext &atom_ctx, - const PlacementContext &place_ctx, - const IoLocationMap &io_location_map, - const SimulationSetting &simulation_setting, - const ConfigProtocol &config_protocol, - const VerilogTestbenchOption &options) { - - vtr::ScopedStartFinishTimer timer("Write interchangeable simulation task configuration\n"); +int fpga_verilog_simulation_task_info( + const ModuleManager &module_manager, + const BitstreamManager &bitstream_manager, const AtomContext &atom_ctx, + const PlacementContext &place_ctx, const IoLocationMap &io_location_map, + const SimulationSetting &simulation_setting, + const ConfigProtocol &config_protocol, + const VerilogTestbenchOption &options) { + vtr::ScopedStartFinishTimer timer( + "Write interchangeable simulation task configuration\n"); std::string src_dir_path = format_dir_path(options.output_directory()); @@ -327,20 +292,14 @@ int fpga_verilog_simulation_task_info(const ModuleManager &module_manager, /* Generate exchangeable files which contains simulation settings */ std::string simulation_ini_file_name = options.simulation_ini_path(); VTR_ASSERT(true != options.simulation_ini_path().empty()); - print_verilog_simulation_info(simulation_ini_file_name, - options, - netlist_name, - src_dir_path, - atom_ctx, place_ctx, io_location_map, - module_manager, - config_protocol.type(), - bitstream_manager.num_bits(), - simulation_setting.num_clock_cycles(), - simulation_setting.programming_clock_frequency(), - simulation_setting.default_operating_clock_frequency()); + print_verilog_simulation_info( + simulation_ini_file_name, options, netlist_name, src_dir_path, atom_ctx, + place_ctx, io_location_map, module_manager, config_protocol.type(), + bitstream_manager.num_bits(), simulation_setting.num_clock_cycles(), + simulation_setting.programming_clock_frequency(), + simulation_setting.default_operating_clock_frequency()); return status; } - } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index 78cb8288d..79ce6759d 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -1,5 +1,5 @@ -#ifndef VERILOG_API_H -#define VERILOG_API_H +#ifndef VERILOG_API_H +#define VERILOG_API_H /******************************************************************** * Include header files that are required by function declaration @@ -7,26 +7,27 @@ #include #include -#include "mux_library.h" -#include "decoder_library.h" + +#include "bitstream_manager.h" +#include "bus_group.h" #include "circuit_library.h" #include "config_protocol.h" +#include "decoder_library.h" +#include "device_rr_gsb.h" +#include "fabric_bitstream.h" +#include "fabric_global_port_info.h" +#include "fabric_verilog_options.h" +#include "io_location_map.h" +#include "memory_bank_shift_register_banks.h" +#include "module_manager.h" +#include "mux_library.h" +#include "netlist_manager.h" +#include "pin_constraints.h" +#include "simulation_setting.h" +#include "verilog_testbench_options.h" #include "vpr_context.h" #include "vpr_device_annotation.h" -#include "device_rr_gsb.h" -#include "netlist_manager.h" -#include "module_manager.h" -#include "bitstream_manager.h" -#include "fabric_bitstream.h" -#include "simulation_setting.h" -#include "pin_constraints.h" -#include "io_location_map.h" -#include "fabric_global_port_info.h" #include "vpr_netlist_annotation.h" -#include "memory_bank_shift_register_banks.h" -#include "bus_group.h" -#include "fabric_verilog_options.h" -#include "verilog_testbench_options.h" /******************************************************************** * Function declaration @@ -35,64 +36,52 @@ /* begin namespace openfpga */ namespace openfpga { -void fpga_fabric_verilog(ModuleManager& module_manager, - NetlistManager& netlist_manager, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const DecoderLibrary& decoder_lib, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const DeviceRRGSB& device_rr_gsb, - const FabricVerilogOption& options); +void fpga_fabric_verilog( + ModuleManager& module_manager, NetlistManager& netlist_manager, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, + const DecoderLibrary& decoder_lib, const DeviceContext& device_ctx, + const VprDeviceAnnotation& device_annotation, + const DeviceRRGSB& device_rr_gsb, const FabricVerilogOption& options); -int fpga_verilog_full_testbench(const ModuleManager& module_manager, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const std::string& bitstream_file, - const IoLocationMap& io_location_map, - const FabricGlobalPortInfo &fabric_global_port_info, - const VprNetlistAnnotation& netlist_annotation, - const CircuitLibrary& circuit_lib, - const SimulationSetting& simulation_parameters, - const ConfigProtocol& config_protocol, - const VerilogTestbenchOption& options); +int fpga_verilog_full_testbench( + const ModuleManager& module_manager, + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const AtomContext& atom_ctx, const PlacementContext& place_ctx, + const PinConstraints& pin_constraints, const BusGroup& bus_group, + const std::string& bitstream_file, const IoLocationMap& io_location_map, + const FabricGlobalPortInfo& fabric_global_port_info, + const VprNetlistAnnotation& netlist_annotation, + const CircuitLibrary& circuit_lib, + const SimulationSetting& simulation_parameters, + const ConfigProtocol& config_protocol, const VerilogTestbenchOption& options); -int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manager, - const BitstreamManager &bitstream_manager, - const AtomContext &atom_ctx, - const PlacementContext &place_ctx, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const IoLocationMap &io_location_map, - const FabricGlobalPortInfo &fabric_global_port_info, - const VprNetlistAnnotation &netlist_annotation, - const CircuitLibrary &circuit_lib, - const ConfigProtocol &config_protocol, - const VerilogTestbenchOption &options); +int fpga_verilog_preconfigured_fabric_wrapper( + const ModuleManager& module_manager, + const BitstreamManager& bitstream_manager, const AtomContext& atom_ctx, + const PlacementContext& place_ctx, const PinConstraints& pin_constraints, + const BusGroup& bus_group, const IoLocationMap& io_location_map, + const FabricGlobalPortInfo& fabric_global_port_info, + const VprNetlistAnnotation& netlist_annotation, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const VerilogTestbenchOption& options); -int fpga_verilog_preconfigured_testbench(const ModuleManager &module_manager, - const AtomContext &atom_ctx, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const FabricGlobalPortInfo &fabric_global_port_info, - const VprNetlistAnnotation &netlist_annotation, - const SimulationSetting &simulation_setting, - const VerilogTestbenchOption &options); +int fpga_verilog_preconfigured_testbench( + const ModuleManager& module_manager, const AtomContext& atom_ctx, + const PinConstraints& pin_constraints, const BusGroup& bus_group, + const FabricGlobalPortInfo& fabric_global_port_info, + const VprNetlistAnnotation& netlist_annotation, + const SimulationSetting& simulation_setting, + const VerilogTestbenchOption& options); -int fpga_verilog_simulation_task_info(const ModuleManager &module_manager, - const BitstreamManager &bitstream_manager, - const AtomContext &atom_ctx, - const PlacementContext &place_ctx, - const IoLocationMap &io_location_map, - const SimulationSetting &simulation_setting, - const ConfigProtocol &config_protocol, - const VerilogTestbenchOption &options); +int fpga_verilog_simulation_task_info( + const ModuleManager& module_manager, + const BitstreamManager& bitstream_manager, const AtomContext& atom_ctx, + const PlacementContext& place_ctx, const IoLocationMap& io_location_map, + const SimulationSetting& simulation_setting, + const ConfigProtocol& config_protocol, const VerilogTestbenchOption& options); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.cpp b/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.cpp index 240f1a195..aa600ddba 100644 --- a/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.cpp +++ b/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.cpp @@ -1,6 +1,6 @@ /******************************************************************** * This file includes functions that are used to generate Verilog files - * or code blocks, with a focus on + * or code blocks, with a focus on * `include user-defined or auto-generated netlists in Verilog format *******************************************************************/ #include @@ -9,13 +9,12 @@ #include "vtr_assert.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - -#include "openfpga_naming.h" #include "circuit_library_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "verilog_auxiliary_netlists.h" #include "verilog_constants.h" #include "verilog_writer_utils.h" -#include "verilog_auxiliary_netlists.h" /* begin namespace openfpga */ namespace openfpga { @@ -25,7 +24,7 @@ namespace openfpga { *******************************************************************/ /******************************************************************** - * Print a file that includes all the fabric netlists + * Print a file that includes all the fabric netlists * that have been generated and user-defined. * This does NOT include any testbenches! * Some netlists are open to compile under specific preprocessing flags @@ -35,12 +34,14 @@ void print_verilog_fabric_include_netlist(const NetlistManager& netlist_manager, const CircuitLibrary& circuit_lib, const bool& use_relative_path, const bool& include_time_stamp) { - /* If we force the use of relative path, the src dir path should NOT be included in any output */ + /* If we force the use of relative path, the src dir path should NOT be + * included in any output */ std::string src_dir = src_dir_path; if (use_relative_path) { src_dir.clear(); } - std::string verilog_fpath = src_dir_path + std::string(FABRIC_INCLUDE_VERILOG_NETLIST_FILE_NAME); + std::string verilog_fpath = + src_dir_path + std::string(FABRIC_INCLUDE_VERILOG_NETLIST_FILE_NAME); /* Create the file stream */ std::fstream fp; @@ -50,43 +51,56 @@ void print_verilog_fabric_include_netlist(const NetlistManager& netlist_manager, check_file_stream(verilog_fpath.c_str(), fp); /* Print the title */ - print_verilog_file_header(fp, std::string("Fabric Netlist Summary"), include_time_stamp); + print_verilog_file_header(fp, std::string("Fabric Netlist Summary"), + include_time_stamp); /* Print preprocessing flags */ - print_verilog_comment(fp, std::string("------ Include defines: preproc flags -----")); - print_verilog_include_netlist(fp, std::string(src_dir + std::string(DEFINES_VERILOG_FILE_NAME))); + print_verilog_comment( + fp, std::string("------ Include defines: preproc flags -----")); + print_verilog_include_netlist( + fp, std::string(src_dir + std::string(DEFINES_VERILOG_FILE_NAME))); fp << std::endl; /* Include all the user-defined netlists */ - print_verilog_comment(fp, std::string("------ Include user-defined netlists -----")); - for (const std::string& user_defined_netlist : find_circuit_library_unique_verilog_netlists(circuit_lib)) { + print_verilog_comment( + fp, std::string("------ Include user-defined netlists -----")); + for (const std::string& user_defined_netlist : + find_circuit_library_unique_verilog_netlists(circuit_lib)) { print_verilog_include_netlist(fp, user_defined_netlist); } /* Include all the primitive modules */ - print_verilog_comment(fp, std::string("------ Include primitive module netlists -----")); - for (const NetlistId& nlist_id : netlist_manager.netlists_by_type(NetlistManager::SUBMODULE_NETLIST)) { + print_verilog_comment( + fp, std::string("------ Include primitive module netlists -----")); + for (const NetlistId& nlist_id : + netlist_manager.netlists_by_type(NetlistManager::SUBMODULE_NETLIST)) { print_verilog_include_netlist(fp, netlist_manager.netlist_name(nlist_id)); } fp << std::endl; /* Include all the CLB, heterogeneous block modules */ - print_verilog_comment(fp, std::string("------ Include logic block netlists -----")); - for (const NetlistId& nlist_id : netlist_manager.netlists_by_type(NetlistManager::LOGIC_BLOCK_NETLIST)) { + print_verilog_comment( + fp, std::string("------ Include logic block netlists -----")); + for (const NetlistId& nlist_id : + netlist_manager.netlists_by_type(NetlistManager::LOGIC_BLOCK_NETLIST)) { print_verilog_include_netlist(fp, netlist_manager.netlist_name(nlist_id)); } fp << std::endl; /* Include all the routing architecture modules */ - print_verilog_comment(fp, std::string("------ Include routing module netlists -----")); - for (const NetlistId& nlist_id : netlist_manager.netlists_by_type(NetlistManager::ROUTING_MODULE_NETLIST)) { + print_verilog_comment( + fp, std::string("------ Include routing module netlists -----")); + for (const NetlistId& nlist_id : netlist_manager.netlists_by_type( + NetlistManager::ROUTING_MODULE_NETLIST)) { print_verilog_include_netlist(fp, netlist_manager.netlist_name(nlist_id)); } fp << std::endl; /* Include FPGA top module */ - print_verilog_comment(fp, std::string("------ Include fabric top-level netlists -----")); - for (const NetlistId& nlist_id : netlist_manager.netlists_by_type(NetlistManager::TOP_MODULE_NETLIST)) { + print_verilog_comment( + fp, std::string("------ Include fabric top-level netlists -----")); + for (const NetlistId& nlist_id : + netlist_manager.netlists_by_type(NetlistManager::TOP_MODULE_NETLIST)) { print_verilog_include_netlist(fp, netlist_manager.netlist_name(nlist_id)); } fp << std::endl; @@ -96,17 +110,20 @@ void print_verilog_fabric_include_netlist(const NetlistManager& netlist_manager, } /******************************************************************** - * Print a file that includes all the netlists + * Print a file that includes all the netlists * including the fabric netlists and full testbenches * that have been generated and user-defined. * Some netlists are open to compile under specific preprocessing flags *******************************************************************/ -void print_verilog_full_testbench_include_netlists(const std::string& src_dir_path, - const std::string& circuit_name, - const VerilogTestbenchOption& options) { - std::string verilog_fname = src_dir_path + circuit_name + std::string(TOP_VERILOG_TESTBENCH_INCLUDE_NETLIST_FILE_NAME_POSTFIX); +void print_verilog_full_testbench_include_netlists( + const std::string& src_dir_path, const std::string& circuit_name, + const VerilogTestbenchOption& options) { + std::string verilog_fname = + src_dir_path + circuit_name + + std::string(TOP_VERILOG_TESTBENCH_INCLUDE_NETLIST_FILE_NAME_POSTFIX); std::string fabric_netlist_file = options.fabric_netlist_file_path(); - std::string reference_benchmark_file = options.reference_benchmark_file_path(); + std::string reference_benchmark_file = + options.reference_benchmark_file_path(); bool no_self_checking = options.no_self_checking(); /* Create the file stream */ @@ -117,18 +134,22 @@ void print_verilog_full_testbench_include_netlists(const std::string& src_dir_pa check_file_stream(verilog_fname.c_str(), fp); /* Print the title */ - print_verilog_file_header(fp, std::string("Netlist Summary"), options.time_stamp()); + print_verilog_file_header(fp, std::string("Netlist Summary"), + options.time_stamp()); - /* If relative path is forced, we do not include an src_dir_path in the netlist */ + /* If relative path is forced, we do not include an src_dir_path in the + * netlist */ std::string src_dir = src_dir_path; if (options.use_relative_path()) { src_dir.clear(); } /* Include FPGA top module */ - print_verilog_comment(fp, std::string("------ Include fabric top-level netlists -----")); + print_verilog_comment( + fp, std::string("------ Include fabric top-level netlists -----")); if (true == fabric_netlist_file.empty()) { - print_verilog_include_netlist(fp, src_dir + std::string(FABRIC_INCLUDE_VERILOG_NETLIST_FILE_NAME)); + print_verilog_include_netlist( + fp, src_dir + std::string(FABRIC_INCLUDE_VERILOG_NETLIST_FILE_NAME)); } else { VTR_ASSERT_SAFE(false == fabric_netlist_file.empty()); print_verilog_include_netlist(fp, fabric_netlist_file); @@ -142,24 +163,29 @@ void print_verilog_full_testbench_include_netlists(const std::string& src_dir_pa } /* Include top-level testbench only when auto-check flag is enabled */ - print_verilog_include_netlist(fp, src_dir + circuit_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX)); + print_verilog_include_netlist( + fp, src_dir + circuit_name + + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX)); /* Close the file stream */ fp.close(); } /******************************************************************** - * Print a file that includes all the netlists + * Print a file that includes all the netlists * including the fabric netlists and preconfigured testbenches * that have been generated and user-defined. * Some netlists are open to compile under specific preprocessing flags *******************************************************************/ -void print_verilog_preconfigured_testbench_include_netlists(const std::string& src_dir_path, - const std::string& circuit_name, - const VerilogTestbenchOption& options) { - std::string verilog_fname = src_dir_path + circuit_name + std::string(TOP_VERILOG_TESTBENCH_INCLUDE_NETLIST_FILE_NAME_POSTFIX); +void print_verilog_preconfigured_testbench_include_netlists( + const std::string& src_dir_path, const std::string& circuit_name, + const VerilogTestbenchOption& options) { + std::string verilog_fname = + src_dir_path + circuit_name + + std::string(TOP_VERILOG_TESTBENCH_INCLUDE_NETLIST_FILE_NAME_POSTFIX); std::string fabric_netlist_file = options.fabric_netlist_file_path(); - std::string reference_benchmark_file = options.reference_benchmark_file_path(); + std::string reference_benchmark_file = + options.reference_benchmark_file_path(); bool no_self_checking = options.no_self_checking(); /* Create the file stream */ @@ -170,18 +196,22 @@ void print_verilog_preconfigured_testbench_include_netlists(const std::string& s check_file_stream(verilog_fname.c_str(), fp); /* Print the title */ - print_verilog_file_header(fp, std::string("Netlist Summary"), options.time_stamp()); + print_verilog_file_header(fp, std::string("Netlist Summary"), + options.time_stamp()); - /* If relative path is forced, we do not include an src_dir_path in the netlist */ + /* If relative path is forced, we do not include an src_dir_path in the + * netlist */ std::string src_dir = src_dir_path; if (options.use_relative_path()) { src_dir.clear(); } /* Include FPGA top module */ - print_verilog_comment(fp, std::string("------ Include fabric top-level netlists -----")); + print_verilog_comment( + fp, std::string("------ Include fabric top-level netlists -----")); if (true == fabric_netlist_file.empty()) { - print_verilog_include_netlist(fp, src_dir + std::string(FABRIC_INCLUDE_VERILOG_NETLIST_FILE_NAME)); + print_verilog_include_netlist( + fp, src_dir + std::string(FABRIC_INCLUDE_VERILOG_NETLIST_FILE_NAME)); } else { VTR_ASSERT_SAFE(false == fabric_netlist_file.empty()); print_verilog_include_netlist(fp, fabric_netlist_file); @@ -195,10 +225,14 @@ void print_verilog_preconfigured_testbench_include_netlists(const std::string& s } /* Include formal verification netlists */ - print_verilog_include_netlist(fp, src_dir + circuit_name + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX)); - + print_verilog_include_netlist( + fp, src_dir + circuit_name + + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX)); + /* Include formal verification testbench */ - print_verilog_include_netlist(fp, src_dir + circuit_name + std::string(RANDOM_TOP_TESTBENCH_VERILOG_FILE_POSTFIX)); + print_verilog_include_netlist( + fp, src_dir + circuit_name + + std::string(RANDOM_TOP_TESTBENCH_VERILOG_FILE_POSTFIX)); /* Close the file stream */ fp.close(); @@ -208,9 +242,8 @@ void print_verilog_preconfigured_testbench_include_netlists(const std::string& s * Print a Verilog file containing preprocessing flags * which are used enable/disable some features in FPGA Verilog modules *******************************************************************/ -void print_verilog_preprocessing_flags_netlist(const std::string& src_dir, - const FabricVerilogOption& fabric_verilog_opts) { - +void print_verilog_preprocessing_flags_netlist( + const std::string& src_dir, const FabricVerilogOption& fabric_verilog_opts) { std::string verilog_fname = src_dir + std::string(DEFINES_VERILOG_FILE_NAME); /* Create the file stream */ @@ -221,15 +254,17 @@ void print_verilog_preprocessing_flags_netlist(const std::string& src_dir, check_file_stream(verilog_fname.c_str(), fp); /* Print the title */ - print_verilog_file_header(fp, - std::string("Preprocessing flags to enable/disable features in FPGA Verilog modules"), - fabric_verilog_opts.time_stamp()); + print_verilog_file_header( + fp, + std::string( + "Preprocessing flags to enable/disable features in FPGA Verilog modules"), + fabric_verilog_opts.time_stamp()); /* To enable timing */ if (true == fabric_verilog_opts.include_timing()) { print_verilog_define_flag(fp, std::string(VERILOG_TIMING_PREPROC_FLAG), 1); fp << std::endl; - } + } /* Close the file stream */ fp.close(); diff --git a/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.h b/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.h index 741d2cd3c..553c8c3a4 100644 --- a/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.h +++ b/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "circuit_library.h" #include "fabric_verilog_options.h" #include "netlist_manager.h" @@ -23,17 +24,17 @@ void print_verilog_fabric_include_netlist(const NetlistManager& netlist_manager, const bool& use_relative_path, const bool& include_time_stamp); -void print_verilog_full_testbench_include_netlists(const std::string& src_dir_path, - const std::string& circuit_name, - const VerilogTestbenchOption& options); +void print_verilog_full_testbench_include_netlists( + const std::string& src_dir_path, const std::string& circuit_name, + const VerilogTestbenchOption& options); -void print_verilog_preconfigured_testbench_include_netlists(const std::string& src_dir_path, - const std::string& circuit_name, - const VerilogTestbenchOption& options); +void print_verilog_preconfigured_testbench_include_netlists( + const std::string& src_dir_path, const std::string& circuit_name, + const VerilogTestbenchOption& options); -void print_verilog_preprocessing_flags_netlist(const std::string& src_dir, - const FabricVerilogOption& fabric_verilog_opts); +void print_verilog_preprocessing_flags_netlist( + const std::string& src_dir, const FabricVerilogOption& fabric_verilog_opts); } /* end namespace openfpga */ -#endif +#endif diff --git a/openfpga/src/fpga_verilog/verilog_constants.h b/openfpga/src/fpga_verilog/verilog_constants.h index 75e8c3c68..da5370fd9 100644 --- a/openfpga/src/fpga_verilog/verilog_constants.h +++ b/openfpga/src/fpga_verilog/verilog_constants.h @@ -4,18 +4,28 @@ /* global parameters for dumping synthesizable verilog */ constexpr const char* VERILOG_NETLIST_FILE_POSTFIX = ".v"; -constexpr float VERILOG_SIM_TIMESCALE = 1e-9; // Verilog Simulation time scale (minimum time unit) : 1ns +constexpr float VERILOG_SIM_TIMESCALE = + 1e-9; // Verilog Simulation time scale (minimum time unit) : 1ns -constexpr const char* VERILOG_TIMING_PREPROC_FLAG = "ENABLE_TIMING"; // the flag to enable timing definition during compilation +constexpr const char* VERILOG_TIMING_PREPROC_FLAG = + "ENABLE_TIMING"; // the flag to enable timing definition during compilation constexpr const char* MODELSIM_SIMULATION_TIME_UNIT = "ms"; -constexpr const char* FABRIC_INCLUDE_VERILOG_NETLIST_FILE_NAME = "fabric_netlists.v"; -constexpr const char* TOP_VERILOG_TESTBENCH_INCLUDE_NETLIST_FILE_NAME_POSTFIX = "_include_netlists.v"; +constexpr const char* FABRIC_INCLUDE_VERILOG_NETLIST_FILE_NAME = + "fabric_netlists.v"; +constexpr const char* TOP_VERILOG_TESTBENCH_INCLUDE_NETLIST_FILE_NAME_POSTFIX = + "_include_netlists.v"; constexpr const char* VERILOG_TOP_POSTFIX = "_top.v"; -constexpr const char* FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX = "_top_formal_verification.v"; -constexpr const char* TOP_TESTBENCH_VERILOG_FILE_POSTFIX = "_top_tb.v"; /* !!! must be consist with the modelsim_testbench_module_postfix */ -constexpr const char* AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX = "_autocheck_top_tb.v"; /* !!! must be consist with the modelsim_autocheck_testbench_module_postfix */ -constexpr const char* RANDOM_TOP_TESTBENCH_VERILOG_FILE_POSTFIX = "_formal_random_top_tb.v"; +constexpr const char* FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX = + "_top_formal_verification.v"; +constexpr const char* TOP_TESTBENCH_VERILOG_FILE_POSTFIX = + "_top_tb.v"; /* !!! must be consist with the modelsim_testbench_module_postfix + */ +constexpr const char* AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX = + "_autocheck_top_tb.v"; /* !!! must be consist with the + modelsim_autocheck_testbench_module_postfix */ +constexpr const char* RANDOM_TOP_TESTBENCH_VERILOG_FILE_POSTFIX = + "_formal_random_top_tb.v"; constexpr const char* DEFINES_VERILOG_FILE_NAME = "fpga_defines.v"; constexpr const char* SUBMODULE_VERILOG_FILE_NAME = "sub_module.v"; constexpr const char* LOGIC_BLOCK_VERILOG_FILE_NAME = "logic_blocks.v"; @@ -26,11 +36,14 @@ constexpr const char* MUXES_VERILOG_FILE_NAME = "muxes.v"; constexpr const char* LOCAL_ENCODER_VERILOG_FILE_NAME = "local_encoder.v"; constexpr const char* ARCH_ENCODER_VERILOG_FILE_NAME = "arch_encoder.v"; constexpr const char* MEMORIES_VERILOG_FILE_NAME = "memories.v"; -constexpr const char* SHIFT_REGISTER_BANKS_VERILOG_FILE_NAME = "shift_register_banks.v"; +constexpr const char* SHIFT_REGISTER_BANKS_VERILOG_FILE_NAME = + "shift_register_banks.v"; constexpr const char* WIRES_VERILOG_FILE_NAME = "wires.v"; constexpr const char* ESSENTIALS_VERILOG_FILE_NAME = "inv_buf_passgate.v"; -constexpr const char* CONFIG_PERIPHERAL_VERILOG_FILE_NAME = "config_peripherals.v"; -constexpr const char* USER_DEFINED_TEMPLATE_VERILOG_FILE_NAME = "user_defined_templates.v"; +constexpr const char* CONFIG_PERIPHERAL_VERILOG_FILE_NAME = + "config_peripherals.v"; +constexpr const char* USER_DEFINED_TEMPLATE_VERILOG_FILE_NAME = + "user_defined_templates.v"; constexpr const char* VERILOG_MUX_BASIS_POSTFIX = "_basis"; constexpr const char* VERILOG_MEM_POSTFIX = "_mem"; @@ -39,11 +52,14 @@ constexpr const char* SB_VERILOG_FILE_NAME_PREFIX = "sb_"; constexpr const char* LOGICAL_MODULE_VERILOG_FILE_NAME_PREFIX = "logical_tile_"; constexpr const char* GRID_VERILOG_FILE_NAME_PREFIX = "grid_"; -constexpr const char* FORMAL_VERIFICATION_TOP_MODULE_POSTFIX = "_top_formal_verification"; +constexpr const char* FORMAL_VERIFICATION_TOP_MODULE_POSTFIX = + "_top_formal_verification"; constexpr const char* FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX = "_fm"; -constexpr const char* FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME = "U0_formal_verification"; +constexpr const char* FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME = + "U0_formal_verification"; -constexpr const char* FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX = "_top_formal_verification_random_tb"; +constexpr const char* FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX = + "_top_formal_verification_random_tb"; #define VERILOG_DEFAULT_SIGNAL_INIT_VALUE 0 diff --git a/openfpga/src/fpga_verilog/verilog_decoders.cpp b/openfpga/src/fpga_verilog/verilog_decoders.cpp index a4521939c..73c59fed4 100644 --- a/openfpga/src/fpga_verilog/verilog_decoders.cpp +++ b/openfpga/src/fpga_verilog/verilog_decoders.cpp @@ -8,18 +8,15 @@ #include "vtr_log.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" -#include "openfpga_decode.h" - #include "decoder_library_utils.h" #include "module_manager.h" - -#include "openfpga_reserved_words.h" +#include "openfpga_decode.h" +#include "openfpga_digest.h" #include "openfpga_naming.h" - +#include "openfpga_reserved_words.h" #include "verilog_constants.h" -#include "verilog_writer_utils.h" #include "verilog_decoders.h" +#include "verilog_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -27,8 +24,8 @@ namespace openfpga { /*************************************************************************************** * Create a Verilog module for a decoder with a given output size * - * Inputs - * | | ... | + * Inputs + * | | ... | * v v v * +-----------+ * / \ @@ -37,17 +34,15 @@ namespace openfpga { * | | | ... | | | * v v v v v v * Outputs - * + * * The outputs are assumes to be one-hot codes (at most only one '1' exist) - * Considering this fact, there are only num_of_outputs conditions to be encoded. - * Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2)) + * Considering this fact, there are only num_of_outputs conditions to be + *encoded. Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2)) ***************************************************************************************/ -static -void print_verilog_mux_local_decoder_module(std::fstream& fp, - const ModuleManager& module_manager, - const DecoderLibrary& decoder_lib, - const DecoderId& decoder, - const e_verilog_default_net_type& default_net_type) { +static void print_verilog_mux_local_decoder_module( + std::fstream& fp, const ModuleManager& module_manager, + const DecoderLibrary& decoder_lib, const DecoderId& decoder, + const e_verilog_default_net_type& default_net_type) { /* Get the number of inputs */ size_t addr_size = decoder_lib.addr_size(decoder); size_t data_size = decoder_lib.data_size(decoder); @@ -56,39 +51,49 @@ void print_verilog_mux_local_decoder_module(std::fstream& fp, VTR_ASSERT(true == valid_file_stream(fp)); /* TODO: create a name for the local encoder */ - std::string module_name = generate_mux_local_decoder_subckt_name(addr_size, data_size); + std::string module_name = + generate_mux_local_decoder_subckt_name(addr_size, data_size); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = module_manager.find_module(module_name); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = module_manager.find_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(module_id)); /* Add module ports */ /* Add each input port */ BasicPort addr_port(generate_mux_local_decoder_addr_port_name(), addr_size); /* Add each output port */ BasicPort data_port(generate_mux_local_decoder_data_port_name(), data_size); - /* Data port is registered. It should be outputted as - * output reg [lsb:msb] data + /* Data port is registered. It should be outputted as + * output reg [lsb:msb] data */ /* Add data_in port */ - BasicPort data_inv_port(generate_mux_local_decoder_data_inv_port_name(), data_size); + BasicPort data_inv_port(generate_mux_local_decoder_data_inv_port_name(), + data_size); VTR_ASSERT(true == decoder_lib.use_data_inv_port(decoder)); /* dump module definition + ports */ - print_verilog_module_declaration(fp, module_manager, module_id, default_net_type); + print_verilog_module_declaration(fp, module_manager, module_id, + default_net_type); /* Finish dumping ports */ - print_verilog_comment(fp, std::string("----- BEGIN Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----")); + print_verilog_comment( + fp, std::string("----- BEGIN Verilog codes for Decoder convert " + + std::to_string(addr_size) + "-bit addr to " + + std::to_string(data_size) + "-bit data -----")); /* Print the truth table of this decoder */ /* Internal logics */ /* Early exit: Corner case for data size = 1 the logic is very simple: - * data = addr; + * data = addr; * data_inv = ~data_inv */ if (1 == data_size) { print_verilog_wire_connection(fp, data_port, addr_port, false); print_verilog_wire_connection(fp, data_inv_port, addr_port, true); - print_verilog_comment(fp, std::string("----- END Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----")); + print_verilog_comment( + fp, std::string("----- END Verilog codes for Decoder convert " + + std::to_string(addr_size) + "-bit addr to " + + std::to_string(data_size) + "-bit data -----")); /* Put an end to the Verilog module */ print_verilog_module_end(fp, module_name); @@ -96,13 +101,13 @@ void print_verilog_mux_local_decoder_module(std::fstream& fp, } /* We use a magic number -1 as the addr=1 should be mapped to ...1 - * Otherwise addr will map addr=1 to ..10 + * Otherwise addr will map addr=1 to ..10 * Note that there should be a range for the shift operators * We should narrow the encoding to be applied to a given set of data * This will lead to that any addr which falls out of the op code of data * will give a all-zero code - * For example: - * data is 5-bit while addr is 3-bit + * For example: + * data is 5-bit while addr is 3-bit * data=8'b0_0000 will be encoded to addr=3'b001; * data=8'b0_0001 will be encoded to addr=3'b010; * data=8'b0_0010 will be encoded to addr=3'b011; @@ -112,37 +117,48 @@ void print_verilog_mux_local_decoder_module(std::fstream& fp, * The rest of addr codes 3'b110, 3'b111 will be decoded to data=8'b0_0000; */ - fp << "\t" << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl; - fp << "\t" << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl; + fp << "\t" + << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) + << ")" << std::endl; + fp << "\t" + << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" + << std::endl; /* Create a string for addr and data */ for (size_t i = 0; i < data_size; ++i) { - fp << "\t\t" << generate_verilog_constant_values(itobin_vec(i, addr_size)); + fp << "\t\t" << generate_verilog_constant_values(itobin_vec(i, addr_size)); fp << " : "; - fp << generate_verilog_port_constant_values(data_port, ito1hot_vec(i, data_size)); + fp << generate_verilog_port_constant_values(data_port, + ito1hot_vec(i, data_size)); fp << ";" << std::endl; } - fp << "\t\t" << "default : "; - fp << generate_verilog_port_constant_values(data_port, ito1hot_vec(data_size - 1, data_size)); + fp << "\t\t" + << "default : "; + fp << generate_verilog_port_constant_values( + data_port, ito1hot_vec(data_size - 1, data_size)); fp << ";" << std::endl; - fp << "\t" << "endcase" << std::endl; + fp << "\t" + << "endcase" << std::endl; print_verilog_wire_connection(fp, data_inv_port, data_port, true); - - print_verilog_comment(fp, std::string("----- END Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----")); + + print_verilog_comment( + fp, std::string("----- END Verilog codes for Decoder convert " + + std::to_string(addr_size) + "-bit addr to " + + std::to_string(data_size) + "-bit data -----")); /* Put an end to the Verilog module */ print_verilog_module_end(fp, module_name); } /*************************************************************************************** - * This function will generate all the unique Verilog modules of local decoders for - * the multiplexers used in a FPGA fabric - * It will reach the goal in two steps: - * 1. Find the unique local decoders w.r.t. the number of inputs/outputs - * We will generate the subgraphs from the multiplexing graph of each multiplexers - * The number of memory bits is the number of outputs. - * From that we can infer the number of inputs of each local decoders. - * Here is an illustrative example of how local decoders are interfaced with multi-level MUXes + * This function will generate all the unique Verilog modules of local decoders + *for the multiplexers used in a FPGA fabric It will reach the goal in two + *steps: + * 1. Find the unique local decoders w.r.t. the number of inputs/outputs + * We will generate the subgraphs from the multiplexing graph of each + *multiplexers The number of memory bits is the number of outputs. From that we + *can infer the number of inputs of each local decoders. Here is an illustrative + *example of how local decoders are interfaced with multi-level MUXes * * +---------+ +---------+ * | Local | | Local | @@ -155,19 +171,17 @@ void print_verilog_mux_local_decoder_module(std::fstream& fp, * | MUX Level 0 |--->| MUX Level 1 | * +--------------+ +--------------+ * 2. Generate local decoder Verilog modules using behavioral description. - * Note that the implementation of local decoders can be dependent on the technology - * and standard cell libraries. - * Therefore, behavioral Verilog is used and the local decoders should be synthesized - * before running the back-end flow for FPGA fabric - * See more details in the function print_verilog_mux_local_decoder() for more details + * Note that the implementation of local decoders can be dependent on the + *technology and standard cell libraries. Therefore, behavioral Verilog is used + *and the local decoders should be synthesized before running the back-end flow + *for FPGA fabric See more details in the function + *print_verilog_mux_local_decoder() for more details ***************************************************************************************/ -void print_verilog_submodule_mux_local_decoders(const ModuleManager& module_manager, - NetlistManager& netlist_manager, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const std::string& submodule_dir, - const std::string& submodule_dir_name, - const FabricVerilogOption& options) { +void print_verilog_submodule_mux_local_decoders( + const ModuleManager& module_manager, NetlistManager& netlist_manager, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, + const std::string& submodule_dir, const std::string& submodule_dir_name, + const FabricVerilogOption& options) { std::string verilog_fname(LOCAL_ENCODER_VERILOG_FILE_NAME); std::string verilog_fpath(submodule_dir + verilog_fname); @@ -177,19 +191,22 @@ void print_verilog_submodule_mux_local_decoders(const ModuleManager& module_mana check_file_stream(verilog_fpath.c_str(), fp); - /* Print out debugging information for if the file is not opened/created properly */ + /* Print out debugging information for if the file is not opened/created + * properly */ VTR_LOG("Writing Verilog netlist for local decoders for multiplexers '%s'...", - verilog_fpath.c_str()); + verilog_fpath.c_str()); - print_verilog_file_header(fp, "Local Decoders for Multiplexers", options.time_stamp()); + print_verilog_file_header(fp, "Local Decoders for Multiplexers", + options.time_stamp()); /* Create a library for local encoders with different sizes */ DecoderLibrary decoder_lib; - - /* Find unique local decoders for unique branches shared by the multiplexers */ + + /* Find unique local decoders for unique branches shared by the multiplexers + */ for (auto mux : mux_lib.muxes()) { /* Local decoders are need only when users specify them */ - CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); + CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); /* If this MUX does not need local decoder, we skip it */ if (false == circuit_lib.mux_use_local_encoder(mux_circuit_model)) { continue; @@ -197,7 +214,8 @@ void print_verilog_submodule_mux_local_decoders(const ModuleManager& module_mana const MuxGraph& mux_graph = mux_lib.mux_graph(mux); /* Create a mux graph for the branch circuit */ - std::vector branch_mux_graphs = mux_graph.build_mux_branch_graphs(); + std::vector branch_mux_graphs = + mux_graph.build_mux_branch_graphs(); /* Add the decoder to the decoder library */ for (auto branch_mux_graph : branch_mux_graphs) { /* The decoder size depends on the number of memories of a branch MUX. @@ -207,8 +225,8 @@ void print_verilog_submodule_mux_local_decoders(const ModuleManager& module_mana if (0 == decoder_data_size) { continue; } - /* Try to find if the decoder already exists in the library, - * If there is no such decoder, add it to the library + /* Try to find if the decoder already exists in the library, + * If there is no such decoder, add it to the library */ add_mux_local_decoder_to_library(decoder_lib, decoder_data_size); } @@ -216,7 +234,8 @@ void print_verilog_submodule_mux_local_decoders(const ModuleManager& module_mana /* Generate Verilog modules for the found unique local encoders */ for (const auto& decoder : decoder_lib.decoders()) { - print_verilog_mux_local_decoder_module(fp, module_manager, decoder_lib, decoder, options.default_net_type()); + print_verilog_mux_local_decoder_module(fp, module_manager, decoder_lib, + decoder, options.default_net_type()); } /* Close the file stream */ @@ -236,11 +255,11 @@ void print_verilog_submodule_mux_local_decoders(const ModuleManager& module_mana } /*************************************************************************************** - * Create a Verilog module for a decoder used as a configuration protocol + * Create a Verilog module for a decoder used as a configuration protocol * in FPGA architecture * * Address - * | | ... | + * | | ... | * v v v * +-----------+ * Enable->/ \ @@ -251,19 +270,17 @@ void print_verilog_submodule_mux_local_decoders(const ModuleManager& module_mana * Data output * * The outputs are assumes to be one-hot codes (at most only one '1' exist) - * Considering this fact, there are only num_of_outputs conditions to be encoded. - * Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2)) + * Considering this fact, there are only num_of_outputs conditions to be + *encoded. Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2)) * - * The decoder has an enable signal which is active at logic '1'. - * When activated, the decoder will output decoding results to the data output port - * Otherwise, the data output port will be always all-zero + * The decoder has an enable signal which is active at logic '1'. + * When activated, the decoder will output decoding results to the data output + *port Otherwise, the data output port will be always all-zero ***************************************************************************************/ -static -void print_verilog_arch_decoder_module(std::fstream& fp, - const ModuleManager& module_manager, - const DecoderLibrary& decoder_lib, - const DecoderId& decoder, - const e_verilog_default_net_type& default_net_type) { +static void print_verilog_arch_decoder_module( + std::fstream& fp, const ModuleManager& module_manager, + const DecoderLibrary& decoder_lib, const DecoderId& decoder, + const e_verilog_default_net_type& default_net_type) { /* Get the number of inputs */ size_t addr_size = decoder_lib.addr_size(decoder); size_t data_size = decoder_lib.data_size(decoder); @@ -272,49 +289,62 @@ void print_verilog_arch_decoder_module(std::fstream& fp, VTR_ASSERT(true == valid_file_stream(fp)); /* Create a name for the decoder */ - std::string module_name = generate_memory_decoder_subckt_name(addr_size, data_size); + std::string module_name = + generate_memory_decoder_subckt_name(addr_size, data_size); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = module_manager.find_module(module_name); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = module_manager.find_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(module_id)); /* Find module ports */ /* Enable port */ - ModulePortId enable_port_id = module_manager.find_module_port(module_id, std::string(DECODER_ENABLE_PORT_NAME)); + ModulePortId enable_port_id = module_manager.find_module_port( + module_id, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort enable_port = module_manager.module_port(module_id, enable_port_id); /* Address port */ - ModulePortId addr_port_id = module_manager.find_module_port(module_id, std::string(DECODER_ADDRESS_PORT_NAME)); + ModulePortId addr_port_id = module_manager.find_module_port( + module_id, std::string(DECODER_ADDRESS_PORT_NAME)); BasicPort addr_port = module_manager.module_port(module_id, addr_port_id); /* Find each output port */ - ModulePortId data_port_id = module_manager.find_module_port(module_id, std::string(DECODER_DATA_OUT_PORT_NAME)); + ModulePortId data_port_id = module_manager.find_module_port( + module_id, std::string(DECODER_DATA_OUT_PORT_NAME)); BasicPort data_port = module_manager.module_port(module_id, data_port_id); - /* Data port is registered. It should be outputted as - * output reg [lsb:msb] data + /* Data port is registered. It should be outputted as + * output reg [lsb:msb] data */ - BasicPort data_inv_port(std::string(DECODER_DATA_OUT_INV_PORT_NAME), data_size); + BasicPort data_inv_port(std::string(DECODER_DATA_OUT_INV_PORT_NAME), + data_size); if (true == decoder_lib.use_data_inv_port(decoder)) { - ModulePortId data_inv_port_id = module_manager.find_module_port(module_id, std::string(DECODER_DATA_OUT_INV_PORT_NAME)); + ModulePortId data_inv_port_id = module_manager.find_module_port( + module_id, std::string(DECODER_DATA_OUT_INV_PORT_NAME)); data_inv_port = module_manager.module_port(module_id, data_inv_port_id); } /* Find readback port */ - ModulePortId readback_port_id = module_manager.find_module_port(module_id, std::string(DECODER_READBACK_PORT_NAME)); + ModulePortId readback_port_id = module_manager.find_module_port( + module_id, std::string(DECODER_READBACK_PORT_NAME)); BasicPort readback_port; if (readback_port_id) { readback_port = module_manager.module_port(module_id, readback_port_id); } /* Find data read-enable port */ - ModulePortId data_ren_port_id = module_manager.find_module_port(module_id, std::string(DECODER_DATA_READ_ENABLE_PORT_NAME)); + ModulePortId data_ren_port_id = module_manager.find_module_port( + module_id, std::string(DECODER_DATA_READ_ENABLE_PORT_NAME)); BasicPort data_ren_port; if (data_ren_port_id) { data_ren_port = module_manager.module_port(module_id, data_ren_port_id); } /* dump module definition + ports */ - print_verilog_module_declaration(fp, module_manager, module_id, default_net_type); + print_verilog_module_declaration(fp, module_manager, module_id, + default_net_type); /* Finish dumping ports */ - print_verilog_comment(fp, std::string("----- BEGIN Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----")); + print_verilog_comment( + fp, std::string("----- BEGIN Verilog codes for Decoder convert " + + std::to_string(addr_size) + "-bit addr to " + + std::to_string(data_size) + "-bit data -----")); /* Print the truth table of this decoder */ /* Internal logics */ @@ -327,40 +357,65 @@ void print_verilog_arch_decoder_module(std::fstream& fp, /* Output logics for data output */ fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port); - /* If there is a readback port, the data output is only enabled when readback is disabled */ + /* If there is a readback port, the data output is only enabled when + * readback is disabled */ if (readback_port_id) { - fp << " or " << "~" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port); + fp << " or " + << "~" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port); } fp << ") begin" << std::endl; - fp << "\tif ((" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) && ("; + fp << "\tif ((" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) + << " == 1'b1) && ("; if (readback_port_id) { - fp << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b0) && ("; + fp << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) + << " == 1'b0) && ("; } - fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << " == 1'b0))"; + fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << " == 1'b0))"; fp << " begin" << std::endl; - fp << "\t\t" << generate_verilog_port_constant_values(data_port, std::vector(1, 1)) << ";" << std::endl; - fp << "\t" << "end else begin" << std::endl; - fp << "\t\t" << generate_verilog_port_constant_values(data_port, std::vector(1, 0)) << ";" << std::endl; - fp << "\t" << "end" << std::endl; + fp << "\t\t" + << generate_verilog_port_constant_values(data_port, + std::vector(1, 1)) + << ";" << std::endl; + fp << "\t" + << "end else begin" << std::endl; + fp << "\t\t" + << generate_verilog_port_constant_values(data_port, + std::vector(1, 0)) + << ";" << std::endl; + fp << "\t" + << "end" << std::endl; fp << "end" << std::endl; /* Output logics for data readback output */ if (data_ren_port_id) { fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port); - /* If there is a readback port, the data output is only enabled when readback is disabled */ + /* If there is a readback port, the data output is only enabled when + * readback is disabled */ if (readback_port_id) { - fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, readback_port); + fp << " or " + << generate_verilog_port(VERILOG_PORT_CONKT, readback_port); } fp << ") begin" << std::endl; - fp << "\tif ((" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) && ("; - fp << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b1) && ("; - fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << " == 1'b0))"; + fp << "\tif ((" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) + << " == 1'b1) && ("; + fp << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) + << " == 1'b1) && ("; + fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) + << " == 1'b0))"; fp << " begin" << std::endl; - fp << "\t\t" << generate_verilog_port_constant_values(data_ren_port, std::vector(1, 1)) << ";" << std::endl; - fp << "\t" << "end else begin" << std::endl; - fp << "\t\t" << generate_verilog_port_constant_values(data_ren_port, std::vector(1, 0)) << ";" << std::endl; - fp << "\t" << "end" << std::endl; + fp << "\t\t" + << generate_verilog_port_constant_values(data_ren_port, + std::vector(1, 1)) + << ";" << std::endl; + fp << "\t" + << "end else begin" << std::endl; + fp << "\t\t" + << generate_verilog_port_constant_values(data_ren_port, + std::vector(1, 0)) + << ";" << std::endl; + fp << "\t" + << "end" << std::endl; fp << "end" << std::endl; } @@ -369,7 +424,10 @@ void print_verilog_arch_decoder_module(std::fstream& fp, print_verilog_wire_connection(fp, data_inv_port, addr_port, true); } - print_verilog_comment(fp, std::string("----- END Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----")); + print_verilog_comment( + fp, std::string("----- END Verilog codes for Decoder convert " + + std::to_string(addr_size) + "-bit addr to " + + std::to_string(data_size) + "-bit data -----")); /* Put an end to the Verilog module */ print_verilog_module_end(fp, module_name); @@ -377,13 +435,13 @@ void print_verilog_arch_decoder_module(std::fstream& fp, } /* We use a magic number -1 as the addr=1 should be mapped to ...1 - * Otherwise addr will map addr=1 to ..10 + * Otherwise addr will map addr=1 to ..10 * Note that there should be a range for the shift operators * We should narrow the encoding to be applied to a given set of data * This will lead to that any addr which falls out of the op code of data * will give a all-zero code - * For example: - * data is 5-bit while addr is 3-bit + * For example: + * data is 5-bit while addr is 3-bit * data=8'b0_0000 will be encoded to addr=3'b001; * data=8'b0_0001 will be encoded to addr=3'b010; * data=8'b0_0010 will be encoded to addr=3'b011; @@ -395,102 +453,137 @@ void print_verilog_arch_decoder_module(std::fstream& fp, /* Output logics for data output */ fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); - /* If there is a readback port, the data output is only enabled when readback is disabled */ + /* If there is a readback port, the data output is only enabled when readback + * is disabled */ if (readback_port_id) { - fp << " or " << "~" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port); + fp << " or " + << "~" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port); } fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port); fp << ") begin" << std::endl; if (readback_port_id) { fp << "\tif ("; - fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) "; + fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) + << " == 1'b1) "; fp << "&&"; - fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b0) "; + fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) + << " == 1'b0) "; fp << ") begin" << std::endl; } else { - fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) begin" << std::endl; + fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) + << " == 1'b1) begin" << std::endl; } - fp << "\t\t" << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl; + fp << "\t\t" + << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" + << std::endl; /* Create a string for addr and data */ for (size_t i = 0; i < data_size; ++i) { - fp << "\t\t\t" << generate_verilog_constant_values(itobin_vec(i, addr_size)); + fp << "\t\t\t" + << generate_verilog_constant_values(itobin_vec(i, addr_size)); fp << " : "; - fp << generate_verilog_port_constant_values(data_port, ito1hot_vec(i, data_size)); + fp << generate_verilog_port_constant_values(data_port, + ito1hot_vec(i, data_size)); fp << ";" << std::endl; } /* Different from MUX decoder, we assign default values which is all zero */ - fp << "\t\t\t" << "default"; + fp << "\t\t\t" + << "default"; fp << " : "; - fp << generate_verilog_port_constant_values(data_port, ito1hot_vec(data_size, data_size)); + fp << generate_verilog_port_constant_values( + data_port, ito1hot_vec(data_size, data_size)); fp << ";" << std::endl; - fp << "\t\t" << "endcase" << std::endl; - fp << "\t" << "end" << std::endl; + fp << "\t\t" + << "endcase" << std::endl; + fp << "\t" + << "end" << std::endl; /* If enable is not active, we should give all zero */ - fp << "\t" << "else begin" << std::endl; - fp << "\t\t" << generate_verilog_port_constant_values(data_port, ito1hot_vec(data_size, data_size)); + fp << "\t" + << "else begin" << std::endl; + fp << "\t\t" + << generate_verilog_port_constant_values( + data_port, ito1hot_vec(data_size, data_size)); fp << ";" << std::endl; - fp << "\t" << "end" << std::endl; - + fp << "\t" + << "end" << std::endl; + fp << "end" << std::endl; /* Output logics for data readback output */ if (data_ren_port_id) { fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); - /* If there is a readback port, the data output is only enabled when readback is disabled */ + /* If there is a readback port, the data output is only enabled when + * readback is disabled */ if (readback_port_id) { fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, readback_port); } fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port); fp << ") begin" << std::endl; fp << "\tif ("; - fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) "; + fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) + << " == 1'b1) "; fp << "&&"; - fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b1) "; + fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) + << " == 1'b1) "; fp << ") begin" << std::endl; - fp << "\t\t" << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl; + fp << "\t\t" + << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) + << ")" << std::endl; /* Create a string for addr and data */ for (size_t i = 0; i < data_size; ++i) { - fp << "\t\t\t" << generate_verilog_constant_values(itobin_vec(i, addr_size)); + fp << "\t\t\t" + << generate_verilog_constant_values(itobin_vec(i, addr_size)); fp << " : "; - fp << generate_verilog_port_constant_values(data_ren_port, ito1hot_vec(i, data_size)); + fp << generate_verilog_port_constant_values(data_ren_port, + ito1hot_vec(i, data_size)); fp << ";" << std::endl; } /* Different from MUX decoder, we assign default values which is all zero */ - fp << "\t\t\t" << "default"; + fp << "\t\t\t" + << "default"; fp << " : "; - fp << generate_verilog_port_constant_values(data_ren_port, ito1hot_vec(data_size, data_size)); + fp << generate_verilog_port_constant_values( + data_ren_port, ito1hot_vec(data_size, data_size)); fp << ";" << std::endl; - fp << "\t\t" << "endcase" << std::endl; - fp << "\t" << "end" << std::endl; + fp << "\t\t" + << "endcase" << std::endl; + fp << "\t" + << "end" << std::endl; /* If enable is not active, we should give all zero */ - fp << "\t" << "else begin" << std::endl; - fp << "\t\t" << generate_verilog_port_constant_values(data_ren_port, ito1hot_vec(data_size, data_size)); + fp << "\t" + << "else begin" << std::endl; + fp << "\t\t" + << generate_verilog_port_constant_values( + data_ren_port, ito1hot_vec(data_size, data_size)); fp << ";" << std::endl; - fp << "\t" << "end" << std::endl; - + fp << "\t" + << "end" << std::endl; + fp << "end" << std::endl; } if (true == decoder_lib.use_data_inv_port(decoder)) { print_verilog_wire_connection(fp, data_inv_port, data_port, true); } - - print_verilog_comment(fp, std::string("----- END Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----")); + + print_verilog_comment( + fp, std::string("----- END Verilog codes for Decoder convert " + + std::to_string(addr_size) + "-bit addr to " + + std::to_string(data_size) + "-bit data -----")); /* Put an end to the Verilog module */ print_verilog_module_end(fp, module_name); } /*************************************************************************************** - * Create a Verilog module for a decoder with data_in used as a configuration protocol - * in FPGA architecture + * Create a Verilog module for a decoder with data_in used as a configuration + *protocol in FPGA architecture * * Address - * | | ... | + * | | ... | * v v v * +-----------+ * Enable->/ \<-data_in @@ -503,16 +596,14 @@ void print_verilog_arch_decoder_module(std::fstream& fp, * The outputs are assumes to be one-hot codes (at most only one '1' exist) * Only the data output at the address bit will show data_in * - * The decoder has an enable signal which is active at logic '1'. - * When activated, the decoder will output decoding results to the data output port - * Otherwise, the data output port will be always all-zero + * The decoder has an enable signal which is active at logic '1'. + * When activated, the decoder will output decoding results to the data output + *port Otherwise, the data output port will be always all-zero ***************************************************************************************/ -static -void print_verilog_arch_decoder_with_data_in_module(std::fstream& fp, - const ModuleManager& module_manager, - const DecoderLibrary& decoder_lib, - const DecoderId& decoder, - const e_verilog_default_net_type& default_net_type) { +static void print_verilog_arch_decoder_with_data_in_module( + std::fstream& fp, const ModuleManager& module_manager, + const DecoderLibrary& decoder_lib, const DecoderId& decoder, + const e_verilog_default_net_type& default_net_type) { /* Get the number of inputs */ size_t addr_size = decoder_lib.addr_size(decoder); size_t data_size = decoder_lib.data_size(decoder); @@ -522,54 +613,73 @@ void print_verilog_arch_decoder_with_data_in_module(std::fstream& fp, VTR_ASSERT(true == valid_file_stream(fp)); /* Create a name for the decoder */ - std::string module_name = generate_memory_decoder_with_data_in_subckt_name(addr_size, data_size); + std::string module_name = + generate_memory_decoder_with_data_in_subckt_name(addr_size, data_size); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = module_manager.find_module(module_name); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = module_manager.find_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(module_id)); /* Find module ports */ /* Enable port */ - ModulePortId enable_port_id = module_manager.find_module_port(module_id, std::string(DECODER_ENABLE_PORT_NAME)); + ModulePortId enable_port_id = module_manager.find_module_port( + module_id, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort enable_port = module_manager.module_port(module_id, enable_port_id); /* Address port */ - ModulePortId addr_port_id = module_manager.find_module_port(module_id, std::string(DECODER_ADDRESS_PORT_NAME)); + ModulePortId addr_port_id = module_manager.find_module_port( + module_id, std::string(DECODER_ADDRESS_PORT_NAME)); BasicPort addr_port = module_manager.module_port(module_id, addr_port_id); /* Find data-in port*/ - ModulePortId din_port_id = module_manager.find_module_port(module_id, std::string(DECODER_DATA_IN_PORT_NAME)); + ModulePortId din_port_id = module_manager.find_module_port( + module_id, std::string(DECODER_DATA_IN_PORT_NAME)); BasicPort din_port = module_manager.module_port(module_id, din_port_id); /* Find each output port */ - ModulePortId data_port_id = module_manager.find_module_port(module_id, std::string(DECODER_DATA_OUT_PORT_NAME)); + ModulePortId data_port_id = module_manager.find_module_port( + module_id, std::string(DECODER_DATA_OUT_PORT_NAME)); BasicPort data_port = module_manager.module_port(module_id, data_port_id); - /* Data port is registered. It should be outputted as - * output reg [lsb:msb] data + /* Data port is registered. It should be outputted as + * output reg [lsb:msb] data */ - BasicPort data_inv_port(std::string(DECODER_DATA_OUT_INV_PORT_NAME), data_size); + BasicPort data_inv_port(std::string(DECODER_DATA_OUT_INV_PORT_NAME), + data_size); if (true == decoder_lib.use_data_inv_port(decoder)) { - ModulePortId data_inv_port_id = module_manager.find_module_port(module_id, std::string(DECODER_DATA_OUT_INV_PORT_NAME)); + ModulePortId data_inv_port_id = module_manager.find_module_port( + module_id, std::string(DECODER_DATA_OUT_INV_PORT_NAME)); data_inv_port = module_manager.module_port(module_id, data_inv_port_id); } /* dump module definition + ports */ - print_verilog_module_declaration(fp, module_manager, module_id, default_net_type); + print_verilog_module_declaration(fp, module_manager, module_id, + default_net_type); /* Finish dumping ports */ - print_verilog_comment(fp, std::string("----- BEGIN Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----")); + print_verilog_comment( + fp, std::string("----- BEGIN Verilog codes for Decoder convert " + + std::to_string(addr_size) + "-bit addr to " + + std::to_string(data_size) + "-bit data -----")); /* Print the truth table of this decoder */ /* Internal logics */ /* Early exit: Corner case for data size = 1 the logic is very simple: - * data = addr; + * data = addr; * data_inv = ~data_inv */ if (1 == data_size) { fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port); fp << ") begin" << std::endl; - fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) begin" << std::endl; - fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, din_port) << ";" << std::endl; - fp << "\t" << "end else begin" << std::endl; - fp << "\t\t" << generate_verilog_port_constant_values(data_port, std::vector(1, 0)) << ";" << std::endl; - fp << "\t" << "end" << std::endl; + fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) + << " == 1'b1) begin" << std::endl; + fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, din_port) << ";" + << std::endl; + fp << "\t" + << "end else begin" << std::endl; + fp << "\t\t" + << generate_verilog_port_constant_values(data_port, + std::vector(1, 0)) + << ";" << std::endl; + fp << "\t" + << "end" << std::endl; fp << "end" << std::endl; /* Depend on if the inverted data output port is needed or not */ @@ -577,14 +687,17 @@ void print_verilog_arch_decoder_with_data_in_module(std::fstream& fp, print_verilog_wire_connection(fp, data_inv_port, addr_port, true); } - print_verilog_comment(fp, std::string("----- END Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----")); + print_verilog_comment( + fp, std::string("----- END Verilog codes for Decoder convert " + + std::to_string(addr_size) + "-bit addr to " + + std::to_string(data_size) + "-bit data -----")); /* Put an end to the Verilog module */ print_verilog_module_end(fp, module_name); return; } - /* Only the selected data output bit will be set to the value of data_in, + /* Only the selected data output bit will be set to the value of data_in, * other data output bits will be '0' */ fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); @@ -592,71 +705,81 @@ void print_verilog_arch_decoder_with_data_in_module(std::fstream& fp, fp << ", " << generate_verilog_port(VERILOG_PORT_CONKT, din_port); fp << ") begin" << std::endl; - fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) begin" << std::endl; - fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, data_port); + fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) + << " == 1'b1) begin" << std::endl; + fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, data_port); fp << " = "; - std::string high_res_str = "{" + std::to_string(data_port.get_width()) + "{1'bz}}"; + std::string high_res_str = + "{" + std::to_string(data_port.get_width()) + "{1'bz}}"; fp << high_res_str; fp << ";" << std::endl; - fp << "\t\t" << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl; + fp << "\t\t" + << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" + << std::endl; /* Create a string for addr and data */ for (size_t i = 0; i < data_size; ++i) { BasicPort cur_data_port(data_port.get_name(), i, i); - fp << "\t\t\t" << generate_verilog_constant_values(itobin_vec(i, addr_size)); + fp << "\t\t\t" + << generate_verilog_constant_values(itobin_vec(i, addr_size)); fp << " : "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, cur_data_port); + fp << generate_verilog_port(VERILOG_PORT_CONKT, cur_data_port); fp << " = "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port); + fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port); fp << ";" << std::endl; } /* Different from MUX decoder, we assign default values which is all zero */ - fp << "\t\t\t" << "default"; + fp << "\t\t\t" + << "default"; fp << " : "; - fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, data_port); + fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, data_port); fp << " = "; fp << high_res_str; fp << ";" << std::endl; - fp << "\t\t" << "endcase" << std::endl; - fp << "\t" << "end" << std::endl; + fp << "\t\t" + << "endcase" << std::endl; + fp << "\t" + << "end" << std::endl; /* If enable is not active, we should give all zero */ - fp << "\t" << "else begin" << std::endl; - fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, data_port); + fp << "\t" + << "else begin" << std::endl; + fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, data_port); fp << " = "; fp << high_res_str; fp << ";" << std::endl; - fp << "\t" << "end" << std::endl; - - fp << "end" << std::endl; + fp << "\t" + << "end" << std::endl; + fp << "end" << std::endl; if (true == decoder_lib.use_data_inv_port(decoder)) { print_verilog_wire_connection(fp, data_inv_port, data_port, true); } - - print_verilog_comment(fp, std::string("----- END Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----")); + + print_verilog_comment( + fp, std::string("----- END Verilog codes for Decoder convert " + + std::to_string(addr_size) + "-bit addr to " + + std::to_string(data_size) + "-bit data -----")); /* Put an end to the Verilog module */ print_verilog_module_end(fp, module_name); } /*************************************************************************************** - * This function will generate all the unique Verilog modules of decoders for + * This function will generate all the unique Verilog modules of decoders for * configuration protocols in a FPGA fabric * It will generate these decoder Verilog modules using behavioral description. - * Note that the implementation of local decoders can be dependent on the technology - * and standard cell libraries. - * Therefore, behavioral Verilog is used and the local decoders should be synthesized - * before running the back-end flow for FPGA fabric - * See more details in the function print_verilog_arch_decoder() for more details + * Note that the implementation of local decoders can be dependent on the + *technology and standard cell libraries. Therefore, behavioral Verilog is used + *and the local decoders should be synthesized before running the back-end flow + *for FPGA fabric See more details in the function print_verilog_arch_decoder() + *for more details ***************************************************************************************/ -void print_verilog_submodule_arch_decoders(const ModuleManager& module_manager, - NetlistManager& netlist_manager, - const DecoderLibrary& decoder_lib, - const std::string& submodule_dir, - const std::string& submodule_dir_name, - const FabricVerilogOption& options) { +void print_verilog_submodule_arch_decoders( + const ModuleManager& module_manager, NetlistManager& netlist_manager, + const DecoderLibrary& decoder_lib, const std::string& submodule_dir, + const std::string& submodule_dir_name, const FabricVerilogOption& options) { std::string verilog_fname(ARCH_ENCODER_VERILOG_FILE_NAME); std::string verilog_fpath(submodule_dir + verilog_fname); @@ -666,18 +789,22 @@ void print_verilog_submodule_arch_decoders(const ModuleManager& module_manager, check_file_stream(verilog_fpath.c_str(), fp); - /* Print out debugging information for if the file is not opened/created properly */ + /* Print out debugging information for if the file is not opened/created + * properly */ VTR_LOG("Writing Verilog netlist for configuration decoders '%s'...", - verilog_fpath.c_str()); + verilog_fpath.c_str()); - print_verilog_file_header(fp, "Decoders for fabric configuration protocol", options.time_stamp()); + print_verilog_file_header(fp, "Decoders for fabric configuration protocol", + options.time_stamp()); /* Generate Verilog modules for the found unique local encoders */ for (const auto& decoder : decoder_lib.decoders()) { if (true == decoder_lib.use_data_in(decoder)) { - print_verilog_arch_decoder_with_data_in_module(fp, module_manager, decoder_lib, decoder, options.default_net_type()); + print_verilog_arch_decoder_with_data_in_module( + fp, module_manager, decoder_lib, decoder, options.default_net_type()); } else { - print_verilog_arch_decoder_module(fp, module_manager, decoder_lib, decoder, options.default_net_type()); + print_verilog_arch_decoder_module(fp, module_manager, decoder_lib, + decoder, options.default_net_type()); } } diff --git a/openfpga/src/fpga_verilog/verilog_decoders.h b/openfpga/src/fpga_verilog/verilog_decoders.h index cfc586da4..b94edda10 100644 --- a/openfpga/src/fpga_verilog/verilog_decoders.h +++ b/openfpga/src/fpga_verilog/verilog_decoders.h @@ -9,13 +9,13 @@ #include #include "circuit_library.h" +#include "decoder_library.h" +#include "fabric_verilog_options.h" +#include "module_manager.h" #include "mux_graph.h" #include "mux_library.h" -#include "decoder_library.h" -#include "module_manager.h" #include "netlist_manager.h" #include "verilog_port_types.h" -#include "fabric_verilog_options.h" /******************************************************************** * Function declaration @@ -24,21 +24,16 @@ /* begin namespace openfpga */ namespace openfpga { -void print_verilog_submodule_mux_local_decoders(const ModuleManager& module_manager, - NetlistManager& netlist_manager, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const std::string& submodule_dir, - const std::string& submodule_dir_name, - const FabricVerilogOption& options); - -void print_verilog_submodule_arch_decoders(const ModuleManager& module_manager, - NetlistManager& netlist_manager, - const DecoderLibrary& decoder_lib, - const std::string& submodule_dir, - const std::string& submodule_dir_name, - const FabricVerilogOption& options); +void print_verilog_submodule_mux_local_decoders( + const ModuleManager& module_manager, NetlistManager& netlist_manager, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, + const std::string& submodule_dir, const std::string& submodule_dir_name, + const FabricVerilogOption& options); +void print_verilog_submodule_arch_decoders( + const ModuleManager& module_manager, NetlistManager& netlist_manager, + const DecoderLibrary& decoder_lib, const std::string& submodule_dir, + const std::string& submodule_dir_name, const FabricVerilogOption& options); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_essential_gates.cpp b/openfpga/src/fpga_verilog/verilog_essential_gates.cpp index b1f04d7eb..98b32bd8e 100644 --- a/openfpga/src/fpga_verilog/verilog_essential_gates.cpp +++ b/openfpga/src/fpga_verilog/verilog_essential_gates.cpp @@ -1,8 +1,8 @@ /************************************************ - * This file includes functions on + * This file includes functions on * outputting Verilog netlists for essential gates * which are inverters, buffers, transmission-gates - * logic gates etc. + * logic gates etc. ***********************************************/ #include @@ -11,39 +11,37 @@ #include "vtr_log.h" /* Headers from openfpgautil library */ -#include "openfpga_port.h" -#include "openfpga_digest.h" - -#include "openfpga_naming.h" #include "module_manager.h" #include "module_manager_utils.h" - +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" #include "verilog_constants.h" -#include "verilog_writer_utils.h" -#include "verilog_submodule_utils.h" #include "verilog_essential_gates.h" +#include "verilog_submodule_utils.h" +#include "verilog_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { /************************************************ - * Print Verilog body codes of a power-gated inverter + * Print Verilog body codes of a power-gated inverter * This function does NOT generate any port map ! ***********************************************/ -static -void print_verilog_power_gated_invbuf_body(std::fstream& fp, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const CircuitPortId& input_port, - const CircuitPortId& output_port, - const std::vector& power_gate_ports) { +static void print_verilog_power_gated_invbuf_body( + std::fstream& fp, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, const CircuitPortId& input_port, + const CircuitPortId& output_port, + const std::vector& power_gate_ports) { /* Ensure a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); - print_verilog_comment(fp, std::string("----- Verilog codes of a power-gated inverter -----")); + print_verilog_comment( + fp, std::string("----- Verilog codes of a power-gated inverter -----")); /* Create a sensitive list */ - fp << "\treg " << circuit_lib.port_lib_name(output_port) << "_reg;" << std::endl; + fp << "\treg " << circuit_lib.port_lib_name(output_port) << "_reg;" + << std::endl; fp << "\talways @("; /* Power-gate port first*/ @@ -55,7 +53,7 @@ void print_verilog_power_gated_invbuf_body(std::fstream& fp, fp << circuit_lib.port_lib_name(power_gate_port); fp << ", "; } - fp << circuit_lib.port_lib_name(input_port) << ") begin" << std::endl; + fp << circuit_lib.port_lib_name(input_port) << ") begin" << std::endl; /* Dump the case of power-gated */ fp << "\t\tif ("; @@ -67,118 +65,129 @@ void print_verilog_power_gated_invbuf_body(std::fstream& fp, continue; } for (const auto& power_gate_pin : circuit_lib.pins(power_gate_port)) { - if (0 < port_cnt) { + if (0 < port_cnt) { fp << std::endl << "\t\t&&"; } fp << "("; - /* Power-gated signal are disable during operating, enabled during configuration, - * Therefore, we need to reverse them here + /* Power-gated signal are disable during operating, enabled during + * configuration, Therefore, we need to reverse them here */ if (1 == circuit_lib.port_default_value(power_gate_port)) { fp << "~"; } - - fp << circuit_lib.port_lib_name(power_gate_port) << "[" << power_gate_pin << "])"; + + fp << circuit_lib.port_lib_name(power_gate_port) << "[" << power_gate_pin + << "])"; port_cnt++; /* Update port counter*/ } } fp << ") begin" << std::endl; - fp << "\t\t\tassign " << circuit_lib.port_lib_name(output_port) << "_reg = "; + fp << "\t\t\tassign " << circuit_lib.port_lib_name(output_port) << "_reg = "; - /* Branch on the type of inverter/buffer: - * 1. If this is an inverter or an tapered(multi-stage) buffer with odd number of stages, - * we invert the input to output - * 2. If this is a buffer or an tapere(multi-stage) buffer with even number of stages, - * we wire the input to output + /* Branch on the type of inverter/buffer: + * 1. If this is an inverter or an tapered(multi-stage) buffer with odd number + * of stages, we invert the input to output + * 2. If this is a buffer or an tapere(multi-stage) buffer with even number of + * stages, we wire the input to output */ - if ( (CIRCUIT_MODEL_BUF_INV == circuit_lib.buffer_type(circuit_model)) - || ( (CIRCUIT_MODEL_BUF_BUF == circuit_lib.buffer_type(circuit_model)) - && (size_t(-1) != circuit_lib.buffer_num_levels(circuit_model)) - && (1 == circuit_lib.buffer_num_levels(circuit_model) % 2 ) ) ) { + if ((CIRCUIT_MODEL_BUF_INV == circuit_lib.buffer_type(circuit_model)) || + ((CIRCUIT_MODEL_BUF_BUF == circuit_lib.buffer_type(circuit_model)) && + (size_t(-1) != circuit_lib.buffer_num_levels(circuit_model)) && + (1 == circuit_lib.buffer_num_levels(circuit_model) % 2))) { fp << "~"; - } + } fp << circuit_lib.port_lib_name(input_port) << ";" << std::endl; fp << "\t\tend else begin" << std::endl; - fp << "\t\t\tassign " << circuit_lib.port_lib_name(output_port) << "_reg = 1'bz;" << std::endl; + fp << "\t\t\tassign " << circuit_lib.port_lib_name(output_port) + << "_reg = 1'bz;" << std::endl; fp << "\t\tend" << std::endl; fp << "\tend" << std::endl; - fp << "\tassign " << circuit_lib.port_lib_name(output_port) << " = " << circuit_lib.port_lib_name(output_port) << "_reg;" << std::endl; + fp << "\tassign " << circuit_lib.port_lib_name(output_port) << " = " + << circuit_lib.port_lib_name(output_port) << "_reg;" << std::endl; } /************************************************ - * Print Verilog body codes of a regular inverter + * Print Verilog body codes of a regular inverter * This function does NOT generate any port map ! ***********************************************/ -static -void print_verilog_invbuf_body(std::fstream& fp, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const CircuitPortId& input_port, - const CircuitPortId& output_port) { +static void print_verilog_invbuf_body(std::fstream& fp, + const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const CircuitPortId& input_port, + const CircuitPortId& output_port) { /* Ensure a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); - print_verilog_comment(fp, std::string("----- Verilog codes of a regular inverter -----")); - - fp << "\tassign " << circuit_lib.port_lib_name(output_port) << " = (" << circuit_lib.port_lib_name(input_port) << " === 1'bz)? $random : "; + print_verilog_comment( + fp, std::string("----- Verilog codes of a regular inverter -----")); - /* Branch on the type of inverter/buffer: - * 1. If this is an inverter or an tapered(multi-stage) buffer with odd number of stages, - * we invert the input to output - * 2. If this is a buffer or an tapere(multi-stage) buffer with even number of stages, - * we wire the input to output + fp << "\tassign " << circuit_lib.port_lib_name(output_port) << " = (" + << circuit_lib.port_lib_name(input_port) << " === 1'bz)? $random : "; + + /* Branch on the type of inverter/buffer: + * 1. If this is an inverter or an tapered(multi-stage) buffer with odd number + * of stages, we invert the input to output + * 2. If this is a buffer or an tapere(multi-stage) buffer with even number of + * stages, we wire the input to output */ - if ( (CIRCUIT_MODEL_BUF_INV == circuit_lib.buffer_type(circuit_model)) - || ( (CIRCUIT_MODEL_BUF_BUF == circuit_lib.buffer_type(circuit_model)) - && (size_t(-1) != circuit_lib.buffer_num_levels(circuit_model)) - && (1 == circuit_lib.buffer_num_levels(circuit_model) % 2 ) ) ) { + if ((CIRCUIT_MODEL_BUF_INV == circuit_lib.buffer_type(circuit_model)) || + ((CIRCUIT_MODEL_BUF_BUF == circuit_lib.buffer_type(circuit_model)) && + (size_t(-1) != circuit_lib.buffer_num_levels(circuit_model)) && + (1 == circuit_lib.buffer_num_levels(circuit_model) % 2))) { fp << "~"; - } + } fp << circuit_lib.port_lib_name(input_port) << ";" << std::endl; } /************************************************ - * Print a Verilog module of inverter or buffer - * or tapered buffer to a file + * Print a Verilog module of inverter or buffer + * or tapered buffer to a file ***********************************************/ -static -void print_verilog_invbuf_module(const ModuleManager& module_manager, - std::fstream& fp, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const e_verilog_default_net_type& default_net_type) { +static void print_verilog_invbuf_module( + const ModuleManager& module_manager, std::fstream& fp, + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const e_verilog_default_net_type& default_net_type) { /* Ensure a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); /* Find the input port, output port and global inputs*/ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); - std::vector global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector global_ports = + circuit_lib.model_global_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); /* Make sure: - * There is only 1 input port and 1 output port, + * There is only 1 input port and 1 output port, * each size of which is 1 */ - VTR_ASSERT( (1 == input_ports.size()) && (1 == circuit_lib.port_size(input_ports[0])) ); - VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + VTR_ASSERT((1 == input_ports.size()) && + (1 == circuit_lib.port_size(input_ports[0]))); + VTR_ASSERT((1 == output_ports.size()) && + (1 == circuit_lib.port_size(output_ports[0]))); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = module_manager.find_module(circuit_lib.model_name(circuit_model)); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = + module_manager.find_module(circuit_lib.model_name(circuit_model)); VTR_ASSERT(true == module_manager.valid_module_id(module_id)); /* dump module definition + ports */ - print_verilog_module_declaration(fp, module_manager, module_id, default_net_type); + print_verilog_module_declaration(fp, module_manager, module_id, + default_net_type); /* Finish dumping ports */ /* Assign logics : depending on topology */ /* Error out for unsupported technology */ - if ( ( CIRCUIT_MODEL_BUF_INV != circuit_lib.buffer_type(circuit_model)) - && ( CIRCUIT_MODEL_BUF_BUF != circuit_lib.buffer_type(circuit_model)) ) { + if ((CIRCUIT_MODEL_BUF_INV != circuit_lib.buffer_type(circuit_model)) && + (CIRCUIT_MODEL_BUF_BUF != circuit_lib.buffer_type(circuit_model))) { VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid topology for circuit model '%s'!\n", circuit_lib.model_name(circuit_model).c_str()); @@ -187,10 +196,13 @@ void print_verilog_invbuf_module(const ModuleManager& module_manager, if (true == circuit_lib.is_power_gated(circuit_model)) { /* Output Verilog codes for a power-gated inverter */ - print_verilog_power_gated_invbuf_body(fp, circuit_lib, circuit_model, input_ports[0], output_ports[0], global_ports); + print_verilog_power_gated_invbuf_body(fp, circuit_lib, circuit_model, + input_ports[0], output_ports[0], + global_ports); } else { /* Output Verilog codes for a regular inverter */ - print_verilog_invbuf_body(fp, circuit_lib, circuit_model, input_ports[0], output_ports[0]); + print_verilog_invbuf_body(fp, circuit_lib, circuit_model, input_ports[0], + output_ports[0]); } /* Print timing info */ @@ -204,67 +216,74 @@ void print_verilog_invbuf_module(const ModuleManager& module_manager, * Print a Verilog module of a pass-gate, * either transmission-gate or pass-transistor ***********************************************/ -static -void print_verilog_passgate_module(const ModuleManager& module_manager, - std::fstream& fp, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const e_verilog_default_net_type& default_net_type) { +static void print_verilog_passgate_module( + const ModuleManager& module_manager, std::fstream& fp, + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const e_verilog_default_net_type& default_net_type) { /* Ensure a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); /* Find the input port, output port*/ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); - std::vector global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector global_ports = + circuit_lib.model_global_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); switch (circuit_lib.pass_gate_logic_type(circuit_model)) { - case CIRCUIT_MODEL_PASS_GATE_TRANSMISSION: - /* Make sure: - * There is only 3 input port (in, sel, selb), - * each size of which is 1 - */ - VTR_ASSERT( 3 == input_ports.size() ); - for (const auto& input_port : input_ports) { - VTR_ASSERT(1 == circuit_lib.port_size(input_port)); - } - break; - case CIRCUIT_MODEL_PASS_GATE_TRANSISTOR: - /* Make sure: - * There is only 2 input port (in, sel), - * each size of which is 1 - */ - VTR_ASSERT( 2 == input_ports.size() ); - for (const auto& input_port : input_ports) { - VTR_ASSERT(1 == circuit_lib.port_size(input_port)); - } - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid topology for circuit model '%s'!\n", - circuit_lib.model_name(circuit_model).c_str()); - exit(1); + case CIRCUIT_MODEL_PASS_GATE_TRANSMISSION: + /* Make sure: + * There is only 3 input port (in, sel, selb), + * each size of which is 1 + */ + VTR_ASSERT(3 == input_ports.size()); + for (const auto& input_port : input_ports) { + VTR_ASSERT(1 == circuit_lib.port_size(input_port)); + } + break; + case CIRCUIT_MODEL_PASS_GATE_TRANSISTOR: + /* Make sure: + * There is only 2 input port (in, sel), + * each size of which is 1 + */ + VTR_ASSERT(2 == input_ports.size()); + for (const auto& input_port : input_ports) { + VTR_ASSERT(1 == circuit_lib.port_size(input_port)); + } + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid topology for circuit model '%s'!\n", + circuit_lib.model_name(circuit_model).c_str()); + exit(1); } /* Make sure: - * There is only 1 output port, + * There is only 1 output port, * each size of which is 1 */ - VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + VTR_ASSERT((1 == output_ports.size()) && + (1 == circuit_lib.port_size(output_ports[0]))); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = module_manager.find_module(circuit_lib.model_name(circuit_model)); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = + module_manager.find_module(circuit_lib.model_name(circuit_model)); VTR_ASSERT(true == module_manager.valid_module_id(module_id)); /* dump module definition + ports */ - print_verilog_module_declaration(fp, module_manager, module_id, default_net_type); + print_verilog_module_declaration(fp, module_manager, module_id, + default_net_type); /* Finish dumping ports */ - /* Dump logics: we propagate input to the output when the gate is '1' + /* Dump logics: we propagate input to the output when the gate is '1' * the input is blocked from output when the gate is '0' */ fp << "\tassign " << circuit_lib.port_lib_name(output_ports[0]) << " = "; - fp << circuit_lib.port_lib_name(input_ports[1]) << " ? " << circuit_lib.port_lib_name(input_ports[0]); + fp << circuit_lib.port_lib_name(input_ports[1]) << " ? " + << circuit_lib.port_lib_name(input_ports[0]); fp << " : 1'bz;" << std::endl; /* Print timing info */ @@ -277,38 +296,43 @@ void print_verilog_passgate_module(const ModuleManager& module_manager, /************************************************ * Print Verilog body codes of an N-input AND gate ***********************************************/ -static -void print_verilog_and_or_gate_body(std::fstream& fp, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const std::vector& input_ports, - const std::vector& output_ports) { +static void print_verilog_and_or_gate_body( + std::fstream& fp, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const std::vector& input_ports, + const std::vector& output_ports) { /* Ensure a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); /* Find the logic operator for the gate */ std::string gate_verilog_operator; switch (circuit_lib.gate_type(circuit_model)) { - case CIRCUIT_MODEL_GATE_AND: - gate_verilog_operator = "&"; - break; - case CIRCUIT_MODEL_GATE_OR: - gate_verilog_operator = "|"; - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid topology for circuit model '%s'!\n", - circuit_lib.model_name(circuit_model).c_str()); - exit(1); + case CIRCUIT_MODEL_GATE_AND: + gate_verilog_operator = "&"; + break; + case CIRCUIT_MODEL_GATE_OR: + gate_verilog_operator = "|"; + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid topology for circuit model '%s'!\n", + circuit_lib.model_name(circuit_model).c_str()); + exit(1); } /* Output verilog codes */ - print_verilog_comment(fp, std::string("----- Verilog codes of a " + std::to_string(input_ports.size()) + "-input " + std::to_string(output_ports.size()) + "-output AND gate -----")); + print_verilog_comment( + fp, std::string("----- Verilog codes of a " + + std::to_string(input_ports.size()) + "-input " + + std::to_string(output_ports.size()) + + "-output AND gate -----")); for (const auto& output_port : output_ports) { for (const auto& output_pin : circuit_lib.pins(output_port)) { - BasicPort output_port_info(circuit_lib.port_lib_name(output_port), output_pin, output_pin); - fp << "\tassign " << generate_verilog_port(VERILOG_PORT_CONKT, output_port_info); + BasicPort output_port_info(circuit_lib.port_lib_name(output_port), + output_pin, output_pin); + fp << "\tassign " + << generate_verilog_port(VERILOG_PORT_CONKT, output_port_info); fp << " = "; size_t port_cnt = 0; @@ -319,10 +343,11 @@ void print_verilog_and_or_gate_body(std::fstream& fp, fp << " " << gate_verilog_operator << " "; } - BasicPort input_port_info(circuit_lib.port_lib_name(input_port), input_pin, input_pin); + BasicPort input_port_info(circuit_lib.port_lib_name(input_port), + input_pin, input_pin); fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info); - - /* Increment the counter for port */ + + /* Increment the counter for port */ port_cnt++; } } @@ -334,12 +359,11 @@ void print_verilog_and_or_gate_body(std::fstream& fp, /************************************************ * Print Verilog body codes of an 2-input MUX gate ***********************************************/ -static -void print_verilog_mux2_gate_body(std::fstream& fp, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const std::vector& input_ports, - const std::vector& output_ports) { +static void print_verilog_mux2_gate_body( + std::fstream& fp, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const std::vector& input_ports, + const std::vector& output_ports) { /* Ensure a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); @@ -348,35 +372,35 @@ void print_verilog_mux2_gate_body(std::fstream& fp, /* Check on the port sequence and map */ /* MUX2 should only have 1 output port with size 1 */ if (1 != output_ports.size()) { - VTR_LOGF_ERROR(__FILE__, __LINE__, + VTR_LOGF_ERROR(__FILE__, __LINE__, "MUX2 circuit model '%s' must have only 1 output!\n", circuit_lib.model_name(circuit_model).c_str()); num_err++; - } - for (const auto& output_port : output_ports) { + } + for (const auto& output_port : output_ports) { /* Bypass port size of 1 */ if (1 == circuit_lib.port_size(output_port)) { continue; } - VTR_LOGF_ERROR(__FILE__, __LINE__, + VTR_LOGF_ERROR(__FILE__, __LINE__, "Output port size of a MUX2 circuit model '%s' must be 1!\n", circuit_lib.model_name(circuit_model).c_str()); num_err++; } /* MUX2 should only have 3 output port, each of which has a port size of 1 */ if (3 != input_ports.size()) { - VTR_LOGF_ERROR(__FILE__, __LINE__, + VTR_LOGF_ERROR(__FILE__, __LINE__, "MUX2 circuit model '%s' must have only 3 input!\n", circuit_lib.model_name(circuit_model).c_str()); num_err++; } - for (const auto& input_port : input_ports) { + for (const auto& input_port : input_ports) { /* Bypass port size of 1 */ if (1 == circuit_lib.port_size(input_port)) { continue; } - VTR_LOGF_ERROR(__FILE__, __LINE__, + VTR_LOGF_ERROR(__FILE__, __LINE__, "Input size MUX2 circuit model '%s' must be 1!\n", circuit_lib.model_name(circuit_model).c_str()); num_err++; @@ -388,7 +412,7 @@ void print_verilog_mux2_gate_body(std::fstream& fp, /* Now, we output the logic of MUX2 * IMPORTANT Restriction: * We always assum the first two inputs are data inputs - * the third input is the select port + * the third input is the select port */ fp << "\tassign "; BasicPort out_port_info(circuit_lib.port_lib_name(output_ports[0]), 0, 0); @@ -409,53 +433,61 @@ void print_verilog_mux2_gate_body(std::fstream& fp, /************************************************ * Print a Verilog module of a logic gate * which are standard cells - * Supported gate types: - * 1. N-input AND + * Supported gate types: + * 1. N-input AND * 2. N-input OR * 3. 2-input MUX ***********************************************/ -static -void print_verilog_gate_module(const ModuleManager& module_manager, - std::fstream& fp, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const e_verilog_default_net_type& default_net_type) { +static void print_verilog_gate_module( + const ModuleManager& module_manager, std::fstream& fp, + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const e_verilog_default_net_type& default_net_type) { /* Ensure a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); /* Find the input port, output port*/ - std::vector input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); - std::vector global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector global_ports = + circuit_lib.model_global_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); /* Make sure: - * There is only 1 output port, + * There is only 1 output port, * each size of which is 1 */ - VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) ); + VTR_ASSERT((1 == output_ports.size()) && + (1 == circuit_lib.port_size(output_ports[0]))); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = module_manager.find_module(circuit_lib.model_name(circuit_model)); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = + module_manager.find_module(circuit_lib.model_name(circuit_model)); VTR_ASSERT(true == module_manager.valid_module_id(module_id)); /* dump module definition + ports */ - print_verilog_module_declaration(fp, module_manager, module_id, default_net_type); + print_verilog_module_declaration(fp, module_manager, module_id, + default_net_type); /* Finish dumping ports */ /* Dump logics */ switch (circuit_lib.gate_type(circuit_model)) { - case CIRCUIT_MODEL_GATE_AND: - case CIRCUIT_MODEL_GATE_OR: - print_verilog_and_or_gate_body(fp, circuit_lib, circuit_model, input_ports, output_ports); - break; - case CIRCUIT_MODEL_GATE_MUX2: - print_verilog_mux2_gate_body(fp, circuit_lib, circuit_model, input_ports, output_ports); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid topology for circuit model '%s'!\n", - circuit_lib.model_name(circuit_model).c_str()); - exit(1); + case CIRCUIT_MODEL_GATE_AND: + case CIRCUIT_MODEL_GATE_OR: + print_verilog_and_or_gate_body(fp, circuit_lib, circuit_model, + input_ports, output_ports); + break; + case CIRCUIT_MODEL_GATE_MUX2: + print_verilog_mux2_gate_body(fp, circuit_lib, circuit_model, input_ports, + output_ports); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid topology for circuit model '%s'!\n", + circuit_lib.model_name(circuit_model).c_str()); + exit(1); } /* Print timing info */ @@ -469,11 +501,10 @@ void print_verilog_gate_module(const ModuleManager& module_manager, * Generate the Verilog netlist for a constant generator, * i.e., either VDD or GND ***********************************************/ -static -void print_verilog_constant_generator_module(const ModuleManager& module_manager, - std::fstream& fp, - const size_t& const_value, - const e_verilog_default_net_type& default_net_type) { +static void print_verilog_constant_generator_module( + const ModuleManager& module_manager, std::fstream& fp, + const size_t& const_value, + const e_verilog_default_net_type& default_net_type) { /* Find the module in module manager */ std::string module_name = generate_const_value_module_name(const_value); ModuleId const_val_module = module_manager.find_module(module_name); @@ -483,15 +514,19 @@ void print_verilog_constant_generator_module(const ModuleManager& module_manager VTR_ASSERT(true == valid_file_stream(fp)); /* dump module definition + ports */ - print_verilog_module_declaration(fp, module_manager, const_val_module, default_net_type); + print_verilog_module_declaration(fp, module_manager, const_val_module, + default_net_type); /* Finish dumping ports */ /* Find the only output*/ - for (const ModulePortId& module_port_id : module_manager.module_ports(const_val_module)) { - BasicPort module_port = module_manager.module_port(const_val_module, module_port_id); - print_verilog_wire_constant_values(fp, module_port, std::vector(1, const_value)); + for (const ModulePortId& module_port_id : + module_manager.module_ports(const_val_module)) { + BasicPort module_port = + module_manager.module_port(const_val_module, module_port_id); + print_verilog_wire_constant_values(fp, module_port, + std::vector(1, const_value)); } - + /* Put an end to the Verilog module */ print_verilog_module_end(fp, module_name); } @@ -501,12 +536,12 @@ void print_verilog_constant_generator_module(const ModuleManager& module_manager * include inverters, buffers, transmission-gates, * etc. ***********************************************/ -void print_verilog_submodule_essentials(const ModuleManager& module_manager, +void print_verilog_submodule_essentials(const ModuleManager& module_manager, NetlistManager& netlist_manager, const std::string& submodule_dir, const std::string& submodule_dir_name, const CircuitLibrary& circuit_lib, - const FabricVerilogOption& options) { + const FabricVerilogOption& options) { std::string verilog_fname(ESSENTIALS_VERILOG_FILE_NAME); std::string verilog_fpath = submodule_dir + verilog_fname; @@ -515,19 +550,21 @@ void print_verilog_submodule_essentials(const ModuleManager& module_manager, /* Create the file stream */ fp.open(verilog_fpath, std::fstream::out | std::fstream::trunc); /* Check if the file stream if valid or not */ - check_file_stream(verilog_fpath.c_str(), fp); + check_file_stream(verilog_fpath.c_str(), fp); /* Create file */ VTR_LOG("Generating Verilog netlist '%s' for essential gates...", - verilog_fpath.c_str()); + verilog_fpath.c_str()); print_verilog_file_header(fp, "Essential gates", options.time_stamp()); /* Print constant generators */ /* VDD */ - print_verilog_constant_generator_module(module_manager, fp, 0, options.default_net_type()); + print_verilog_constant_generator_module(module_manager, fp, 0, + options.default_net_type()); /* GND */ - print_verilog_constant_generator_module(module_manager, fp, 1, options.default_net_type()); + print_verilog_constant_generator_module(module_manager, fp, 1, + options.default_net_type()); for (const auto& circuit_model : circuit_lib.models()) { /* By pass user-defined modules */ @@ -535,15 +572,18 @@ void print_verilog_submodule_essentials(const ModuleManager& module_manager, continue; } if (CIRCUIT_MODEL_INVBUF == circuit_lib.model_type(circuit_model)) { - print_verilog_invbuf_module(module_manager, fp, circuit_lib, circuit_model, options.default_net_type()); + print_verilog_invbuf_module(module_manager, fp, circuit_lib, + circuit_model, options.default_net_type()); continue; } if (CIRCUIT_MODEL_PASSGATE == circuit_lib.model_type(circuit_model)) { - print_verilog_passgate_module(module_manager, fp, circuit_lib, circuit_model, options.default_net_type()); + print_verilog_passgate_module(module_manager, fp, circuit_lib, + circuit_model, options.default_net_type()); continue; } if (CIRCUIT_MODEL_GATE == circuit_lib.model_type(circuit_model)) { - print_verilog_gate_module(module_manager, fp, circuit_lib, circuit_model, options.default_net_type()); + print_verilog_gate_module(module_manager, fp, circuit_lib, circuit_model, + options.default_net_type()); continue; } } diff --git a/openfpga/src/fpga_verilog/verilog_essential_gates.h b/openfpga/src/fpga_verilog/verilog_essential_gates.h index 3c92bbb5e..6921c110d 100644 --- a/openfpga/src/fpga_verilog/verilog_essential_gates.h +++ b/openfpga/src/fpga_verilog/verilog_essential_gates.h @@ -5,11 +5,12 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "circuit_library.h" +#include "fabric_verilog_options.h" #include "module_manager.h" #include "netlist_manager.h" #include "verilog_port_types.h" -#include "fabric_verilog_options.h" /******************************************************************** * Function declaration @@ -18,7 +19,7 @@ /* begin namespace openfpga */ namespace openfpga { -void print_verilog_submodule_essentials(const ModuleManager& module_manager, +void print_verilog_submodule_essentials(const ModuleManager& module_manager, NetlistManager& netlist_manager, const std::string& submodule_dir, const std::string& submodule_dir_name, diff --git a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp index ac7bed10b..c72eb6786 100644 --- a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp @@ -1,11 +1,11 @@ /******************************************************************** - * This file includes functions that are used to generate a Verilog + * This file includes functions that are used to generate a Verilog * testbench for the top-level module (FPGA fabric), in purpose of - * running formal verification with random input vectors + * running formal verification with random input vectors *******************************************************************/ -#include -#include #include +#include +#include #include /* Headers from vtrutil library */ @@ -14,18 +14,16 @@ #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_port.h" -#include "openfpga_digest.h" -#include "openfpga_reserved_words.h" - -#include "openfpga_atom_netlist_utils.h" -#include "simulation_utils.h" #include "fabric_global_port_info_utils.h" - +#include "openfpga_atom_netlist_utils.h" +#include "openfpga_digest.h" +#include "openfpga_port.h" +#include "openfpga_reserved_words.h" +#include "simulation_utils.h" #include "verilog_constants.h" -#include "verilog_writer_utils.h" -#include "verilog_testbench_utils.h" #include "verilog_formal_random_top_testbench.h" +#include "verilog_testbench_utils.h" +#include "verilog_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -43,54 +41,54 @@ constexpr const char* ERROR_COUNTER = "nb_error"; constexpr const char* FORMAL_TB_SIM_START_PORT_NAME = "sim_start"; /******************************************************************** - * Print the module ports for the Verilog testbench - * using random vectors - * This function generates - * 1. the input ports to drive both input benchmark module and FPGA fabric module + * Print the module ports for the Verilog testbench + * using random vectors + * This function generates + * 1. the input ports to drive both input benchmark module and FPGA fabric + *module * 2. the output ports for input benchmark module * 3. the output ports for FPGA fabric module - * 4. the error checking ports + * 4. the error checking ports *******************************************************************/ -static -void print_verilog_top_random_testbench_ports(std::fstream& fp, - const ModuleManager& module_manager, - const std::string& circuit_name, - const std::vector& clock_port_names, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const VerilogTestbenchOption& options) { +static void print_verilog_top_random_testbench_ports( + std::fstream& fp, const ModuleManager& module_manager, + const std::string& circuit_name, + const std::vector& clock_port_names, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const VerilogTestbenchOption& options) { /* Validate the file stream */ valid_file_stream(fp); - print_verilog_default_net_type_declaration(fp, - options.default_net_type()); - - /* Print the declaration for the module */ - fp << "module " << circuit_name << FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX << ";" << std::endl; + print_verilog_default_net_type_declaration(fp, options.default_net_type()); - /* Create a clock port if the benchmark does not have one! - * The clock is used for counting and synchronizing input stimulus + /* Print the declaration for the module */ + fp << "module " << circuit_name << FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX << ";" + << std::endl; + + /* Create a clock port if the benchmark does not have one! + * The clock is used for counting and synchronizing input stimulus */ - std::vector clock_ports = generate_verilog_testbench_clock_port(clock_port_names, std::string(DEFAULT_CLOCK_NAME)); - print_verilog_comment(fp, std::string("----- Default clock port is added here since benchmark does not contain one -------")); + std::vector clock_ports = generate_verilog_testbench_clock_port( + clock_port_names, std::string(DEFAULT_CLOCK_NAME)); + print_verilog_comment( + fp, std::string("----- Default clock port is added here since benchmark " + "does not contain one -------")); for (const BasicPort& clock_port : clock_ports) { - fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, clock_port) << ";" << std::endl; + fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, clock_port) << ";" + << std::endl; } /* Add an empty line as splitter */ fp << std::endl; - print_verilog_testbench_shared_ports(fp, module_manager, FabricGlobalPortInfo(), PinConstraints(), - atom_ctx, netlist_annotation, - clock_port_names, - std::string(), - std::string(BENCHMARK_PORT_POSTFIX), - std::string(FPGA_PORT_POSTFIX), - std::string(CHECKFLAG_PORT_POSTFIX), - options.no_self_checking()); + print_verilog_testbench_shared_ports( + fp, module_manager, FabricGlobalPortInfo(), PinConstraints(), atom_ctx, + netlist_annotation, clock_port_names, std::string(), + std::string(BENCHMARK_PORT_POSTFIX), std::string(FPGA_PORT_POSTFIX), + std::string(CHECKFLAG_PORT_POSTFIX), options.no_self_checking()); - /* Instantiate an integer to count the number of error - * and determine if the simulation succeed or failed + /* Instantiate an integer to count the number of error + * and determine if the simulation succeed or failed */ if (!options.no_self_checking()) { print_verilog_comment(fp, std::string("----- Error counter -------")); @@ -103,33 +101,26 @@ void print_verilog_top_random_testbench_ports(std::fstream& fp, /******************************************************************** * Instanciate the input benchmark module *******************************************************************/ -static -void print_verilog_top_random_testbench_benchmark_instance(std::fstream& fp, - const std::string& reference_verilog_top_name, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const bool& explicit_port_mapping) { +static void print_verilog_top_random_testbench_benchmark_instance( + std::fstream& fp, const std::string& reference_verilog_top_name, + const AtomContext& atom_ctx, const VprNetlistAnnotation& netlist_annotation, + const PinConstraints& pin_constraints, const BusGroup& bus_group, + const bool& explicit_port_mapping) { /* Validate the file stream */ valid_file_stream(fp); /* Instanciate benchmark */ - print_verilog_comment(fp, std::string("----- Reference Benchmark Instanication -------")); + print_verilog_comment( + fp, std::string("----- Reference Benchmark Instanication -------")); - print_verilog_testbench_benchmark_instance(fp, reference_verilog_top_name, - std::string(BENCHMARK_INSTANCE_NAME), - std::string(), - std::string(), - std::string(), - std::string(BENCHMARK_PORT_POSTFIX), - std::vector(), - atom_ctx, netlist_annotation, - pin_constraints, - bus_group, - explicit_port_mapping); + print_verilog_testbench_benchmark_instance( + fp, reference_verilog_top_name, std::string(BENCHMARK_INSTANCE_NAME), + std::string(), std::string(), std::string(), + std::string(BENCHMARK_PORT_POSTFIX), std::vector(), atom_ctx, + netlist_annotation, pin_constraints, bus_group, explicit_port_mapping); - print_verilog_comment(fp, std::string("----- End reference Benchmark Instanication -------")); + print_verilog_comment( + fp, std::string("----- End reference Benchmark Instanication -------")); /* Add an empty line as splitter */ fp << std::endl; @@ -138,33 +129,29 @@ void print_verilog_top_random_testbench_benchmark_instance(std::fstream& fp, /******************************************************************** * Instanciate the FPGA fabric module *******************************************************************/ -static -void print_verilog_random_testbench_fpga_instance(std::fstream& fp, - const std::string& circuit_name, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const bool& explicit_port_mapping) { +static void print_verilog_random_testbench_fpga_instance( + std::fstream& fp, const std::string& circuit_name, + const AtomContext& atom_ctx, const VprNetlistAnnotation& netlist_annotation, + const PinConstraints& pin_constraints, const BusGroup& bus_group, + const bool& explicit_port_mapping) { /* Validate the file stream */ valid_file_stream(fp); - print_verilog_comment(fp, std::string("----- FPGA fabric instanciation -------")); + print_verilog_comment(fp, + std::string("----- FPGA fabric instanciation -------")); /* Always use explicit port mapping */ - print_verilog_testbench_benchmark_instance(fp, std::string(circuit_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX)), - std::string(FPGA_INSTANCE_NAME), - std::string(), - std::string(), - std::string(), - std::string(FPGA_PORT_POSTFIX), - std::vector(), - atom_ctx, netlist_annotation, - pin_constraints, - bus_group, - explicit_port_mapping); + print_verilog_testbench_benchmark_instance( + fp, + std::string(circuit_name + + std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX)), + std::string(FPGA_INSTANCE_NAME), std::string(), std::string(), + std::string(), std::string(FPGA_PORT_POSTFIX), std::vector(), + atom_ctx, netlist_annotation, pin_constraints, bus_group, + explicit_port_mapping); - print_verilog_comment(fp, std::string("----- End FPGA Fabric Instanication -------")); + print_verilog_comment( + fp, std::string("----- End FPGA Fabric Instanication -------")); /* Add an empty line as splitter */ fp << std::endl; @@ -173,19 +160,17 @@ void print_verilog_random_testbench_fpga_instance(std::fstream& fp, /******************************************************************** * Generate random stimulus for the reset port * This function is designed to drive the reset port of a benchmark module - * The reset signal will be + * The reset signal will be * - enabled in the 1st clock cycle * - disabled in the rest of clock cycles *******************************************************************/ -static -void print_verilog_random_testbench_reset_stimuli(std::fstream& fp, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const ModuleManager& module_manager, - const FabricGlobalPortInfo& global_ports, - const PinConstraints& pin_constraints, - const std::vector& clock_port_names, - const BasicPort& clock_port) { +static void print_verilog_random_testbench_reset_stimuli( + std::fstream& fp, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const ModuleManager& module_manager, const FabricGlobalPortInfo& global_ports, + const PinConstraints& pin_constraints, + const std::vector& clock_port_names, + const BasicPort& clock_port) { valid_file_stream(fp); print_verilog_comment(fp, "----- Begin reset signal generation -----"); @@ -196,28 +181,35 @@ void print_verilog_random_testbench_reset_stimuli(std::fstream& fp, continue; } - /* The block may be renamed as it contains special characters which violate Verilog syntax */ + /* The block may be renamed as it contains special characters which violate + * Verilog syntax */ std::string block_name = atom_ctx.nlist.block_name(atom_blk); if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); - } + } /* Bypass clock ports because their stimulus cannot be random */ - if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), block_name)) { + if (clock_port_names.end() != std::find(clock_port_names.begin(), + clock_port_names.end(), + block_name)) { continue; } - /* Bypass any constained net that are mapped to a global port of the FPGA fabric - * because their stimulus cannot be random + /* Bypass any constained net that are mapped to a global port of the FPGA + * fabric because their stimulus cannot be random */ - if (false == port_is_fabric_global_reset_port(global_ports, module_manager, pin_constraints.net_pin(block_name))) { + if (false == + port_is_fabric_global_reset_port(global_ports, module_manager, + pin_constraints.net_pin(block_name))) { continue; } /* Generete stimuli for this net which is how reset signal works */ BasicPort reset_port(block_name, 1); size_t initial_value = 1; - if (1 == global_ports.global_port_default_value(find_fabric_global_port(global_ports, module_manager, pin_constraints.net_pin(block_name)))) { + if (1 == + global_ports.global_port_default_value(find_fabric_global_port( + global_ports, module_manager, pin_constraints.net_pin(block_name)))) { initial_value = 0; } @@ -230,13 +222,17 @@ void print_verilog_random_testbench_reset_stimuli(std::fstream& fp, fp << ";" << std::endl; /* Flip the reset at the second negative edge of the clock port - * So the generic reset stimuli is applicable to both synchronous reset and asynchronous reset - * This is because the reset is activated in a complete clock cycle - * This gaurantees that even for synchronous reset, the reset can be sensed in the 1st rising/falling - * edge of the clock signal + * So the generic reset stimuli is applicable to both synchronous reset and + * asynchronous reset This is because the reset is activated in a complete + * clock cycle This gaurantees that even for synchronous reset, the reset + * can be sensed in the 1st rising/falling edge of the clock signal */ - fp << "\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << ");" << std::endl; - fp << "\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << ");" << std::endl; + fp << "\t@(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << ");" + << std::endl; + fp << "\t@(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << ");" + << std::endl; print_verilog_register_connection(fp, reset_port, reset_port, true); fp << "\tend" << std::endl; } @@ -248,40 +244,39 @@ void print_verilog_random_testbench_reset_stimuli(std::fstream& fp, /********************************************************************* * Top-level function in this file: - * Create a Verilog testbench using random input vectors + * Create a Verilog testbench using random input vectors * The testbench consists of two modules, i.e., Design Under Test (DUT) * 1. top-level module of FPGA fabric - * 2. top-level module of users' benchmark, + * 2. top-level module of users' benchmark, * i.e., the input benchmark of VPR flow * +----------+ * | FPGA | +------------+ * +----->| Fabric |------>| | * | | | | | * | +----------+ | | - * | | Output | - * random_input_vectors -----+ | Vector |---->Functional correct? - * | | Comparator | - * | +-----------+ | | - * | | Input | | | + * | | Output | + * random_input_vectors -----+ | Vector + *|---->Functional correct? | | Comparator | | + *+-----------+ | | | | Input | | | * +----->| Benchmark |----->| | * +-----------+ +------------+ * * Same input vectors are given to drive both DUTs. * The output vectors of the DUTs are compared to verify if they * have the same functionality. - * A flag will be raised to indicate the result + * A flag will be raised to indicate the result ********************************************************************/ -void print_verilog_random_top_testbench(const std::string& circuit_name, - const std::string& verilog_fname, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const ModuleManager& module_manager, - const FabricGlobalPortInfo& global_ports, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const SimulationSetting& simulation_parameters, - const VerilogTestbenchOption &options) { - std::string timer_message = std::string("Write configuration-skip testbench for FPGA top-level Verilog netlist implemented by '") + circuit_name.c_str() + std::string("'"); +void print_verilog_random_top_testbench( + const std::string& circuit_name, const std::string& verilog_fname, + const AtomContext& atom_ctx, const VprNetlistAnnotation& netlist_annotation, + const ModuleManager& module_manager, const FabricGlobalPortInfo& global_ports, + const PinConstraints& pin_constraints, const BusGroup& bus_group, + const SimulationSetting& simulation_parameters, + const VerilogTestbenchOption& options) { + std::string timer_message = std::string( + "Write configuration-skip testbench for FPGA " + "top-level Verilog netlist implemented by '") + + circuit_name.c_str() + std::string("'"); /* Start time count */ vtr::ScopedStartFinishTimer timer(timer_message); @@ -294,91 +289,81 @@ void print_verilog_random_top_testbench(const std::string& circuit_name, check_file_stream(verilog_fname.c_str(), fp); /* Generate a brief description on the Verilog file*/ - std::string title = std::string("FPGA Verilog Testbench for Formal Top-level netlist of Design: ") + circuit_name; - print_verilog_file_header(fp, title, options.time_stamp()); + std::string title = + std::string( + "FPGA Verilog Testbench for Formal Top-level netlist of Design: ") + + circuit_name; + print_verilog_file_header(fp, title, options.time_stamp()); /* Preparation: find all the clock ports */ - std::vector clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); + std::vector clock_port_names = + find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); /* Start of testbench */ - print_verilog_top_random_testbench_ports(fp, module_manager, circuit_name, clock_port_names, atom_ctx, netlist_annotation, options); + print_verilog_top_random_testbench_ports(fp, module_manager, circuit_name, + clock_port_names, atom_ctx, + netlist_annotation, options); /* Call defined top-level module */ - print_verilog_random_testbench_fpga_instance(fp, circuit_name, - atom_ctx, netlist_annotation, - pin_constraints, - bus_group, - options.explicit_port_mapping()); + print_verilog_random_testbench_fpga_instance( + fp, circuit_name, atom_ctx, netlist_annotation, pin_constraints, bus_group, + options.explicit_port_mapping()); /* Call defined benchmark */ if (!options.no_self_checking()) { - print_verilog_top_random_testbench_benchmark_instance(fp, circuit_name, - atom_ctx, netlist_annotation, - pin_constraints, - bus_group, - options.explicit_port_mapping()); + print_verilog_top_random_testbench_benchmark_instance( + fp, circuit_name, atom_ctx, netlist_annotation, pin_constraints, + bus_group, options.explicit_port_mapping()); } /* Find clock port to be used */ - std::vector clock_ports = generate_verilog_testbench_clock_port(clock_port_names, std::string(DEFAULT_CLOCK_NAME)); + std::vector clock_ports = generate_verilog_testbench_clock_port( + clock_port_names, std::string(DEFAULT_CLOCK_NAME)); /* Add stimuli for reset, set, clock and iopad signals */ - print_verilog_testbench_clock_stimuli(fp, - pin_constraints, - simulation_parameters, - clock_ports); - /* TODO: use the first clock now because we do not have information how the reset is - * correlated to clock ports. Once we have such information, the limitation should be removed! + print_verilog_testbench_clock_stimuli(fp, pin_constraints, + simulation_parameters, clock_ports); + /* TODO: use the first clock now because we do not have information how the + * reset is correlated to clock ports. Once we have such information, the + * limitation should be removed! */ - print_verilog_random_testbench_reset_stimuli(fp, - atom_ctx, - netlist_annotation, - module_manager, - global_ports, - pin_constraints, - clock_port_names, - clock_ports[0]); + print_verilog_random_testbench_reset_stimuli( + fp, atom_ctx, netlist_annotation, module_manager, global_ports, + pin_constraints, clock_port_names, clock_ports[0]); - print_verilog_testbench_random_stimuli(fp, atom_ctx, - netlist_annotation, - module_manager, - global_ports, - pin_constraints, - clock_port_names, - std::string(), - std::string(CHECKFLAG_PORT_POSTFIX), - clock_ports, - options.no_self_checking()); + print_verilog_testbench_random_stimuli( + fp, atom_ctx, netlist_annotation, module_manager, global_ports, + pin_constraints, clock_port_names, std::string(), + std::string(CHECKFLAG_PORT_POSTFIX), clock_ports, + options.no_self_checking()); if (!options.no_self_checking()) { - print_verilog_testbench_check(fp, - std::string(FORMAL_TB_SIM_START_PORT_NAME), - std::string(BENCHMARK_PORT_POSTFIX), - std::string(FPGA_PORT_POSTFIX), - std::string(CHECKFLAG_PORT_POSTFIX), - std::string(), - std::string(ERROR_COUNTER), - atom_ctx, - netlist_annotation, - clock_port_names, - std::string(DEFAULT_CLOCK_NAME)); + print_verilog_testbench_check( + fp, std::string(FORMAL_TB_SIM_START_PORT_NAME), + std::string(BENCHMARK_PORT_POSTFIX), std::string(FPGA_PORT_POSTFIX), + std::string(CHECKFLAG_PORT_POSTFIX), std::string(), + std::string(ERROR_COUNTER), atom_ctx, netlist_annotation, + clock_port_names, std::string(DEFAULT_CLOCK_NAME)); } - float simulation_time = find_operating_phase_simulation_time(simulation_parameters.num_clock_cycles(), - 1./simulation_parameters.default_operating_clock_frequency(), - VERILOG_SIM_TIMESCALE); + float simulation_time = find_operating_phase_simulation_time( + simulation_parameters.num_clock_cycles(), + 1. / simulation_parameters.default_operating_clock_frequency(), + VERILOG_SIM_TIMESCALE); /* Add Icarus requirement */ - print_verilog_timeout_and_vcd(fp, - std::string(circuit_name + std::string(FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX)), - std::string(circuit_name + std::string("_formal.vcd")), - std::string(FORMAL_TB_SIM_START_PORT_NAME), - std::string(ERROR_COUNTER), - simulation_time, - options.no_self_checking()); + print_verilog_timeout_and_vcd( + fp, + std::string(circuit_name + + std::string(FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX)), + std::string(circuit_name + std::string("_formal.vcd")), + std::string(FORMAL_TB_SIM_START_PORT_NAME), std::string(ERROR_COUNTER), + simulation_time, options.no_self_checking()); /* Testbench ends*/ - print_verilog_module_end(fp, std::string(circuit_name) + std::string(FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX)); + print_verilog_module_end(fp, + std::string(circuit_name) + + std::string(FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX)); /* Close the file stream */ fp.close(); diff --git a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.h b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.h index e3b092e1c..f6c5987db 100644 --- a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.h +++ b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.h @@ -5,13 +5,14 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "vpr_context.h" -#include "pin_constraints.h" -#include "module_manager.h" + +#include "bus_group.h" #include "fabric_global_port_info.h" +#include "module_manager.h" +#include "pin_constraints.h" #include "simulation_setting.h" #include "verilog_testbench_options.h" -#include "bus_group.h" +#include "vpr_context.h" /******************************************************************** * Function declaration @@ -20,16 +21,13 @@ /* begin namespace openfpga */ namespace openfpga { -void print_verilog_random_top_testbench(const std::string& circuit_name, - const std::string& verilog_fname, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const ModuleManager& module_manager, - const FabricGlobalPortInfo& global_ports, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const SimulationSetting& simulation_parameters, - const VerilogTestbenchOption &options); +void print_verilog_random_top_testbench( + const std::string& circuit_name, const std::string& verilog_fname, + const AtomContext& atom_ctx, const VprNetlistAnnotation& netlist_annotation, + const ModuleManager& module_manager, const FabricGlobalPortInfo& global_ports, + const PinConstraints& pin_constraints, const BusGroup& bus_group, + const SimulationSetting& simulation_parameters, + const VerilogTestbenchOption& options); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_grid.cpp b/openfpga/src/fpga_verilog/verilog_grid.cpp index 8141029d2..44036a727 100644 --- a/openfpga/src/fpga_verilog/verilog_grid.cpp +++ b/openfpga/src/fpga_verilog/verilog_grid.cpp @@ -1,14 +1,14 @@ /******************************************************************** * This file includes functions to print Verilog modules for a Grid - * (CLBs, I/Os, heterogeneous blocks etc.) + * (CLBs, I/Os, heterogeneous blocks etc.) *******************************************************************/ /* System header files */ -#include #include +#include /* Headers from vtrutil library */ -#include "vtr_geometry.h" #include "vtr_assert.h" +#include "vtr_geometry.h" #include "vtr_log.h" /* Headers from readarch library */ @@ -19,19 +19,17 @@ #include "openfpga_side_manager.h" /* Headers from vpr library */ -#include "vpr_utils.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" -#include "openfpga_physical_tile_utils.h" -#include "pb_type_utils.h" #include "circuit_library_utils.h" #include "module_manager_utils.h" - +#include "openfpga_naming.h" +#include "openfpga_physical_tile_utils.h" +#include "openfpga_reserved_words.h" +#include "pb_type_utils.h" #include "verilog_constants.h" -#include "verilog_writer_utils.h" -#include "verilog_module_writer.h" #include "verilog_grid.h" +#include "verilog_module_writer.h" +#include "verilog_writer_utils.h" +#include "vpr_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -39,7 +37,8 @@ namespace openfpga { /******************************************************************** * Print Verilog modules of a primitive node in the pb_graph_node graph * This generic function can support all the different types of primitive nodes - * i.e., Look-Up Tables (LUTs), Flip-flops (FFs) and hard logic blocks such as adders. + * i.e., Look-Up Tables (LUTs), Flip-flops (FFs) and hard logic blocks such as + *adders. * * The Verilog module will consist of two parts: * 1. Logic module of the primitive node @@ -52,36 +51,34 @@ namespace openfpga { * * Primitive block * +---------------------------------------+ - * | | + * | | * | +---------+ +---------+ | * in |----->| |--->| |<------|configuration lines * | | Logic |... | Memory | | * out|<-----| |--->| | | * | +---------+ +---------+ | - * | | + * | | * +---------------------------------------+ * - * Note that the primitive may be mapped to a standard cell, we force to use + * Note that the primitive may be mapped to a standard cell, we force to use * explict port mapping. This aims to avoid any port sequence issues!!! * *******************************************************************/ -static -void print_verilog_primitive_block(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const std::string& subckt_dir, - const std::string& subckt_dir_name, - t_pb_graph_node* primitive_pb_graph_node, - const FabricVerilogOption& options, - const bool& verbose) { - /* Ensure a valid pb_graph_node */ +static void print_verilog_primitive_block( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const std::string& subckt_dir, const std::string& subckt_dir_name, + t_pb_graph_node* primitive_pb_graph_node, const FabricVerilogOption& options, + const bool& verbose) { + /* Ensure a valid pb_graph_node */ if (nullptr == primitive_pb_graph_node) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid primitive_pb_graph_node!\n"); + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid primitive_pb_graph_node!\n"); exit(1); } /* Give a name to the Verilog netlist */ - std::string verilog_fname(generate_logical_tile_netlist_name(std::string(), primitive_pb_graph_node, std::string(VERILOG_NETLIST_FILE_POSTFIX))); + std::string verilog_fname(generate_logical_tile_netlist_name( + std::string(), primitive_pb_graph_node, + std::string(VERILOG_NETLIST_FILE_POSTFIX))); /* Create the file name for Verilog */ std::string verilog_fpath(subckt_dir + verilog_fname); @@ -95,12 +92,15 @@ void print_verilog_primitive_block(NetlistManager& netlist_manager, check_file_stream(verilog_fpath.c_str(), fp); - print_verilog_file_header(fp, - std::string("Verilog modules for primitive pb_type: " + std::string(primitive_pb_graph_node->pb_type->name)), - options.time_stamp()); + print_verilog_file_header( + fp, + std::string("Verilog modules for primitive pb_type: " + + std::string(primitive_pb_graph_node->pb_type->name)), + options.time_stamp()); /* Generate the module name for this primitive pb_graph_node*/ - std::string primitive_module_name = generate_physical_block_module_name(primitive_pb_graph_node->pb_type); + std::string primitive_module_name = + generate_physical_block_module_name(primitive_pb_graph_node->pb_type); /* Create a module of the primitive LUT and register it to module manager */ ModuleId primitive_module = module_manager.find_module(primitive_module_name); @@ -108,14 +108,11 @@ void print_verilog_primitive_block(NetlistManager& netlist_manager, VTR_ASSERT(true == module_manager.valid_module_id(primitive_module)); VTR_LOGV(verbose, - "Writing Verilog codes of logical tile primitive block '%s'...", + "Writing Verilog codes of logical tile primitive block '%s'...", module_manager.module_name(primitive_module).c_str()); - + /* Write the verilog module */ - write_verilog_module_to_file(fp, - module_manager, - primitive_module, - true, + write_verilog_module_to_file(fp, module_manager, primitive_module, true, options.default_net_type()); /* Close file handler */ @@ -129,81 +126,74 @@ void print_verilog_primitive_block(NetlistManager& netlist_manager, nlist_id = netlist_manager.add_netlist(verilog_fpath); } VTR_ASSERT(nlist_id); - netlist_manager.set_netlist_type(nlist_id, NetlistManager::LOGIC_BLOCK_NETLIST); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::LOGIC_BLOCK_NETLIST); VTR_LOGV(verbose, "Done\n"); } /******************************************************************** * Print Verilog modules of physical blocks inside a grid (CLB, I/O. etc.) - * This function will traverse the graph of complex logic block (t_pb_graph_node) - * in a recursive way, using a Depth First Search (DFS) algorithm. - * As such, primitive physical blocks (LUTs, FFs, etc.), leaf node of the pb_graph - * will be printed out first, while the top-level will be printed out in the last + * This function will traverse the graph of complex logic block + *(t_pb_graph_node) in a recursive way, using a Depth First Search (DFS) + *algorithm. As such, primitive physical blocks (LUTs, FFs, etc.), leaf node of + *the pb_graph will be printed out first, while the top-level will be printed + *out in the last * - * Note: this function will print a unique Verilog module for each type of - * t_pb_graph_node, i.e., t_pb_type, in the graph, in order to enable highly + * Note: this function will print a unique Verilog module for each type of + * t_pb_graph_node, i.e., t_pb_type, in the graph, in order to enable highly * hierarchical Verilog organization as well as simplify the Verilog file sizes. * * Note: DFS is the right way. Do NOT use BFS. * DFS can guarantee that all the sub-modules can be registered properly - * to its parent in module manager + * to its parent in module manager *******************************************************************/ -static -void rec_print_verilog_logical_tile(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const VprDeviceAnnotation& device_annotation, - const std::string& subckt_dir, - const std::string& subckt_dir_name, - t_pb_graph_node* physical_pb_graph_node, - const FabricVerilogOption& options, - const bool& verbose) { - +static void rec_print_verilog_logical_tile( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const VprDeviceAnnotation& device_annotation, const std::string& subckt_dir, + const std::string& subckt_dir_name, t_pb_graph_node* physical_pb_graph_node, + const FabricVerilogOption& options, const bool& verbose) { /* Check cur_pb_graph_node*/ if (nullptr == physical_pb_graph_node) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid physical_pb_graph_node\n"); + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid physical_pb_graph_node\n"); exit(1); } /* Get the pb_type definition related to the node */ - t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; + t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; /* Find the mode that physical implementation of a pb_type */ t_mode* physical_mode = device_annotation.physical_mode(physical_pb_type); - /* For non-leaf node in the pb_type graph: - * Recursively Depth-First Generate all the child pb_type at the level + /* For non-leaf node in the pb_type graph: + * Recursively Depth-First Generate all the child pb_type at the level */ - if (false == is_primitive_pb_type(physical_pb_type)) { + if (false == is_primitive_pb_type(physical_pb_type)) { for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) { /* Go recursive to visit the children */ - rec_print_verilog_logical_tile(netlist_manager, - module_manager, device_annotation, - subckt_dir, - subckt_dir_name, - &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][0]), - options, - verbose); + rec_print_verilog_logical_tile( + netlist_manager, module_manager, device_annotation, subckt_dir, + subckt_dir_name, + &(physical_pb_graph_node + ->child_pb_graph_nodes[physical_mode->index][ipb][0]), + options, verbose); } } /* For leaf node, a primitive Verilog module will be generated. */ - if (true == is_primitive_pb_type(physical_pb_type)) { - print_verilog_primitive_block(netlist_manager, - module_manager, - subckt_dir, - subckt_dir_name, - physical_pb_graph_node, - options, - verbose); + if (true == is_primitive_pb_type(physical_pb_type)) { + print_verilog_primitive_block(netlist_manager, module_manager, subckt_dir, + subckt_dir_name, physical_pb_graph_node, + options, verbose); /* Finish for primitive node, return */ return; } /* Give a name to the Verilog netlist */ /* Create the file name for Verilog */ - std::string verilog_fname(generate_logical_tile_netlist_name(std::string(), physical_pb_graph_node, std::string(VERILOG_NETLIST_FILE_POSTFIX))); + std::string verilog_fname(generate_logical_tile_netlist_name( + std::string(), physical_pb_graph_node, + std::string(VERILOG_NETLIST_FILE_POSTFIX))); std::string verilog_fpath(subckt_dir + verilog_fname); VTR_LOG("Writing Verilog netlist '%s' for pb_type '%s' ...", @@ -217,31 +207,36 @@ void rec_print_verilog_logical_tile(NetlistManager& netlist_manager, check_file_stream(verilog_fpath.c_str(), fp); print_verilog_file_header(fp, - std::string("Verilog modules for pb_type: " + std::string(physical_pb_type->name)), - options.time_stamp()); + std::string("Verilog modules for pb_type: " + + std::string(physical_pb_type->name)), + options.time_stamp()); /* Generate the name of the Verilog module for this pb_type */ - std::string pb_module_name = generate_physical_block_module_name(physical_pb_type); + std::string pb_module_name = + generate_physical_block_module_name(physical_pb_type); /* Register the Verilog module in module manager */ ModuleId pb_module = module_manager.find_module(pb_module_name); VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); - VTR_LOGV(verbose, - "Writing Verilog codes of pb_type '%s'...", + VTR_LOGV(verbose, "Writing Verilog codes of pb_type '%s'...", module_manager.module_name(pb_module).c_str()); /* Comment lines */ - print_verilog_comment(fp, std::string("----- BEGIN Physical programmable logic block Verilog module: " + std::string(physical_pb_type->name) + " -----")); + print_verilog_comment( + fp, std::string( + "----- BEGIN Physical programmable logic block Verilog module: " + + std::string(physical_pb_type->name) + " -----")); /* Write the verilog module */ - write_verilog_module_to_file(fp, - module_manager, - pb_module, + write_verilog_module_to_file(fp, module_manager, pb_module, options.explicit_port_mapping(), options.default_net_type()); - print_verilog_comment(fp, std::string("----- END Physical programmable logic block Verilog module: " + std::string(physical_pb_type->name) + " -----")); + print_verilog_comment( + fp, + std::string("----- END Physical programmable logic block Verilog module: " + + std::string(physical_pb_type->name) + " -----")); /* Close file handler */ fp.close(); @@ -254,71 +249,59 @@ void rec_print_verilog_logical_tile(NetlistManager& netlist_manager, nlist_id = netlist_manager.add_netlist(verilog_fpath); } VTR_ASSERT(nlist_id); - netlist_manager.set_netlist_type(nlist_id, NetlistManager::LOGIC_BLOCK_NETLIST); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::LOGIC_BLOCK_NETLIST); VTR_LOGV(verbose, "Done\n"); } /***************************************************************************** - * This function will create a Verilog file and print out a Verilog netlist - * for the logical tile (pb_graph/pb_type) + * This function will create a Verilog file and print out a Verilog netlist + * for the logical tile (pb_graph/pb_type) *****************************************************************************/ -static -void print_verilog_logical_tile_netlist(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const VprDeviceAnnotation& device_annotation, - const std::string& subckt_dir, - const std::string& subckt_dir_name, - t_pb_graph_node* pb_graph_head, - const FabricVerilogOption& options, - const bool& verbose) { - +static void print_verilog_logical_tile_netlist( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const VprDeviceAnnotation& device_annotation, const std::string& subckt_dir, + const std::string& subckt_dir_name, t_pb_graph_node* pb_graph_head, + const FabricVerilogOption& options, const bool& verbose) { VTR_LOG("Writing Verilog netlists for logic tile '%s' ...", pb_graph_head->pb_type->name); VTR_LOG("\n"); /* Print Verilog modules for all the pb_types/pb_graph_nodes - * use a Depth-First Search Algorithm to print the sub-modules + * use a Depth-First Search Algorithm to print the sub-modules * Note: DFS is the right way. Do NOT use BFS. * DFS can guarantee that all the sub-modules can be registered properly - * to its parent in module manager + * to its parent in module manager */ - /* Print Verilog modules starting from the top-level pb_type/pb_graph_node, and traverse the graph in a recursive way */ - rec_print_verilog_logical_tile(netlist_manager, - module_manager, - device_annotation, - subckt_dir, - subckt_dir_name, - pb_graph_head, - options, - verbose); + /* Print Verilog modules starting from the top-level pb_type/pb_graph_node, + * and traverse the graph in a recursive way */ + rec_print_verilog_logical_tile(netlist_manager, module_manager, + device_annotation, subckt_dir, subckt_dir_name, + pb_graph_head, options, verbose); VTR_LOG("Done\n"); VTR_LOG("\n"); } /***************************************************************************** - * This function will create a Verilog file and print out a Verilog netlist - * for a type of physical block + * This function will create a Verilog file and print out a Verilog netlist + * for a type of physical block * - * For IO blocks: + * For IO blocks: * The param 'border_side' is required, which is specify which side of fabric * the I/O block locates at. *****************************************************************************/ -static -void print_verilog_physical_tile_netlist(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const std::string& subckt_dir, - const std::string& subckt_dir_name, - t_physical_tile_type_ptr phy_block_type, - const e_side& border_side, - const FabricVerilogOption& options) { +static void print_verilog_physical_tile_netlist( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const std::string& subckt_dir, const std::string& subckt_dir_name, + t_physical_tile_type_ptr phy_block_type, const e_side& border_side, + const FabricVerilogOption& options) { /* Give a name to the Verilog netlist */ - std::string verilog_fname(generate_grid_block_netlist_name(std::string(GRID_MODULE_NAME_PREFIX) + std::string(phy_block_type->name), - is_io_type(phy_block_type), - border_side, - std::string(VERILOG_NETLIST_FILE_POSTFIX)) - ); + std::string verilog_fname(generate_grid_block_netlist_name( + std::string(GRID_MODULE_NAME_PREFIX) + std::string(phy_block_type->name), + is_io_type(phy_block_type), border_side, + std::string(VERILOG_NETLIST_FILE_POSTFIX))); /* Create the file name for Verilog */ std::string verilog_fpath(subckt_dir + verilog_fname); @@ -326,10 +309,10 @@ void print_verilog_physical_tile_netlist(NetlistManager& netlist_manager, /* Echo status */ if (true == is_io_type(phy_block_type)) { SideManager side_manager(border_side); - VTR_LOG("Writing Verilog Netlist '%s' for physical tile '%s' at %s side ...", - verilog_fpath.c_str(), phy_block_type->name, - side_manager.c_str()); - } else { + VTR_LOG( + "Writing Verilog Netlist '%s' for physical tile '%s' at %s side ...", + verilog_fpath.c_str(), phy_block_type->name, side_manager.c_str()); + } else { VTR_LOG("Writing Verilog Netlist '%s' for physical_tile '%s'...", verilog_fpath.c_str(), phy_block_type->name); } @@ -340,24 +323,31 @@ void print_verilog_physical_tile_netlist(NetlistManager& netlist_manager, check_file_stream(verilog_fpath.c_str(), fp); - print_verilog_file_header(fp, - std::string("Verilog modules for physical tile: " + std::string(phy_block_type->name) + "]"), - options.time_stamp()); + print_verilog_file_header( + fp, + std::string("Verilog modules for physical tile: " + + std::string(phy_block_type->name) + "]"), + options.time_stamp()); - /* Create a Verilog Module for the top-level physical block, and add to module manager */ - std::string grid_module_name = generate_grid_block_module_name(std::string(GRID_VERILOG_FILE_NAME_PREFIX), std::string(phy_block_type->name), is_io_type(phy_block_type), border_side); - ModuleId grid_module = module_manager.find_module(grid_module_name); + /* Create a Verilog Module for the top-level physical block, and add to module + * manager */ + std::string grid_module_name = generate_grid_block_module_name( + std::string(GRID_VERILOG_FILE_NAME_PREFIX), + std::string(phy_block_type->name), is_io_type(phy_block_type), border_side); + ModuleId grid_module = module_manager.find_module(grid_module_name); VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); /* Write the verilog module */ - print_verilog_comment(fp, std::string("----- BEGIN Grid Verilog module: " + module_manager.module_name(grid_module) + " -----")); - write_verilog_module_to_file(fp, - module_manager, - grid_module, + print_verilog_comment( + fp, std::string("----- BEGIN Grid Verilog module: " + + module_manager.module_name(grid_module) + " -----")); + write_verilog_module_to_file(fp, module_manager, grid_module, options.explicit_port_mapping(), options.default_net_type()); - print_verilog_comment(fp, std::string("----- END Grid Verilog module: " + module_manager.module_name(grid_module) + " -----")); + print_verilog_comment( + fp, std::string("----- END Grid Verilog module: " + + module_manager.module_name(grid_module) + " -----")); /* Add an empty line as a splitter */ fp << std::endl; @@ -373,7 +363,8 @@ void print_verilog_physical_tile_netlist(NetlistManager& netlist_manager, nlist_id = netlist_manager.add_netlist(verilog_fpath); } VTR_ASSERT(nlist_id); - netlist_manager.set_netlist_type(nlist_id, NetlistManager::LOGIC_BLOCK_NETLIST); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::LOGIC_BLOCK_NETLIST); VTR_LOG("Done\n"); } @@ -384,39 +375,33 @@ void print_verilog_physical_tile_netlist(NetlistManager& netlist_manager, * 2. Only one module for each CLB (FILL_TYPE) * 3. Only one module for each heterogeneous block ****************************************************************************/ -void print_verilog_grids(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const std::string& subckt_dir, - const std::string& subckt_dir_name, - const FabricVerilogOption& options, - const bool& verbose) { - /* Create a vector to contain all the Verilog netlist names that have been generated in this function */ +void print_verilog_grids( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, + const std::string& subckt_dir, const std::string& subckt_dir_name, + const FabricVerilogOption& options, const bool& verbose) { + /* Create a vector to contain all the Verilog netlist names that have been + * generated in this function */ std::vector netlist_names; - /* Enumerate the types of logical tiles, and build a module for each + /* Enumerate the types of logical tiles, and build a module for each * Write modules for all the pb_types/pb_graph_nodes - * use a Depth-First Search Algorithm to print the sub-modules + * use a Depth-First Search Algorithm to print the sub-modules * Note: DFS is the right way. Do NOT use BFS. * DFS can guarantee that all the sub-modules can be registered properly - * to its parent in module manager + * to its parent in module manager */ VTR_LOG("Writing logical tiles..."); VTR_LOGV(verbose, "\n"); - for (const t_logical_block_type& logical_tile : device_ctx.logical_block_types) { + for (const t_logical_block_type& logical_tile : + device_ctx.logical_block_types) { /* Bypass empty pb_graph */ if (nullptr == logical_tile.pb_graph_head) { continue; } - print_verilog_logical_tile_netlist(netlist_manager, - module_manager, - device_annotation, - subckt_dir, - subckt_dir_name, - logical_tile.pb_graph_head, - options, - verbose); + print_verilog_logical_tile_netlist( + netlist_manager, module_manager, device_annotation, subckt_dir, + subckt_dir_name, logical_tile.pb_graph_head, options, verbose); } VTR_LOG("Writing logical tiles..."); VTR_LOG("Done\n"); @@ -428,7 +413,8 @@ void print_verilog_grids(NetlistManager& netlist_manager, */ VTR_LOG("Building physical tiles..."); VTR_LOGV(verbose, "\n"); - for (const t_physical_tile_type& physical_tile : device_ctx.physical_tile_types) { + for (const t_physical_tile_type& physical_tile : + device_ctx.physical_tile_types) { /* Bypass empty type or nullptr */ if (true == is_empty_type(&physical_tile)) { continue; @@ -437,31 +423,24 @@ void print_verilog_grids(NetlistManager& netlist_manager, * We will search the grids and see where the I/O blocks are located: * - If a I/O block locates on border sides of FPGA fabric: * i.e., one or more from {TOP, RIGHT, BOTTOM, LEFT}, - * we will generate one module for each border side + * we will generate one module for each border side * - If a I/O block locates in the center of FPGA fabric: - * we will generate one module with NUM_SIDES (same treatment as regular grids) + * we will generate one module with NUM_SIDES (same treatment as regular + * grids) */ - std::set io_type_sides = find_physical_io_tile_located_sides(device_ctx.grid, - &physical_tile); + std::set io_type_sides = + find_physical_io_tile_located_sides(device_ctx.grid, &physical_tile); for (const e_side& io_type_side : io_type_sides) { - print_verilog_physical_tile_netlist(netlist_manager, - module_manager, - subckt_dir, - subckt_dir_name, - &physical_tile, - io_type_side, - options); - } + print_verilog_physical_tile_netlist( + netlist_manager, module_manager, subckt_dir, subckt_dir_name, + &physical_tile, io_type_side, options); + } continue; } else { /* For CLB and heterogenenous blocks */ - print_verilog_physical_tile_netlist(netlist_manager, - module_manager, - subckt_dir, - subckt_dir_name, - &physical_tile, - NUM_SIDES, - options); + print_verilog_physical_tile_netlist(netlist_manager, module_manager, + subckt_dir, subckt_dir_name, + &physical_tile, NUM_SIDES, options); } } VTR_LOG("Building physical tiles..."); diff --git a/openfpga/src/fpga_verilog/verilog_grid.h b/openfpga/src/fpga_verilog/verilog_grid.h index 573ee9d6f..565c4cc83 100644 --- a/openfpga/src/fpga_verilog/verilog_grid.h +++ b/openfpga/src/fpga_verilog/verilog_grid.h @@ -5,11 +5,12 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "vpr_context.h" + +#include "fabric_verilog_options.h" #include "module_manager.h" #include "netlist_manager.h" +#include "vpr_context.h" #include "vpr_device_annotation.h" -#include "fabric_verilog_options.h" /******************************************************************** * Function declaration @@ -18,15 +19,11 @@ /* begin namespace openfpga */ namespace openfpga { -void print_verilog_grids(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const std::string& subckt_dir, - const std::string& subckt_dir_name, - const FabricVerilogOption& options, - const bool& verbose); - +void print_verilog_grids( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, + const std::string& subckt_dir, const std::string& subckt_dir_name, + const FabricVerilogOption& options, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_lut.cpp b/openfpga/src/fpga_verilog/verilog_lut.cpp index 289cdc87b..856c4e7ef 100644 --- a/openfpga/src/fpga_verilog/verilog_lut.cpp +++ b/openfpga/src/fpga_verilog/verilog_lut.cpp @@ -1,32 +1,29 @@ /******************************************************************** * This file includes functions to generate Verilog submodules for LUTs ********************************************************************/ -#include #include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" #include "vtr_log.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - -#include "mux_graph.h" #include "module_manager.h" +#include "mux_graph.h" #include "mux_utils.h" - +#include "openfpga_digest.h" #include "openfpga_naming.h" - #include "verilog_constants.h" -#include "verilog_writer_utils.h" -#include "verilog_module_writer.h" #include "verilog_lut.h" +#include "verilog_module_writer.h" +#include "verilog_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { -/******************************************************************** - * Print Verilog modules for the Look-Up Tables (LUTs) +/******************************************************************** + * Print Verilog modules for the Look-Up Tables (LUTs) * in the circuit library ********************************************************************/ void print_verilog_submodule_luts(const ModuleManager& module_manager, @@ -43,27 +40,29 @@ void print_verilog_submodule_luts(const ModuleManager& module_manager, /* Create the file stream */ fp.open(verilog_fpath, std::fstream::out | std::fstream::trunc); /* Check if the file stream if valid or not */ - check_file_stream(verilog_fpath.c_str(), fp); + check_file_stream(verilog_fpath.c_str(), fp); /* Create file */ - VTR_LOG("Writing Verilog netlist for LUTs '%s'...", - verilog_fpath.c_str()); + VTR_LOG("Writing Verilog netlist for LUTs '%s'...", verilog_fpath.c_str()); - print_verilog_file_header(fp, "Look-Up Tables", options.time_stamp()); + print_verilog_file_header(fp, "Look-Up Tables", options.time_stamp()); /* Search for each LUT circuit model */ for (const auto& lut_model : circuit_lib.models()) { /* Bypass user-defined and non-LUT modules */ - if ( (!circuit_lib.model_verilog_netlist(lut_model).empty()) - || (CIRCUIT_MODEL_LUT != circuit_lib.model_type(lut_model)) ) { + if ((!circuit_lib.model_verilog_netlist(lut_model).empty()) || + (CIRCUIT_MODEL_LUT != circuit_lib.model_type(lut_model))) { continue; } /* Find the module id */ - ModuleId lut_module = module_manager.find_module(circuit_lib.model_name(lut_model)); + ModuleId lut_module = + module_manager.find_module(circuit_lib.model_name(lut_model)); VTR_ASSERT(true == module_manager.valid_module_id(lut_module)); - write_verilog_module_to_file(fp, module_manager, lut_module, - options.explicit_port_mapping() || circuit_lib.dump_explicit_port_map(lut_model), - options.default_net_type()); + write_verilog_module_to_file( + fp, module_manager, lut_module, + options.explicit_port_mapping() || + circuit_lib.dump_explicit_port_map(lut_model), + options.default_net_type()); } /* Close the file handler */ diff --git a/openfpga/src/fpga_verilog/verilog_lut.h b/openfpga/src/fpga_verilog/verilog_lut.h index a027877ad..2505f21e9 100644 --- a/openfpga/src/fpga_verilog/verilog_lut.h +++ b/openfpga/src/fpga_verilog/verilog_lut.h @@ -8,9 +8,9 @@ #include #include "circuit_library.h" +#include "fabric_verilog_options.h" #include "module_manager.h" #include "netlist_manager.h" -#include "fabric_verilog_options.h" /******************************************************************** * Function declaration diff --git a/openfpga/src/fpga_verilog/verilog_memory.cpp b/openfpga/src/fpga_verilog/verilog_memory.cpp index d5c497c2a..ef6903cd5 100644 --- a/openfpga/src/fpga_verilog/verilog_memory.cpp +++ b/openfpga/src/fpga_verilog/verilog_memory.cpp @@ -1,100 +1,98 @@ /********************************************************************* - * This file includes functions to generate Verilog submodules for + * This file includes functions to generate Verilog submodules for * the memories that are affiliated to multiplexers and other programmable * circuit models, such as IOPADs, LUTs, etc. ********************************************************************/ -#include #include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" #include "vtr_log.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - -#include "mux_graph.h" -#include "module_manager.h" #include "circuit_library_utils.h" +#include "module_manager.h" +#include "mux_graph.h" #include "mux_utils.h" - +#include "openfpga_digest.h" #include "openfpga_naming.h" - #include "verilog_constants.h" -#include "verilog_writer_utils.h" -#include "verilog_module_writer.h" #include "verilog_memory.h" +#include "verilog_module_writer.h" +#include "verilog_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { /********************************************************************* * Generate Verilog modules for the memories that are used - * by multiplexers + * by multiplexers * * +----------------+ * mem_in --->| Memory Module |---> mem_out * +----------------+ - * | | ... | | + * | | ... | | * v v v v SRAM ports of multiplexer * +---------------------+ * in--->| Multiplexer Module |---> out * +---------------------+ ********************************************************************/ -static -void print_verilog_mux_memory_module(const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - std::fstream& fp, - const CircuitModelId& mux_model, - const MuxGraph& mux_graph, - const FabricVerilogOption& options) { - /* Multiplexers built with different technology is in different organization */ +static void print_verilog_mux_memory_module( + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + std::fstream& fp, const CircuitModelId& mux_model, const MuxGraph& mux_graph, + const FabricVerilogOption& options) { + /* Multiplexers built with different technology is in different organization + */ switch (circuit_lib.design_tech_type(mux_model)) { - case CIRCUIT_MODEL_DESIGN_CMOS: { - /* Generate module name */ - std::string module_name = generate_mux_subckt_name(circuit_lib, mux_model, - find_mux_num_datapath_inputs(circuit_lib, mux_model, mux_graph.num_inputs()), - std::string(VERILOG_MEM_POSTFIX)); - ModuleId mem_module = module_manager.find_module(module_name); - VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); - /* Write the module content in Verilog format */ - write_verilog_module_to_file(fp, module_manager, mem_module, - options.explicit_port_mapping() || circuit_lib.dump_explicit_port_map(mux_model), - options.default_net_type()); + case CIRCUIT_MODEL_DESIGN_CMOS: { + /* Generate module name */ + std::string module_name = generate_mux_subckt_name( + circuit_lib, mux_model, + find_mux_num_datapath_inputs(circuit_lib, mux_model, + mux_graph.num_inputs()), + std::string(VERILOG_MEM_POSTFIX)); + ModuleId mem_module = module_manager.find_module(module_name); + VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); + /* Write the module content in Verilog format */ + write_verilog_module_to_file( + fp, module_manager, mem_module, + options.explicit_port_mapping() || + circuit_lib.dump_explicit_port_map(mux_model), + options.default_net_type()); - /* Add an empty line as a splitter */ - fp << std::endl; - break; - } - case CIRCUIT_MODEL_DESIGN_RRAM: - /* We do not need a memory submodule for RRAM MUX, - * RRAM are embedded in the datapath - * TODO: generate local encoders for RRAM-based multiplexers here!!! - */ - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid design technology of multiplexer '%s'\n", - circuit_lib.model_name(mux_model).c_str()); - exit(1); + /* Add an empty line as a splitter */ + fp << std::endl; + break; + } + case CIRCUIT_MODEL_DESIGN_RRAM: + /* We do not need a memory submodule for RRAM MUX, + * RRAM are embedded in the datapath + * TODO: generate local encoders for RRAM-based multiplexers here!!! + */ + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid design technology of multiplexer '%s'\n", + circuit_lib.model_name(mux_model).c_str()); + exit(1); } } - /********************************************************************* - * Generate Verilog modules for + * Generate Verilog modules for * the memories that are affiliated to multiplexers and other programmable * circuit models, such as IOPADs, LUTs, etc. * - * We keep the memory modules separated from the multiplexers and other + * We keep the memory modules separated from the multiplexers and other * programmable circuit models, for the sake of supporting * various configuration schemes. * By following such organiztion, the Verilog modules of the circuit models * implements the functionality (circuit logic) only, while the memory Verilog * modules implements the memory circuits as well as configuration protocols. * For example, the local decoders of multiplexers are implemented in the - * memory modules. - * Take another example, the memory circuit can implement the scan-chain or + * memory modules. + * Take another example, the memory circuit can implement the scan-chain or * memory-bank organization for the memories. ********************************************************************/ void print_verilog_submodule_memories(const ModuleManager& module_manager, @@ -114,35 +112,32 @@ void print_verilog_submodule_memories(const ModuleManager& module_manager, check_file_stream(verilog_fpath.c_str(), fp); - /* Print out debugging information for if the file is not opened/created properly */ + /* Print out debugging information for if the file is not opened/created + * properly */ VTR_LOG("Writing Verilog netlist for memories '%s' ...", - verilog_fpath.c_str()); + verilog_fpath.c_str()); - print_verilog_file_header(fp, "Memories used in FPGA", options.time_stamp()); + print_verilog_file_header(fp, "Memories used in FPGA", options.time_stamp()); /* Create the memory circuits for the multiplexer */ for (auto mux : mux_lib.muxes()) { const MuxGraph& mux_graph = mux_lib.mux_graph(mux); - CircuitModelId mux_model = mux_lib.mux_circuit_model(mux); - /* Bypass the non-MUX circuit models (i.e., LUTs). - * They should be handled in a different way + CircuitModelId mux_model = mux_lib.mux_circuit_model(mux); + /* Bypass the non-MUX circuit models (i.e., LUTs). + * They should be handled in a different way * Memory circuits of LUT includes both regular and mode-select ports */ if (CIRCUIT_MODEL_MUX != circuit_lib.model_type(mux_model)) { continue; } /* Create a Verilog module for the memories used by the multiplexer */ - print_verilog_mux_memory_module(module_manager, - circuit_lib, - fp, - mux_model, - mux_graph, - options); + print_verilog_mux_memory_module(module_manager, circuit_lib, fp, mux_model, + mux_graph, options); } /* Create the memory circuits for non-MUX circuit models. * In this case, the memory modules are designed to interface - * the mode-select ports + * the mode-select ports */ for (const auto& model : circuit_lib.models()) { /* Bypass MUXes, they have already been considered */ @@ -150,13 +145,14 @@ void print_verilog_submodule_memories(const ModuleManager& module_manager, continue; } /* Bypass those modules without any SRAM ports */ - std::vector sram_ports = circuit_lib.model_ports_by_type(model, CIRCUIT_MODEL_PORT_SRAM, true); + std::vector sram_ports = + circuit_lib.model_ports_by_type(model, CIRCUIT_MODEL_PORT_SRAM, true); if (0 == sram_ports.size()) { continue; } /* Find the name of memory module */ /* Get the total number of SRAMs */ - size_t num_mems = 0; + size_t num_mems = 0; for (const auto& port : sram_ports) { num_mems += circuit_lib.port_size(port); } @@ -166,23 +162,26 @@ void print_verilog_submodule_memories(const ModuleManager& module_manager, CircuitModelId sram_model = circuit_lib.port_tri_state_model(port); VTR_ASSERT(CircuitModelId::INVALID() != sram_model); /* Found in the vector of sram_models, do not update and go to the next */ - if (sram_models.end() != std::find(sram_models.begin(), sram_models.end(), sram_model)) { + if (sram_models.end() != + std::find(sram_models.begin(), sram_models.end(), sram_model)) { continue; } /* sram_model not found in the vector, update the sram_models */ sram_models.push_back(sram_model); } /* Should have only 1 SRAM model */ - VTR_ASSERT( 1 == sram_models.size() ); - + VTR_ASSERT(1 == sram_models.size()); + /* Create the module name for the memory block */ - std::string module_name = generate_memory_module_name(circuit_lib, model, sram_models[0], std::string(VERILOG_MEM_POSTFIX)); + std::string module_name = generate_memory_module_name( + circuit_lib, model, sram_models[0], std::string(VERILOG_MEM_POSTFIX)); ModuleId mem_module = module_manager.find_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); /* Write the module content in Verilog format */ - write_verilog_module_to_file(fp, module_manager, mem_module, - options.explicit_port_mapping() || circuit_lib.dump_explicit_port_map(model), + write_verilog_module_to_file(fp, module_manager, mem_module, + options.explicit_port_mapping() || + circuit_lib.dump_explicit_port_map(model), options.default_net_type()); /* Add an empty line as a splitter */ diff --git a/openfpga/src/fpga_verilog/verilog_memory.h b/openfpga/src/fpga_verilog/verilog_memory.h index 43b1e72e7..1c3702eff 100644 --- a/openfpga/src/fpga_verilog/verilog_memory.h +++ b/openfpga/src/fpga_verilog/verilog_memory.h @@ -7,11 +7,11 @@ #include #include "circuit_library.h" +#include "fabric_verilog_options.h" +#include "module_manager.h" #include "mux_graph.h" #include "mux_library.h" -#include "module_manager.h" #include "netlist_manager.h" -#include "fabric_verilog_options.h" /******************************************************************** * Function declaration diff --git a/openfpga/src/fpga_verilog/verilog_module_writer.cpp b/openfpga/src/fpga_verilog/verilog_module_writer.cpp index 18ae4af58..4a0ede484 100644 --- a/openfpga/src/fpga_verilog/verilog_module_writer.cpp +++ b/openfpga/src/fpga_verilog/verilog_module_writer.cpp @@ -3,7 +3,7 @@ * based on its definition in Module Manager * * Note that Verilog writer functions are just an outputter for the - * module definition. + * module definition. * You should NOT modify any content of the module manager * Please use const keyword to restrict this! *******************************************************************/ @@ -13,83 +13,90 @@ #include "vtr_assert.h" /* Headers from openfpgautil library */ -#include "openfpga_port.h" -#include "openfpga_digest.h" - -#include "openfpga_naming.h" - #include "module_manager_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" +#include "verilog_module_writer.h" #include "verilog_port_types.h" #include "verilog_writer_utils.h" -#include "verilog_module_writer.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * Generate the name of a local wire for a undriven port inside Verilog - * module + * Generate the name of a local wire for a undriven port inside Verilog + * module *******************************************************************/ -static -std::string generate_verilog_undriven_local_wire_name(const ModuleManager& module_manager, - const ModuleId& parent, - const ModuleId& child, - const size_t& instance_id, - const ModulePortId& child_port_id) { +static std::string generate_verilog_undriven_local_wire_name( + const ModuleManager& module_manager, const ModuleId& parent, + const ModuleId& child, const size_t& instance_id, + const ModulePortId& child_port_id) { std::string wire_name; if (!module_manager.instance_name(parent, child, instance_id).empty()) { wire_name = module_manager.instance_name(parent, child, instance_id); } else { - wire_name = module_manager.module_name(child) + std::string("_") + std::to_string(instance_id); + wire_name = module_manager.module_name(child) + std::string("_") + + std::to_string(instance_id); wire_name += std::string("_"); } - + wire_name += std::string("_undriven_"); wire_name += module_manager.module_port(child, child_port_id).get_name(); - + return wire_name; } - /******************************************************************** - * Name a net for a local wire for a verilog module - * 1. If this is a local wire, name it after the __ - * 2. If this is not a local wire, name it after the port name of parent module + * Name a net for a local wire for a verilog module + * 1. If this is a local wire, name it after the + *__ + * 2. If this is not a local wire, name it after the port name of parent module * - * In addition, it will assign the pin index as well + * In addition, it will assign the pin index as well * * Restriction: this function requires each net has single driver * which is definitely always true in circuits. *******************************************************************/ -static -BasicPort generate_verilog_port_for_module_net(const ModuleManager& module_manager, - const ModuleId& module_id, - const ModuleNetId& module_net) { +static BasicPort generate_verilog_port_for_module_net( + const ModuleManager& module_manager, const ModuleId& module_id, + const ModuleNetId& module_net) { BasicPort port_to_return; - /* Check all the sink modules of the net, - * if we have a source module is the current module, this is not local wire + /* Check all the sink modules of the net, + * if we have a source module is the current module, this is not local wire */ - for (ModuleNetSrcId src_id : module_manager.module_net_sources(module_id, module_net)) { - if (module_id == module_manager.net_source_modules(module_id, module_net)[src_id]) { + for (ModuleNetSrcId src_id : + module_manager.module_net_sources(module_id, module_net)) { + if (module_id == + module_manager.net_source_modules(module_id, module_net)[src_id]) { /* Here, this is not a local wire, return the port name of the src_port */ - ModulePortId net_src_port = module_manager.net_source_ports(module_id, module_net)[src_id]; - size_t src_pin_index = module_manager.net_source_pins(module_id, module_net)[src_id]; + ModulePortId net_src_port = + module_manager.net_source_ports(module_id, module_net)[src_id]; + size_t src_pin_index = + module_manager.net_source_pins(module_id, module_net)[src_id]; port_to_return.set(module_manager.module_port(module_id, net_src_port)); port_to_return.set_width(src_pin_index, src_pin_index); - port_to_return.set_origin_port_width(module_manager.module_port(module_id, net_src_port).get_width()); + port_to_return.set_origin_port_width( + module_manager.module_port(module_id, net_src_port).get_width()); return port_to_return; } } /* Check all the sink modules of the net */ - for (ModuleNetSinkId sink_id : module_manager.module_net_sinks(module_id, module_net)) { - if (module_id == module_manager.net_sink_modules(module_id, module_net)[sink_id]) { - /* Here, this is not a local wire, return the port name of the sink_port */ - ModulePortId net_sink_port = module_manager.net_sink_ports(module_id, module_net)[sink_id]; - size_t sink_pin_index = module_manager.net_sink_pins(module_id, module_net)[sink_id]; + for (ModuleNetSinkId sink_id : + module_manager.module_net_sinks(module_id, module_net)) { + if (module_id == + module_manager.net_sink_modules(module_id, module_net)[sink_id]) { + /* Here, this is not a local wire, return the port name of the sink_port + */ + ModulePortId net_sink_port = + module_manager.net_sink_ports(module_id, module_net)[sink_id]; + size_t sink_pin_index = + module_manager.net_sink_pins(module_id, module_net)[sink_id]; port_to_return.set(module_manager.module_port(module_id, net_sink_port)); port_to_return.set_width(sink_pin_index, sink_pin_index); - port_to_return.set_origin_port_width(module_manager.module_port(module_id, net_sink_port).get_width()); + port_to_return.set_origin_port_width( + module_manager.module_port(module_id, net_sink_port).get_width()); return port_to_return; } } @@ -97,30 +104,38 @@ BasicPort generate_verilog_port_for_module_net(const ModuleManager& module_manag /* Reach here, this is a local wire */ std::string net_name; - /* Each net must only one 1 source */ - VTR_ASSERT(1 == module_manager.net_source_modules(module_id, module_net).size()); + /* Each net must only one 1 source */ + VTR_ASSERT(1 == + module_manager.net_source_modules(module_id, module_net).size()); /* Get the source module */ - ModuleId net_src_module = module_manager.net_source_modules(module_id, module_net)[ModuleNetSrcId(0)]; + ModuleId net_src_module = + module_manager.net_source_modules(module_id, module_net)[ModuleNetSrcId(0)]; /* Get the instance id */ - size_t net_src_instance = module_manager.net_source_instances(module_id, module_net)[ModuleNetSrcId(0)]; + size_t net_src_instance = module_manager.net_source_instances( + module_id, module_net)[ModuleNetSrcId(0)]; /* Get the port id */ - ModulePortId net_src_port = module_manager.net_source_ports(module_id, module_net)[ModuleNetSrcId(0)]; + ModulePortId net_src_port = + module_manager.net_source_ports(module_id, module_net)[ModuleNetSrcId(0)]; /* Get the pin id */ - size_t net_src_pin = module_manager.net_source_pins(module_id, module_net)[ModuleNetSrcId(0)]; + size_t net_src_pin = + module_manager.net_source_pins(module_id, module_net)[ModuleNetSrcId(0)]; /* Load user-defined name if we have it */ if (false == module_manager.net_name(module_id, module_net).empty()) { net_name = module_manager.net_name(module_id, module_net); } else { - net_name = module_manager.module_name(net_src_module); - net_name += std::string("_") + std::to_string(net_src_instance) + std::string("_"); - net_name += module_manager.module_port(net_src_module, net_src_port).get_name(); + net_name = module_manager.module_name(net_src_module); + net_name += + std::string("_") + std::to_string(net_src_instance) + std::string("_"); + net_name += + module_manager.module_port(net_src_module, net_src_port).get_name(); } port_to_return.set_name(net_name); port_to_return.set_width(net_src_pin, net_src_pin); - port_to_return.set_origin_port_width(module_manager.module_port(net_src_module, net_src_port).get_width()); + port_to_return.set_origin_port_width( + module_manager.module_port(net_src_module, net_src_port).get_width()); return port_to_return; } @@ -130,66 +145,79 @@ BasicPort generate_verilog_port_for_module_net(const ModuleManager& module_manag * Verilog wire writter function will use the output of this function * to write up local wire declaration in Verilog format *******************************************************************/ -static -std::map> find_verilog_module_local_wires(const ModuleManager& module_manager, - const ModuleId& module_id) { +static std::map> +find_verilog_module_local_wires(const ModuleManager& module_manager, + const ModuleId& module_id) { std::map> local_wires; /* Local wires come from the child modules */ for (ModuleNetId module_net : module_manager.module_nets(module_id)) { /* Bypass dangling nets: - * Xifan Tang: I comment this part because it will shadow our problems in creating module graph - * Indeed this make a robust and a smooth Verilog module writing - * But I do want the module graph create is nice and clean !!! + * Xifan Tang: I comment this part because it will shadow our problems in + * creating module graph Indeed this make a robust and a smooth Verilog + * module writing But I do want the module graph create is nice and clean + * !!! */ /* - if ( (0 == module_manager.net_source_modules(module_id, module_net).size()) - && (0 == module_manager.net_source_modules(module_id, module_net).size()) ) { - continue; + if ( (0 == module_manager.net_source_modules(module_id, module_net).size()) + && (0 == module_manager.net_source_modules(module_id, module_net).size()) + ) { continue; } */ - /* We only care local wires */ - if (false == module_net_is_local_wire(module_manager, module_id, module_net)) { + /* We only care local wires */ + if (false == + module_net_is_local_wire(module_manager, module_id, module_net)) { continue; } /* Find the name for this local wire */ - BasicPort local_wire_candidate = generate_verilog_port_for_module_net(module_manager, module_id, module_net); + BasicPort local_wire_candidate = generate_verilog_port_for_module_net( + module_manager, module_id, module_net); /* Cache the net name, try to find it in the cache. - * If you can find one, it means this port may be mergeable, try to do merging. If merge fail, add to the local wire list - * If you cannot find one, it means that this port is not mergeable, add to the local wire list immediately. + * If you can find one, it means this port may be mergeable, try to do + * merging. If merge fail, add to the local wire list If you cannot find + * one, it means that this port is not mergeable, add to the local wire list + * immediately. */ - std::map>::iterator it = local_wires.find(local_wire_candidate.get_name()); + std::map>::iterator it = + local_wires.find(local_wire_candidate.get_name()); bool merged = false; if (it != local_wires.end()) { - /* Try to merge to one the port in the list that can absorb the current local wire */ - for (BasicPort& local_wire : local_wires[local_wire_candidate.get_name()]) { + /* Try to merge to one the port in the list that can absorb the current + * local wire */ + for (BasicPort& local_wire : + local_wires[local_wire_candidate.get_name()]) { /* check if the candidate can be combined to an existing local wire */ - if (true == two_verilog_ports_mergeable(local_wire, local_wire_candidate)) { + if (true == + two_verilog_ports_mergeable(local_wire, local_wire_candidate)) { /* Merge the ports */ - local_wire = merge_two_verilog_ports(local_wire, local_wire_candidate); + local_wire = + merge_two_verilog_ports(local_wire, local_wire_candidate); merged = true; break; - } + } } } /* If not merged/not found in the cache, push the port to the list */ if (false == merged) { - local_wires[local_wire_candidate.get_name()].push_back(local_wire_candidate); + local_wires[local_wire_candidate.get_name()].push_back( + local_wire_candidate); } } /* Local wires could also happen for undriven ports of child module */ for (const ModuleId& child : module_manager.child_modules(module_id)) { - for (size_t instance : module_manager.child_module_instances(module_id, child)) { - for (const ModulePortId& child_port_id : module_manager.module_ports(child)) { + for (size_t instance : + module_manager.child_module_instances(module_id, child)) { + for (const ModulePortId& child_port_id : + module_manager.module_ports(child)) { BasicPort child_port = module_manager.module_port(child, child_port_id); std::vector undriven_pins; for (size_t child_pin : child_port.pins()) { /* Find the net linked to the pin */ - ModuleNetId net = module_manager.module_instance_port_net(module_id, child, instance, - child_port_id, child_pin); + ModuleNetId net = module_manager.module_instance_port_net( + module_id, child, instance, child_port_id, child_pin); /* We only care undriven ports */ if (ModuleNetId::INVALID() == net) { undriven_pins.push_back(child_pin); @@ -198,12 +226,16 @@ std::map> find_verilog_module_local_wires(co if (true == undriven_pins.empty()) { continue; } - /* Reach here, we need a local wire, we will create a port only for the undriven pins of the port! */ + /* Reach here, we need a local wire, we will create a port only for the + * undriven pins of the port! */ BasicPort instance_port; - instance_port.set_name(generate_verilog_undriven_local_wire_name(module_manager, module_id, child, instance, child_port_id)); - /* We give the same port name as child module, this case happens to global ports */ - instance_port.set_width(*std::min_element(undriven_pins.begin(), undriven_pins.end()), - *std::max_element(undriven_pins.begin(), undriven_pins.end())); + instance_port.set_name(generate_verilog_undriven_local_wire_name( + module_manager, module_id, child, instance, child_port_id)); + /* We give the same port name as child module, this case happens to + * global ports */ + instance_port.set_width( + *std::min_element(undriven_pins.begin(), undriven_pins.end()), + *std::max_element(undriven_pins.begin(), undriven_pins.end())); local_wires[instance_port.get_name()].push_back(instance_port); } @@ -214,17 +246,15 @@ std::map> find_verilog_module_local_wires(co } /******************************************************************** - * Print a Verilog wire connection - * We search all the sinks of the net, - * if we find a module output, we try to find the next module output + * Print a Verilog wire connection + * We search all the sinks of the net, + * if we find a module output, we try to find the next module output * among the sinks of the net - * For each module output (except the first one), we print a wire connection + * For each module output (except the first one), we print a wire connection *******************************************************************/ -static -void print_verilog_module_output_short_connection(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const ModuleNetId& module_net) { +static void print_verilog_module_output_short_connection( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const ModuleNetId& module_net) { /* Ensure a valid file stream */ VTR_ASSERT(true == valid_file_stream(fp)); @@ -232,18 +262,25 @@ void print_verilog_module_output_short_connection(std::fstream& fp, BasicPort src_port; /* We have found a module input, now check all the sink modules of the net */ - for (ModuleNetSinkId net_sink : module_manager.module_net_sinks(module_id, module_net)) { - ModuleId sink_module = module_manager.net_sink_modules(module_id, module_net)[net_sink]; + for (ModuleNetSinkId net_sink : + module_manager.module_net_sinks(module_id, module_net)) { + ModuleId sink_module = + module_manager.net_sink_modules(module_id, module_net)[net_sink]; if (module_id != sink_module) { continue; } /* Find the sink port and pin information */ - ModulePortId sink_port_id = module_manager.net_sink_ports(module_id, module_net)[net_sink]; - size_t sink_pin = module_manager.net_sink_pins(module_id, module_net)[net_sink]; - BasicPort sink_port(module_manager.module_port(module_id, sink_port_id).get_name(), sink_pin, sink_pin); + ModulePortId sink_port_id = + module_manager.net_sink_ports(module_id, module_net)[net_sink]; + size_t sink_pin = + module_manager.net_sink_pins(module_id, module_net)[net_sink]; + BasicPort sink_port( + module_manager.module_port(module_id, sink_port_id).get_name(), sink_pin, + sink_pin); - /* For the first module output, this is the source port, we do nothing and go to the next */ + /* For the first module output, this is the source port, we do nothing and + * go to the next */ if (true == first_port) { src_port = sink_port; /* Flip the flag */ @@ -256,45 +293,59 @@ void print_verilog_module_output_short_connection(std::fstream& fp, } } - /******************************************************************** - * Print a Verilog wire connection - * We search all the sources of the net, - * if we find a module input, we try to find a module output + * Print a Verilog wire connection + * We search all the sources of the net, + * if we find a module input, we try to find a module output * among the sinks of the net - * If we find such a pair, we print a wire connection + * If we find such a pair, we print a wire connection *******************************************************************/ -static -void print_verilog_module_local_short_connection(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const ModuleNetId& module_net) { +static void print_verilog_module_local_short_connection( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const ModuleNetId& module_net) { /* Ensure a valid file stream */ VTR_ASSERT(true == valid_file_stream(fp)); - for (ModuleNetSrcId net_src : module_manager.module_net_sources(module_id, module_net)) { - ModuleId src_module = module_manager.net_source_modules(module_id, module_net)[net_src]; + for (ModuleNetSrcId net_src : + module_manager.module_net_sources(module_id, module_net)) { + ModuleId src_module = + module_manager.net_source_modules(module_id, module_net)[net_src]; if (module_id != src_module) { continue; } /* Find the source port and pin information */ - print_verilog_comment(fp, std::string("----- Net source id " + std::to_string(size_t(net_src)) + " -----")); - ModulePortId src_port_id = module_manager.net_source_ports(module_id, module_net)[net_src]; - size_t src_pin = module_manager.net_source_pins(module_id, module_net)[net_src]; - BasicPort src_port(module_manager.module_port(module_id, src_port_id).get_name(), src_pin, src_pin); + print_verilog_comment( + fp, std::string("----- Net source id " + std::to_string(size_t(net_src)) + + " -----")); + ModulePortId src_port_id = + module_manager.net_source_ports(module_id, module_net)[net_src]; + size_t src_pin = + module_manager.net_source_pins(module_id, module_net)[net_src]; + BasicPort src_port( + module_manager.module_port(module_id, src_port_id).get_name(), src_pin, + src_pin); - /* We have found a module input, now check all the sink modules of the net */ - for (ModuleNetSinkId net_sink : module_manager.module_net_sinks(module_id, module_net)) { - ModuleId sink_module = module_manager.net_sink_modules(module_id, module_net)[net_sink]; + /* We have found a module input, now check all the sink modules of the net + */ + for (ModuleNetSinkId net_sink : + module_manager.module_net_sinks(module_id, module_net)) { + ModuleId sink_module = + module_manager.net_sink_modules(module_id, module_net)[net_sink]; if (module_id != sink_module) { continue; } /* Find the sink port and pin information */ - print_verilog_comment(fp, std::string("----- Net sink id " + std::to_string(size_t(net_sink)) + " -----")); - ModulePortId sink_port_id = module_manager.net_sink_ports(module_id, module_net)[net_sink]; - size_t sink_pin = module_manager.net_sink_pins(module_id, module_net)[net_sink]; - BasicPort sink_port(module_manager.module_port(module_id, sink_port_id).get_name(), sink_pin, sink_pin); + print_verilog_comment( + fp, std::string("----- Net sink id " + + std::to_string(size_t(net_sink)) + " -----")); + ModulePortId sink_port_id = + module_manager.net_sink_ports(module_id, module_net)[net_sink]; + size_t sink_pin = + module_manager.net_sink_pins(module_id, module_net)[net_sink]; + BasicPort sink_port( + module_manager.module_port(module_id, sink_port_id).get_name(), + sink_pin, sink_pin); /* We need to print a wire connection here */ print_verilog_wire_connection(fp, sink_port, src_port, false); @@ -307,7 +358,7 @@ void print_verilog_module_local_short_connection(std::fstream& fp, * The short connection is defined as the direct connection * between an input port of the module and an output port of the module * This type of connection is not covered when printing Verilog instances - * Therefore, they are covered in this function + * Therefore, they are covered in this function * * module * +-----------------------------+ @@ -318,18 +369,21 @@ void print_verilog_module_local_short_connection(std::fstream& fp, * | | * +-----------------------------+ *******************************************************************/ -static -void print_verilog_module_local_short_connections(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id) { +static void print_verilog_module_local_short_connections( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id) { /* Local wires come from the child modules */ for (ModuleNetId module_net : module_manager.module_nets(module_id)) { - /* We only care the nets that indicate short connections */ - if (false == module_net_include_local_short_connection(module_manager, module_id, module_net)) { + /* We only care the nets that indicate short connections */ + if (false == module_net_include_local_short_connection( + module_manager, module_id, module_net)) { continue; } - print_verilog_comment(fp, std::string("----- Local connection due to Wire " + std::to_string(size_t(module_net)) + " -----")); - print_verilog_module_local_short_connection(fp, module_manager, module_id, module_net); + print_verilog_comment( + fp, std::string("----- Local connection due to Wire " + + std::to_string(size_t(module_net)) + " -----")); + print_verilog_module_local_short_connection(fp, module_manager, module_id, + module_net); } } @@ -338,7 +392,7 @@ void print_verilog_module_local_short_connections(std::fstream& fp, * The output short connection is defined as the direct connection * between two output ports of the module * This type of connection is not covered when printing Verilog instances - * Therefore, they are covered in this function + * Therefore, they are covered in this function * * module * +-----------------------------+ @@ -349,17 +403,18 @@ void print_verilog_module_local_short_connections(std::fstream& fp, * +--------------->|--->outputB * +-----------------------------+ *******************************************************************/ -static -void print_verilog_module_output_short_connections(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id) { +static void print_verilog_module_output_short_connections( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id) { /* Local wires come from the child modules */ for (ModuleNetId module_net : module_manager.module_nets(module_id)) { - /* We only care the nets that indicate short connections */ - if (false == module_net_include_output_short_connection(module_manager, module_id, module_net)) { + /* We only care the nets that indicate short connections */ + if (false == module_net_include_output_short_connection( + module_manager, module_id, module_net)) { continue; } - print_verilog_module_output_short_connection(fp, module_manager, module_id, module_net); + print_verilog_module_output_short_connection(fp, module_manager, module_id, + module_net); } } @@ -367,7 +422,7 @@ void print_verilog_module_output_short_connections(std::fstream& fp, * Write a Verilog instance to a file * This function will name the input and output connections to * the inputs/output or local wires available in the parent module - * + * * Parent_module * +-----------------------------+ * | | @@ -380,31 +435,36 @@ void print_verilog_module_output_short_connections(std::fstream& fp, * +-----------------------------+ * *******************************************************************/ -static -void write_verilog_instance_to_file(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const ModuleId& child_module, - const size_t& instance_id, - const bool& use_explicit_port_map) { +static void write_verilog_instance_to_file(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& parent_module, + const ModuleId& child_module, + const size_t& instance_id, + const bool& use_explicit_port_map) { /* Ensure a valid file stream */ VTR_ASSERT(true == valid_file_stream(fp)); /* Print module name */ fp << "\t" << module_manager.module_name(child_module) << " "; - /* Print instance name: + /* Print instance name: * if we have an instance name, use it; - * if not, we use a default name _ + * if not, we use a default name _ */ - if (true == module_manager.instance_name(parent_module, child_module, instance_id).empty()) { - fp << generate_instance_name(module_manager.module_name(child_module), instance_id) << " (" << std::endl; + if (true == + module_manager.instance_name(parent_module, child_module, instance_id) + .empty()) { + fp << generate_instance_name(module_manager.module_name(child_module), + instance_id) + << " (" << std::endl; } else { - fp << module_manager.instance_name(parent_module, child_module, instance_id) << " (" << std::endl; + fp << module_manager.instance_name(parent_module, child_module, instance_id) + << " (" << std::endl; } /* Print each port with/without explicit port map */ /* port type2type mapping */ - std::map port_type2type_map; + std::map + port_type2type_map; port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_CONKT; port_type2type_map[ModuleManager::MODULE_GPIN_PORT] = VERILOG_PORT_CONKT; port_type2type_map[ModuleManager::MODULE_GPOUT_PORT] = VERILOG_PORT_CONKT; @@ -417,11 +477,13 @@ void write_verilog_instance_to_file(std::fstream& fp, /* Port sequence: global, inout, input, output and clock ports, */ size_t port_cnt = 0; for (const auto& kv : port_type2type_map) { - for (const ModulePortId& child_port_id : module_manager.module_port_ids_by_type(child_module, kv.first)) { - BasicPort child_port = module_manager.module_port(child_module, child_port_id); + for (const ModulePortId& child_port_id : + module_manager.module_port_ids_by_type(child_module, kv.first)) { + BasicPort child_port = + module_manager.module_port(child_module, child_port_id); if (0 != port_cnt) { /* Do not dump a comma for the first port */ - fp << "," << std::endl; + fp << "," << std::endl; } /* Print port */ fp << "\t\t"; @@ -431,27 +493,34 @@ void write_verilog_instance_to_file(std::fstream& fp, } /* Create the port name and width to be used by the instance */ - std::vector instance_ports; - std::vector instance_ports_is_single_bit; + std::vector instance_ports; + std::vector instance_ports_is_single_bit; for (size_t child_pin : child_port.pins()) { /* Find the net linked to the pin */ - ModuleNetId net = module_manager.module_instance_port_net(parent_module, child_module, instance_id, - child_port_id, child_pin); + ModuleNetId net = module_manager.module_instance_port_net( + parent_module, child_module, instance_id, child_port_id, child_pin); BasicPort instance_port; if (ModuleNetId::INVALID() == net) { - /* We give the same port name as child module, this case happens to global ports */ - instance_port.set_name(generate_verilog_undriven_local_wire_name(module_manager, parent_module, child_module, instance_id, child_port_id)); - instance_port.set_width(child_pin, child_pin); - instance_port.set_origin_port_width(module_manager.module_port(child_module, child_port_id).get_width()); + /* We give the same port name as child module, this case happens to + * global ports */ + instance_port.set_name(generate_verilog_undriven_local_wire_name( + module_manager, parent_module, child_module, instance_id, + child_port_id)); + instance_port.set_width(child_pin, child_pin); + instance_port.set_origin_port_width( + module_manager.module_port(child_module, child_port_id) + .get_width()); } else { /* Find the name for this child port */ - instance_port = generate_verilog_port_for_module_net(module_manager, parent_module, net); + instance_port = generate_verilog_port_for_module_net( + module_manager, parent_module, net); } /* Create the port information for the net */ instance_ports.push_back(instance_port); - } + } /* Try to merge the ports */ - std::vector merged_ports = combine_verilog_ports(instance_ports); + std::vector merged_ports = + combine_verilog_ports(instance_ports); /* Print a verilog port by combining the instance ports */ fp << generate_verilog_ports(merged_ports); @@ -463,7 +532,7 @@ void write_verilog_instance_to_file(std::fstream& fp, port_cnt++; } } - + /* Print an end to the instance */ fp << ");" << std::endl; } @@ -471,36 +540,38 @@ void write_verilog_instance_to_file(std::fstream& fp, /******************************************************************** * Write a Verilog module to a file * This is a key function, maybe most frequently called in our Verilog writer - * Note that file stream must be valid + * Note that file stream must be valid *******************************************************************/ -void write_verilog_module_to_file(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const bool& use_explicit_port_map, - const e_verilog_default_net_type& default_net_type) { - +void write_verilog_module_to_file( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const bool& use_explicit_port_map, + const e_verilog_default_net_type& default_net_type) { VTR_ASSERT(true == valid_file_stream(fp)); /* Ensure we have a valid module_id */ - VTR_ASSERT(module_manager.valid_module_id(module_id)); + VTR_ASSERT(module_manager.valid_module_id(module_id)); /* Print module declaration */ - print_verilog_module_declaration(fp, module_manager, module_id, default_net_type); + print_verilog_module_declaration(fp, module_manager, module_id, + default_net_type); /* Print an empty line as splitter */ fp << std::endl; - + /* Print internal wires */ - std::map> local_wires = find_verilog_module_local_wires(module_manager, module_id); - for (std::pair> port_group : local_wires) { + std::map> local_wires = + find_verilog_module_local_wires(module_manager, module_id); + for (std::pair> port_group : + local_wires) { for (const BasicPort& local_wire : port_group.second) { - /* When default net type is wire, we can skip single-bit wires whose LSB is 0 */ - if ( (VERILOG_DEFAULT_NET_TYPE_WIRE == default_net_type) - && (1 == local_wire.get_width()) - && (0 == local_wire.get_lsb())) { + /* When default net type is wire, we can skip single-bit wires whose LSB + * is 0 */ + if ((VERILOG_DEFAULT_NET_TYPE_WIRE == default_net_type) && + (1 == local_wire.get_width()) && (0 == local_wire.get_lsb())) { continue; } - fp << generate_verilog_port(VERILOG_PORT_WIRE, local_wire) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_WIRE, local_wire) << ";" + << std::endl; } } @@ -508,29 +579,36 @@ void write_verilog_module_to_file(std::fstream& fp, fp << std::endl; /* Print local connection (from module inputs to output! */ - print_verilog_comment(fp, std::string("----- BEGIN Local short connections -----")); + print_verilog_comment( + fp, std::string("----- BEGIN Local short connections -----")); print_verilog_module_local_short_connections(fp, module_manager, module_id); - print_verilog_comment(fp, std::string("----- END Local short connections -----")); + print_verilog_comment(fp, + std::string("----- END Local short connections -----")); - print_verilog_comment(fp, std::string("----- BEGIN Local output short connections -----")); + print_verilog_comment( + fp, std::string("----- BEGIN Local output short connections -----")); print_verilog_module_output_short_connections(fp, module_manager, module_id); - - print_verilog_comment(fp, std::string("----- END Local output short connections -----")); + + print_verilog_comment( + fp, std::string("----- END Local output short connections -----")); /* Print an empty line as splitter */ fp << std::endl; /* Print instances */ for (ModuleId child_module : module_manager.child_modules(module_id)) { - for (size_t instance : module_manager.child_module_instances(module_id, child_module)) { + for (size_t instance : + module_manager.child_module_instances(module_id, child_module)) { /* Print an instance */ - write_verilog_instance_to_file(fp, module_manager, module_id, child_module, instance, use_explicit_port_map); + write_verilog_instance_to_file(fp, module_manager, module_id, + child_module, instance, + use_explicit_port_map); /* Print an empty line as splitter */ fp << std::endl; } } /* Print an end for the module */ - print_verilog_module_end(fp, module_manager.module_name(module_id)); + print_verilog_module_end(fp, module_manager.module_name(module_id)); /* Print an empty line as splitter */ fp << std::endl; diff --git a/openfpga/src/fpga_verilog/verilog_module_writer.h b/openfpga/src/fpga_verilog/verilog_module_writer.h index 322538b29..8e11637a7 100644 --- a/openfpga/src/fpga_verilog/verilog_module_writer.h +++ b/openfpga/src/fpga_verilog/verilog_module_writer.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "module_manager.h" #include "verilog_port_types.h" @@ -15,11 +16,10 @@ /* begin namespace openfpga */ namespace openfpga { -void write_verilog_module_to_file(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const bool& use_explicit_port_map, - const e_verilog_default_net_type& default_net_type); +void write_verilog_module_to_file( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const bool& use_explicit_port_map, + const e_verilog_default_net_type& default_net_type); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_mux.cpp b/openfpga/src/fpga_verilog/verilog_mux.cpp index e30db3fac..ea1d666ba 100644 --- a/openfpga/src/fpga_verilog/verilog_mux.cpp +++ b/openfpga/src/fpga_verilog/verilog_mux.cpp @@ -2,12 +2,12 @@ * This file includes functions to generate * Verilog submodules for multiplexers. * including both fundamental submodules - * such as a branch in a multiplexer + * such as a branch in a multiplexer * and the full multiplexer **********************************************/ -#include -#include #include +#include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" @@ -20,59 +20,64 @@ #include "circuit_types.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - -#include "mux_graph.h" -#include "module_manager.h" -#include "mux_utils.h" #include "circuit_library_utils.h" #include "decoder_library_utils.h" - +#include "module_manager.h" +#include "mux_graph.h" +#include "mux_utils.h" +#include "openfpga_digest.h" #include "openfpga_naming.h" - #include "verilog_constants.h" -#include "verilog_writer_utils.h" #include "verilog_module_writer.h" #include "verilog_mux.h" +#include "verilog_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { /********************************************************************* - * Generate behavior-level Verilog codes modeling an branch circuit - * for a multiplexer with the given size + * Generate behavior-level Verilog codes modeling an branch circuit + * for a multiplexer with the given size *********************************************************************/ -static -void generate_verilog_cmos_mux_branch_body_behavioral(std::fstream& fp, - const BasicPort& input_port, - const BasicPort& output_port, - const BasicPort& mem_port, - const MuxGraph& mux_graph, - const size_t& default_mem_val) { +static void generate_verilog_cmos_mux_branch_body_behavioral( + std::fstream& fp, const BasicPort& input_port, const BasicPort& output_port, + const BasicPort& mem_port, const MuxGraph& mux_graph, + const size_t& default_mem_val) { /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); /* Verilog Behavior description for a MUX */ - print_verilog_comment(fp, std::string("---- Behavioral-level description -----")); + print_verilog_comment(fp, + std::string("---- Behavioral-level description -----")); /* Add an internal register for the output */ BasicPort outreg_port("out_reg", mux_graph.num_outputs()); /* Print the port */ - fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, outreg_port) << ";" << std::endl; + fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, outreg_port) << ";" + << std::endl; /* Generate the case-switch table */ - fp << "\talways @(" << generate_verilog_port(VERILOG_PORT_CONKT, input_port) << ", " << generate_verilog_port(VERILOG_PORT_CONKT, mem_port) << ")" << std::endl; - fp << "\tcase (" << generate_verilog_port(VERILOG_PORT_CONKT, mem_port) << ")" << std::endl; + fp << "\talways @(" << generate_verilog_port(VERILOG_PORT_CONKT, input_port) + << ", " << generate_verilog_port(VERILOG_PORT_CONKT, mem_port) << ")" + << std::endl; + fp << "\tcase (" << generate_verilog_port(VERILOG_PORT_CONKT, mem_port) << ")" + << std::endl; /* Output the netlist following the connections in mux_graph */ /* Iterate over the inputs */ for (const auto& mux_input : mux_graph.inputs()) { - BasicPort cur_input_port(input_port.get_name(), size_t(mux_graph.input_id(mux_input)), size_t(mux_graph.input_id(mux_input))); + BasicPort cur_input_port(input_port.get_name(), + size_t(mux_graph.input_id(mux_input)), + size_t(mux_graph.input_id(mux_input))); /* Iterate over the outputs */ for (const auto& mux_output : mux_graph.outputs()) { - BasicPort cur_output_port(output_port.get_name(), size_t(mux_graph.output_id(mux_output)), size_t(mux_graph.output_id(mux_output))); - /* if there is a connection between the input and output, a tgate will be outputted */ - std::vector edges = mux_graph.find_edges(mux_input, mux_output); + BasicPort cur_output_port(output_port.get_name(), + size_t(mux_graph.output_id(mux_output)), + size_t(mux_graph.output_id(mux_output))); + /* if there is a connection between the input and output, a tgate will be + * outputted */ + std::vector edges = + mux_graph.find_edges(mux_input, mux_output); /* There should be only one edge or no edge*/ VTR_ASSERT((1 == edges.size()) || (0 == edges.size())); /* No need to output tgates if there are no edges between two nodes */ @@ -92,41 +97,44 @@ void generate_verilog_cmos_mux_branch_body_behavioral(std::fstream& fp, } else { case_code[size_t(mux_mem)] = '0'; } - fp << case_code << ": " << generate_verilog_port(VERILOG_PORT_CONKT, outreg_port) << " <= "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, cur_input_port) << ";" << std::endl; + fp << case_code << ": " + << generate_verilog_port(VERILOG_PORT_CONKT, outreg_port) << " <= "; + fp << generate_verilog_port(VERILOG_PORT_CONKT, cur_input_port) << ";" + << std::endl; } } /* Default case: outputs are at high-impedance state 'z' */ std::string default_case(mux_graph.num_outputs(), 'z'); - fp << "\t\tdefault: " << generate_verilog_port(VERILOG_PORT_CONKT, outreg_port) << " <= "; + fp << "\t\tdefault: " + << generate_verilog_port(VERILOG_PORT_CONKT, outreg_port) << " <= "; fp << mux_graph.num_outputs() << "'b" << default_case << ";" << std::endl; /* End the case */ fp << "\tendcase" << std::endl; /* Wire registers to output ports */ - fp << "\tassign " << generate_verilog_port(VERILOG_PORT_CONKT, output_port) << " = "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, outreg_port) << ";" << std::endl; + fp << "\tassign " << generate_verilog_port(VERILOG_PORT_CONKT, output_port) + << " = "; + fp << generate_verilog_port(VERILOG_PORT_CONKT, outreg_port) << ";" + << std::endl; } /********************************************************************* - * Generate Verilog codes modeling an branch circuit - * for a CMOS multiplexer with the given size + * Generate Verilog codes modeling an branch circuit + * for a CMOS multiplexer with the given size * Support structural and behavioral Verilog codes *********************************************************************/ -static -void print_verilog_cmos_mux_branch_module_behavioral(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - std::fstream& fp, - const CircuitModelId& mux_model, - const std::string& module_name, - const MuxGraph& mux_graph, - const e_verilog_default_net_type& default_net_type) { +static void print_verilog_cmos_mux_branch_module_behavioral( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + std::fstream& fp, const CircuitModelId& mux_model, + const std::string& module_name, const MuxGraph& mux_graph, + const e_verilog_default_net_type& default_net_type) { /* Get the tgate model */ CircuitModelId tgate_model = circuit_lib.pass_gate_logic_model(mux_model); - /* Skip output if the tgate model is a MUX2, it is handled by essential-gate generator */ + /* Skip output if the tgate model is a MUX2, it is handled by essential-gate + * generator */ if (CIRCUIT_MODEL_GATE == circuit_lib.model_type(tgate_model)) { VTR_ASSERT(CIRCUIT_MODEL_GATE_MUX2 == circuit_lib.gate_type(tgate_model)); return; @@ -136,11 +144,11 @@ void print_verilog_cmos_mux_branch_module_behavioral(ModuleManager& module_manag VTR_ASSERT(true == valid_file_stream(fp)); /* Generate the Verilog netlist according to the mux_graph */ - /* Find out the number of inputs */ + /* Find out the number of inputs */ size_t num_inputs = mux_graph.num_inputs(); - /* Find out the number of outputs */ + /* Find out the number of outputs */ size_t num_outputs = mux_graph.num_outputs(); - /* Find out the number of memory bits */ + /* Find out the number of memory bits */ size_t num_mems = mux_graph.num_memory_bits(); /* Check codes to ensure the port of Verilog netlists will match */ @@ -149,8 +157,9 @@ void print_verilog_cmos_mux_branch_module_behavioral(ModuleManager& module_manag /* MUX graph must have only 1 level*/ VTR_ASSERT(1 == mux_graph.num_levels()); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId mux_module = module_manager.find_module(module_name); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId mux_module = module_manager.find_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); /* Find module ports */ /* Find each input port */ @@ -161,32 +170,37 @@ void print_verilog_cmos_mux_branch_module_behavioral(ModuleManager& module_manag BasicPort mem_port("mem", num_mems); /* dump module definition + ports */ - print_verilog_module_declaration(fp, module_manager, mux_module, default_net_type); + print_verilog_module_declaration(fp, module_manager, mux_module, + default_net_type); /* Print the internal logic in behavioral Verilog codes */ /* Get the default value of SRAM ports */ - std::vector regular_sram_ports = find_circuit_regular_sram_ports(circuit_lib, mux_model); + std::vector regular_sram_ports = + find_circuit_regular_sram_ports(circuit_lib, mux_model); VTR_ASSERT(1 == regular_sram_ports.size()); - std::string mem_default_val = std::to_string(circuit_lib.port_default_value(regular_sram_ports[0])); + std::string mem_default_val = + std::to_string(circuit_lib.port_default_value(regular_sram_ports[0])); /* Mem string must be only 1-bit! */ VTR_ASSERT(1 == mem_default_val.length()); - generate_verilog_cmos_mux_branch_body_behavioral(fp, input_port, output_port, mem_port, mux_graph, mem_default_val[0]); + generate_verilog_cmos_mux_branch_body_behavioral( + fp, input_port, output_port, mem_port, mux_graph, mem_default_val[0]); /* Put an end to the Verilog module */ print_verilog_module_end(fp, module_name); } /********************************************************************* - * Dump a structural verilog for RRAM MUX basis module - * This is only called when structural verilog dumping option is enabled for this spice model - * IMPORTANT: the structural verilog can NOT be used for functionality verification!!! + * Dump a structural verilog for RRAM MUX basis module + * This is only called when structural verilog dumping option is enabled for + *this spice model IMPORTANT: the structural verilog can NOT be used for + *functionality verification!!! * TODO: This part is quite restricted to the way we implemented our RRAM FPGA * Should be reworked to be more generic !!! * - * By structural the schematic is splitted into two parts: left part and right part - * The left part includes BLB[0..N-1] and WL[0..N-1] signals as well as RRAMs - * The right part includes BLB[N] and WL[N] - * Corresponding Schematic is as follows: + * By structural the schematic is splitted into two parts: left part and right + *part The left part includes BLB[0..N-1] and WL[0..N-1] signals as well as + *RRAMs The right part includes BLB[N] and WL[N] Corresponding Schematic is as + *follows: * * LEFT PART | RIGHT PART * @@ -198,11 +212,11 @@ void print_verilog_cmos_mux_branch_module_behavioral(ModuleManager& module_manag * BLB[1] | * | | * \|/ | - * in[1] ---->RRAM[1]-----+ + * in[1] ---->RRAM[1]-----+ * |-----> out[0] - * ... + * ... * | - * in[N-1] ---->RRAM[N-1]---+ + * in[N-1] ---->RRAM[N-1]---+ * /|\ /|\ * | | * BLB[N-1] WL[N] @@ -215,37 +229,33 @@ void print_verilog_cmos_mux_branch_module_behavioral(ModuleManager& module_manag * The structure is done in the way we implement the physical layout of RRAM MUX * It is NOT the only road to the goal!!! *********************************************************************/ -static -void generate_verilog_rram_mux_branch_body_structural(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - std::fstream& fp, - const ModuleId& module_id, - const CircuitModelId& circuit_model, - const BasicPort& input_port, - const BasicPort& output_port, - const BasicPort& blb_port, - const BasicPort& wl_port, - const MuxGraph& mux_graph) { +static void generate_verilog_rram_mux_branch_body_structural( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + std::fstream& fp, const ModuleId& module_id, + const CircuitModelId& circuit_model, const BasicPort& input_port, + const BasicPort& output_port, const BasicPort& blb_port, + const BasicPort& wl_port, const MuxGraph& mux_graph) { std::string progTE_module_name("PROG_TE"); - std::string progBE_module_name("PROG_BE"); + std::string progBE_module_name("PROG_BE"); /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); /* Verilog Behavior description for a MUX */ - print_verilog_comment(fp, std::string("---- Structure-level description of RRAM MUX -----")); + print_verilog_comment( + fp, std::string("---- Structure-level description of RRAM MUX -----")); /* Print internal structure of 4T1R programming structures * Written in structural Verilog * The whole structure-level description is divided into two parts: * 1. Left part consists of N PROG_TE modules, each of which * includes a PMOS, a NMOS and a RRAM, which is actually the left - * part of a 4T1R programming structure + * part of a 4T1R programming structure * 2. Right part includes only a PROG_BE module, which consists * of a PMOS and a NMOS, which is actually the right part of a * 4T1R programming sturcture */ - /* Create a module for the progTE and register it in the module manager + /* Create a module for the progTE and register it in the module manager * Structure of progTE * * +----------+ @@ -255,7 +265,8 @@ void generate_verilog_rram_mux_branch_body_structural(ModuleManager& module_mana * +----------+ */ ModuleId progTE_module_id = module_manager.add_module(progTE_module_name); - /* If there is already such as module inside, we just ned to find the module id */ + /* If there is already such as module inside, we just ned to find the module + * id */ if (ModuleId::INVALID() == progTE_module_id) { progTE_module_id = module_manager.find_module(progTE_module_name); /* We should have a valid id! */ @@ -264,26 +275,36 @@ void generate_verilog_rram_mux_branch_body_structural(ModuleManager& module_mana /* Add ports to the module */ /* input port */ BasicPort progTE_in_port("A", 1); - module_manager.add_port(progTE_module_id, progTE_in_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(progTE_module_id, progTE_in_port, + ModuleManager::MODULE_INPUT_PORT); /* WL port */ BasicPort progTE_wl_port("WL", 1); - module_manager.add_port(progTE_module_id, progTE_wl_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(progTE_module_id, progTE_wl_port, + ModuleManager::MODULE_INPUT_PORT); /* BLB port */ BasicPort progTE_blb_port("BLB", 1); - module_manager.add_port(progTE_module_id, progTE_blb_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(progTE_module_id, progTE_blb_port, + ModuleManager::MODULE_INPUT_PORT); /* output port */ BasicPort progTE_out_port("Z", 1); - module_manager.add_port(progTE_module_id, progTE_out_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(progTE_module_id, progTE_out_port, + ModuleManager::MODULE_INPUT_PORT); /* LEFT part: Verilog code generation */ /* Iterate over the inputs */ for (const auto& mux_input : mux_graph.inputs()) { - BasicPort cur_input_port(input_port.get_name(), size_t(mux_graph.input_id(mux_input)), size_t(mux_graph.input_id(mux_input))); + BasicPort cur_input_port(input_port.get_name(), + size_t(mux_graph.input_id(mux_input)), + size_t(mux_graph.input_id(mux_input))); /* Iterate over the outputs */ for (const auto& mux_output : mux_graph.outputs()) { - BasicPort cur_output_port(output_port.get_name(), size_t(mux_graph.output_id(mux_output)), size_t(mux_graph.output_id(mux_output))); - /* if there is a connection between the input and output, a tgate will be outputted */ - std::vector edges = mux_graph.find_edges(mux_input, mux_output); + BasicPort cur_output_port(output_port.get_name(), + size_t(mux_graph.output_id(mux_output)), + size_t(mux_graph.output_id(mux_output))); + /* if there is a connection between the input and output, a tgate will be + * outputted */ + std::vector edges = + mux_graph.find_edges(mux_input, mux_output); /* There should be only one edge or no edge*/ VTR_ASSERT((1 == edges.size()) || (0 == edges.size())); /* No need to output tgates if there are no edges between two nodes */ @@ -298,23 +319,29 @@ void generate_verilog_rram_mux_branch_body_structural(ModuleManager& module_mana port2port_name_map[progTE_out_port.get_name()] = cur_output_port; /* Find the mem_id controlling the edge */ MuxMemId mux_mem = mux_graph.find_edge_mem(edges[0]); - BasicPort cur_blb_port(blb_port.get_name(), size_t(mux_mem), size_t(mux_mem)); - BasicPort cur_wl_port(wl_port.get_name(), size_t(mux_mem), size_t(mux_mem)); - /* RRAM configuration port: there should not be any inverted edge in RRAM MUX! */ - VTR_ASSERT( false == mux_graph.is_edge_use_inv_mem(edges[0]) ); + BasicPort cur_blb_port(blb_port.get_name(), size_t(mux_mem), + size_t(mux_mem)); + BasicPort cur_wl_port(wl_port.get_name(), size_t(mux_mem), + size_t(mux_mem)); + /* RRAM configuration port: there should not be any inverted edge in RRAM + * MUX! */ + VTR_ASSERT(false == mux_graph.is_edge_use_inv_mem(edges[0])); /* wire mem to mem of module, and wire mem_inv to mem_inv of module */ port2port_name_map[progTE_blb_port.get_name()] = cur_blb_port; port2port_name_map[progTE_wl_port.get_name()] = cur_wl_port; /* Output an instance of the module */ - print_verilog_module_instance(fp, module_manager, module_id, progTE_module_id, port2port_name_map, circuit_lib.dump_explicit_port_map(circuit_model)); + print_verilog_module_instance( + fp, module_manager, module_id, progTE_module_id, port2port_name_map, + circuit_lib.dump_explicit_port_map(circuit_model)); /* IMPORTANT: this update MUST be called after the instance outputting!!!! - * update the module manager with the relationship between the parent and child modules + * update the module manager with the relationship between the parent and + * child modules */ module_manager.add_child_module(module_id, progTE_module_id); } } - /* Create a module for the progBE and register it in the module manager + /* Create a module for the progBE and register it in the module manager * Structure of progBE * * +----------+ @@ -324,7 +351,8 @@ void generate_verilog_rram_mux_branch_body_structural(ModuleManager& module_mana * +----------+ */ ModuleId progBE_module_id = module_manager.add_module(progBE_module_name); - /* If there is already such as module inside, we just ned to find the module id */ + /* If there is already such as module inside, we just ned to find the module + * id */ if (ModuleId::INVALID() == progBE_module_id) { progBE_module_id = module_manager.find_module(progBE_module_name); /* We should have a valid id! */ @@ -333,39 +361,49 @@ void generate_verilog_rram_mux_branch_body_structural(ModuleManager& module_mana /* Add ports to the module */ /* inout port */ BasicPort progBE_inout_port("INOUT", 1); - module_manager.add_port(progBE_module_id, progBE_inout_port, ModuleManager::MODULE_INOUT_PORT); + module_manager.add_port(progBE_module_id, progBE_inout_port, + ModuleManager::MODULE_INOUT_PORT); /* WL port */ BasicPort progBE_wl_port("WL", 1); - module_manager.add_port(progBE_module_id, progBE_wl_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(progBE_module_id, progBE_wl_port, + ModuleManager::MODULE_INPUT_PORT); /* BLB port */ BasicPort progBE_blb_port("BLB", 1); - module_manager.add_port(progBE_module_id, progBE_blb_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(progBE_module_id, progBE_blb_port, + ModuleManager::MODULE_INPUT_PORT); /* RIGHT part: Verilog code generation */ /* Iterate over the outputs */ for (const auto& mux_output : mux_graph.outputs()) { - BasicPort cur_output_port(output_port.get_name(), size_t(mux_graph.output_id(mux_output)), size_t(mux_graph.output_id(mux_output))); + BasicPort cur_output_port(output_port.get_name(), + size_t(mux_graph.output_id(mux_output)), + size_t(mux_graph.output_id(mux_output))); /* Create a port-to-port name map */ std::map port2port_name_map; /* Wire the output port to the INOUT port */ port2port_name_map[progBE_inout_port.get_name()] = cur_output_port; /* Find the mem_id controlling the edge */ - BasicPort cur_blb_port(blb_port.get_name(), mux_graph.num_memory_bits(), mux_graph.num_memory_bits()); - BasicPort cur_wl_port(wl_port.get_name(), mux_graph.num_memory_bits(), mux_graph.num_memory_bits()); + BasicPort cur_blb_port(blb_port.get_name(), mux_graph.num_memory_bits(), + mux_graph.num_memory_bits()); + BasicPort cur_wl_port(wl_port.get_name(), mux_graph.num_memory_bits(), + mux_graph.num_memory_bits()); port2port_name_map[progBE_blb_port.get_name()] = cur_blb_port; port2port_name_map[progBE_wl_port.get_name()] = cur_wl_port; /* Output an instance of the module */ - print_verilog_module_instance(fp, module_manager, module_id, progBE_module_id, port2port_name_map, circuit_lib.dump_explicit_port_map(circuit_model)); + print_verilog_module_instance( + fp, module_manager, module_id, progBE_module_id, port2port_name_map, + circuit_lib.dump_explicit_port_map(circuit_model)); /* IMPORTANT: this update MUST be called after the instance outputting!!!! - * update the module manager with the relationship between the parent and child modules + * update the module manager with the relationship between the parent and + * child modules */ module_manager.add_child_module(module_id, progBE_module_id); } } /********************************************************************* - * Generate behavior-level Verilog codes modeling an branch circuit - * for a RRAM-based multiplexer with the given size + * Generate behavior-level Verilog codes modeling an branch circuit + * for a RRAM-based multiplexer with the given size * Corresponding Schematic is as follows: * * BLB[0] BLB[N] @@ -376,11 +414,11 @@ void generate_verilog_rram_mux_branch_body_structural(ModuleManager& module_mana * BLB[1] | * | | * \|/ | - * in[1] ---->RRAM[1]-----+ + * in[1] ---->RRAM[1]-----+ * |-----> out[0] - * ... + * ... * | - * in[N-1] ---->RRAM[N-1]---+ + * in[N-1] ---->RRAM[N-1]---+ * /|\ /|\ * | | * BLB[N-1] WL[N] @@ -391,42 +429,43 @@ void generate_verilog_rram_mux_branch_body_structural(ModuleManager& module_mana * 3. Operation: disable all BLBs and WLs * * TODO: Elaborate the codes to output the circuit logic - * following the mux_graph! + * following the mux_graph! *********************************************************************/ -static -void generate_verilog_rram_mux_branch_body_behavioral(std::fstream& fp, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const BasicPort& input_port, - const BasicPort& output_port, - const BasicPort& blb_port, - const BasicPort& wl_port, - const MuxGraph& mux_graph) { +static void generate_verilog_rram_mux_branch_body_behavioral( + std::fstream& fp, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, const BasicPort& input_port, + const BasicPort& output_port, const BasicPort& blb_port, + const BasicPort& wl_port, const MuxGraph& mux_graph) { /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); /* Verilog Behavior description for a MUX */ - print_verilog_comment(fp, std::string("---- Behavioral-level description of RRAM MUX -----")); + print_verilog_comment( + fp, std::string("---- Behavioral-level description of RRAM MUX -----")); /* Add an internal register for the output */ BasicPort outreg_port("out_reg", mux_graph.num_inputs()); /* Print the port */ - fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, outreg_port) << ";" << std::endl; + fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, outreg_port) << ";" + << std::endl; /* Print the internal logics */ - fp << "\t" << "always @("; - fp << generate_verilog_port(VERILOG_PORT_CONKT, blb_port); + fp << "\t" + << "always @("; + fp << generate_verilog_port(VERILOG_PORT_CONKT, blb_port); fp << ", "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, wl_port); + fp << generate_verilog_port(VERILOG_PORT_CONKT, wl_port); fp << ")"; fp << " begin" << std::endl; - /* Only when the last bit of wl is enabled, - * the propagating path can be changed + /* Only when the last bit of wl is enabled, + * the propagating path can be changed * (RRAM value can be changed) */ - fp << "\t\t" << "if ("; - BasicPort set_enable_port(wl_port.get_name(), wl_port.get_width() - 1, wl_port.get_width() - 1); - fp << generate_verilog_port(VERILOG_PORT_CONKT, set_enable_port); + fp << "\t\t" + << "if ("; + BasicPort set_enable_port(wl_port.get_name(), wl_port.get_width() - 1, + wl_port.get_width() - 1); + fp << generate_verilog_port(VERILOG_PORT_CONKT, set_enable_port); /* We need two config-enable ports: prog_EN and prog_ENb */ bool find_prog_EN = false; bool find_prog_ENb = false; @@ -435,32 +474,37 @@ void generate_verilog_rram_mux_branch_body_behavioral(std::fstream& fp, if (false == circuit_lib.port_is_config_enable(port)) { continue; } - /* Reach here, the port should be is_config_enable */ + /* Reach here, the port should be is_config_enable */ /* Create a port object */ - fp << " && "; - BasicPort prog_en_port(circuit_lib.port_prefix(port), circuit_lib.port_size(port)); - if ( 0 == circuit_lib.port_default_value(port)) { + fp << " && "; + BasicPort prog_en_port(circuit_lib.port_prefix(port), + circuit_lib.port_size(port)); + if (0 == circuit_lib.port_default_value(port)) { /* Default value = 0 means that this is a prog_EN port */ - fp << generate_verilog_port(VERILOG_PORT_CONKT, prog_en_port); + fp << generate_verilog_port(VERILOG_PORT_CONKT, prog_en_port); find_prog_EN = true; } else { - VTR_ASSERT ( 1 == circuit_lib.port_default_value(port)); - /* Default value = 1 means that this is a prog_ENb port, add inversion in the if condition */ - fp << "(~" << generate_verilog_port(VERILOG_PORT_CONKT, prog_en_port) << ")"; + VTR_ASSERT(1 == circuit_lib.port_default_value(port)); + /* Default value = 1 means that this is a prog_ENb port, add inversion in + * the if condition */ + fp << "(~" << generate_verilog_port(VERILOG_PORT_CONKT, prog_en_port) + << ")"; find_prog_ENb = true; } } /* Check if we find any config_enable signals */ if (false == find_prog_EN) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Unable to find a config_enable signal with default value 0 for a RRAM MUX '%s'!\n", - circuit_lib.model_name(circuit_model).c_str()); + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Unable to find a config_enable signal with default value 0 " + "for a RRAM MUX '%s'!\n", + circuit_lib.model_name(circuit_model).c_str()); exit(1); } if (false == find_prog_ENb) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Unable to find a config_enable signal with default value 1 for a RRAM MUX '%s'!\n", - circuit_lib.model_name(circuit_model).c_str()); + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Unable to find a config_enable signal with default value 1 " + "for a RRAM MUX '%s'!\n", + circuit_lib.model_name(circuit_model).c_str()); exit(1); } @@ -469,66 +513,76 @@ void generate_verilog_rram_mux_branch_body_behavioral(std::fstream& fp, for (const auto& mux_input : mux_graph.inputs()) { /* First if clause need tabs */ - if ( 0 == size_t(mux_graph.input_id(mux_input)) ) { + if (0 == size_t(mux_graph.input_id(mux_input))) { fp << "\t\t\t"; } fp << "if (1 == "; /* Create a temp port of a BLB bit */ - BasicPort cur_blb_port(blb_port.get_name(), size_t(mux_graph.input_id(mux_input)), size_t(mux_graph.input_id(mux_input))); - fp << generate_verilog_port(VERILOG_PORT_CONKT, cur_blb_port); + BasicPort cur_blb_port(blb_port.get_name(), + size_t(mux_graph.input_id(mux_input)), + size_t(mux_graph.input_id(mux_input))); + fp << generate_verilog_port(VERILOG_PORT_CONKT, cur_blb_port); fp << ") begin" << std::endl; - fp << "\t\t\t\t" << "assign "; - fp << outreg_port.get_name(); + fp << "\t\t\t\t" + << "assign "; + fp << outreg_port.get_name(); fp << " = " << size_t(mux_graph.input_id(mux_input)) << ";" << std::endl; - fp << "\t\t\t" << "end else "; + fp << "\t\t\t" + << "end else "; } fp << "begin" << std::endl; - fp << "\t\t\t\t" << "assign "; - fp << outreg_port.get_name(); + fp << "\t\t\t\t" + << "assign "; + fp << outreg_port.get_name(); fp << " = 0;" << std::endl; - fp << "\t\t\t" << "end" << std::endl; - fp << "\t\t" << "end" << std::endl; - fp << "\t" << "end" << std::endl; - - fp << "\t" << "assign "; + fp << "\t\t\t" + << "end" << std::endl; + fp << "\t\t" + << "end" << std::endl; + fp << "\t" + << "end" << std::endl; + + fp << "\t" + << "assign "; fp << generate_verilog_port(VERILOG_PORT_CONKT, output_port); - fp << " = "; + fp << " = "; fp << input_port.get_name() << "["; - fp << outreg_port.get_name(); + fp << outreg_port.get_name(); fp << "];" << std::endl; } /********************************************************************* - * Generate Verilog codes modeling an branch circuit - * for a RRAM-based multiplexer with the given size + * Generate Verilog codes modeling an branch circuit + * for a RRAM-based multiplexer with the given size * Support structural and behavioral Verilog codes *********************************************************************/ -static -void generate_verilog_rram_mux_branch_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - std::fstream& fp, - const CircuitModelId& circuit_model, - const std::string& module_name, - const MuxGraph& mux_graph, - const e_verilog_default_net_type& default_net_type, - const bool& use_structural_verilog) { +static void generate_verilog_rram_mux_branch_module( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + std::fstream& fp, const CircuitModelId& circuit_model, + const std::string& module_name, const MuxGraph& mux_graph, + const e_verilog_default_net_type& default_net_type, + const bool& use_structural_verilog) { /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); /* Get the input ports from the mux */ - std::vector mux_input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector mux_input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); /* Get the output ports from the mux */ - std::vector mux_output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector mux_output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); /* Get the BL and WL ports from the mux */ - std::vector mux_blb_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_BLB, true); - std::vector mux_wl_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_WL, true); + std::vector mux_blb_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_BLB, true); + std::vector mux_wl_ports = + circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_WL, true); /* Generate the Verilog netlist according to the mux_graph */ - /* Find out the number of inputs */ + /* Find out the number of inputs */ size_t num_inputs = mux_graph.num_inputs(); - /* Find out the number of outputs */ + /* Find out the number of outputs */ size_t num_outputs = mux_graph.num_outputs(); - /* Find out the number of memory bits */ + /* Find out the number of memory bits */ size_t num_mems = mux_graph.num_memory_bits(); /* Check codes to ensure the port of Verilog netlists will match */ @@ -542,18 +596,20 @@ void generate_verilog_rram_mux_branch_module(ModuleManager& module_manager, VTR_ASSERT(1 == mux_blb_ports.size()); VTR_ASSERT(1 == mux_wl_ports.size()); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = module_manager.find_module(module_name); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = module_manager.find_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(module_id)); /* Find each input port */ BasicPort input_port(circuit_lib.port_prefix(mux_input_ports[0]), num_inputs); /* Find each output port */ - BasicPort output_port(circuit_lib.port_prefix(mux_output_ports[0]), num_outputs); + BasicPort output_port(circuit_lib.port_prefix(mux_output_ports[0]), + num_outputs); - /* Find RRAM programming ports, - * RRAM MUXes require one more pair of BLB and WL + /* Find RRAM programming ports, + * RRAM MUXes require one more pair of BLB and WL * to configure the memories. See schematic for details */ BasicPort blb_port(circuit_lib.port_prefix(mux_blb_ports[0]), num_mems + 1); @@ -561,13 +617,19 @@ void generate_verilog_rram_mux_branch_module(ModuleManager& module_manager, BasicPort wl_port(circuit_lib.port_prefix(mux_wl_ports[0]), num_mems + 1); /* dump module definition + ports */ - print_verilog_module_declaration(fp, module_manager, module_id, default_net_type); + print_verilog_module_declaration(fp, module_manager, module_id, + default_net_type); - /* Print the internal logic in either structural or behavioral Verilog codes */ + /* Print the internal logic in either structural or behavioral Verilog codes + */ if (true == use_structural_verilog) { - generate_verilog_rram_mux_branch_body_structural(module_manager, circuit_lib, fp, module_id, circuit_model, input_port, output_port, blb_port, wl_port, mux_graph); + generate_verilog_rram_mux_branch_body_structural( + module_manager, circuit_lib, fp, module_id, circuit_model, input_port, + output_port, blb_port, wl_port, mux_graph); } else { - generate_verilog_rram_mux_branch_body_behavioral(fp, circuit_lib, circuit_model, input_port, output_port, blb_port, wl_port, mux_graph); + generate_verilog_rram_mux_branch_body_behavioral( + fp, circuit_lib, circuit_model, input_port, output_port, blb_port, + wl_port, mux_graph); } /* Put an end to the Verilog module */ @@ -575,72 +637,67 @@ void generate_verilog_rram_mux_branch_module(ModuleManager& module_manager, } /*********************************************** - * Generate Verilog codes modeling an branch circuit - * for a multiplexer with the given size + * Generate Verilog codes modeling an branch circuit + * for a multiplexer with the given size **********************************************/ -static -void generate_verilog_mux_branch_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - std::fstream& fp, - const CircuitModelId& mux_model, - const MuxGraph& mux_graph, - const bool& use_explicit_port_map, - const e_verilog_default_net_type& default_net_type, - std::map& branch_mux_module_is_outputted) { - std::string module_name = generate_mux_branch_subckt_name(circuit_lib, mux_model, mux_graph.num_inputs(), mux_graph.num_memory_bits(), VERILOG_MUX_BASIS_POSTFIX); +static void generate_verilog_mux_branch_module( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + std::fstream& fp, const CircuitModelId& mux_model, const MuxGraph& mux_graph, + const bool& use_explicit_port_map, + const e_verilog_default_net_type& default_net_type, + std::map& branch_mux_module_is_outputted) { + std::string module_name = generate_mux_branch_subckt_name( + circuit_lib, mux_model, mux_graph.num_inputs(), mux_graph.num_memory_bits(), + VERILOG_MUX_BASIS_POSTFIX); /* Skip outputting if the module has already been outputted */ auto result = branch_mux_module_is_outputted.find(module_name); - if ((result != branch_mux_module_is_outputted.end()) - && (true == result->second)) { + if ((result != branch_mux_module_is_outputted.end()) && + (true == result->second)) { return; } - /* Multiplexers built with different technology is in different organization */ + /* Multiplexers built with different technology is in different organization + */ switch (circuit_lib.design_tech_type(mux_model)) { - case CIRCUIT_MODEL_DESIGN_CMOS: - /* Skip module writing if the branch subckt is a standard cell! */ - if (true == circuit_lib.valid_model_id(circuit_lib.model(module_name))) { - /* This model must be a MUX2 gate */ - VTR_ASSERT(CIRCUIT_MODEL_GATE == circuit_lib.model_type(circuit_lib.model(module_name))); - VTR_ASSERT(CIRCUIT_MODEL_GATE_MUX2 == circuit_lib.gate_type(circuit_lib.model(module_name))); + case CIRCUIT_MODEL_DESIGN_CMOS: + /* Skip module writing if the branch subckt is a standard cell! */ + if (true == circuit_lib.valid_model_id(circuit_lib.model(module_name))) { + /* This model must be a MUX2 gate */ + VTR_ASSERT(CIRCUIT_MODEL_GATE == + circuit_lib.model_type(circuit_lib.model(module_name))); + VTR_ASSERT(CIRCUIT_MODEL_GATE_MUX2 == + circuit_lib.gate_type(circuit_lib.model(module_name))); + break; + } + if (true == circuit_lib.dump_structural_verilog(mux_model)) { + /* Structural verilog can be easily generated by module writer */ + ModuleId mux_module = module_manager.find_module(module_name); + VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); + write_verilog_module_to_file( + fp, module_manager, mux_module, + use_explicit_port_map || + circuit_lib.dump_explicit_port_map(mux_model), + default_net_type); + /* Add an empty line as a splitter */ + fp << std::endl; + } else { + /* Behavioral verilog requires customized generation */ + print_verilog_cmos_mux_branch_module_behavioral( + module_manager, circuit_lib, fp, mux_model, module_name, mux_graph, + default_net_type); + } break; - } - if (true == circuit_lib.dump_structural_verilog(mux_model)) { - /* Structural verilog can be easily generated by module writer */ - ModuleId mux_module = module_manager.find_module(module_name); - VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); - write_verilog_module_to_file(fp, module_manager, mux_module, - use_explicit_port_map || circuit_lib.dump_explicit_port_map(mux_model), - default_net_type); - /* Add an empty line as a splitter */ - fp << std::endl; - } else { - /* Behavioral verilog requires customized generation */ - print_verilog_cmos_mux_branch_module_behavioral(module_manager, - circuit_lib, - fp, - mux_model, - module_name, - mux_graph, - default_net_type); - } - break; - case CIRCUIT_MODEL_DESIGN_RRAM: - generate_verilog_rram_mux_branch_module(module_manager, - circuit_lib, - fp, - mux_model, - module_name, - mux_graph, - default_net_type, - circuit_lib.dump_structural_verilog(mux_model)); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid design technology of multiplexer '%s'\n", - circuit_lib.model_name(mux_model).c_str()); - exit(1); + case CIRCUIT_MODEL_DESIGN_RRAM: + generate_verilog_rram_mux_branch_module( + module_manager, circuit_lib, fp, mux_model, module_name, mux_graph, + default_net_type, circuit_lib.dump_structural_verilog(mux_model)); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid design technology of multiplexer '%s'\n", + circuit_lib.model_name(mux_model).c_str()); + exit(1); } /* Record that this branch module has been outputted */ @@ -648,227 +705,289 @@ void generate_verilog_mux_branch_module(ModuleManager& module_manager, } /******************************************************************** - * Generate the input bufferes for a multiplexer or LUT in Verilog codes + * Generate the input bufferes for a multiplexer or LUT in Verilog codes * 1. If input are required to be buffered (specified by users), * buffers will be added to all the datapath inputs. * 2. If input are required to NOT be buffered (specified by users), - * all the datapath inputs will be short wired to MUX inputs. + * all the datapath inputs will be short wired to MUX inputs. * * For those Multiplexers or LUTs require a constant input: * the last input of multiplexer will be wired to a constant voltage level *******************************************************************/ -static -void generate_verilog_cmos_mux_module_input_buffers(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - std::fstream& fp, - const ModuleId& module_id, - const CircuitModelId& circuit_model, - const MuxGraph& mux_graph) { +static void generate_verilog_cmos_mux_module_input_buffers( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + std::fstream& fp, const ModuleId& module_id, + const CircuitModelId& circuit_model, const MuxGraph& mux_graph) { /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); /* Get the input ports from the mux */ - std::vector mux_input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector mux_input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); /* We should have only 1 input port! */ VTR_ASSERT(1 == mux_input_ports.size()); /* Get the input port from MUX module */ - ModulePortId module_input_port_id = module_manager.find_module_port(module_id, circuit_lib.port_prefix(mux_input_ports[0])); + ModulePortId module_input_port_id = module_manager.find_module_port( + module_id, circuit_lib.port_prefix(mux_input_ports[0])); VTR_ASSERT(ModulePortId::INVALID() != module_input_port_id); /* Get the port from module */ - BasicPort module_input_port = module_manager.module_port(module_id, module_input_port_id); + BasicPort module_input_port = + module_manager.module_port(module_id, module_input_port_id); /* Iterate over all the inputs in the MUX graph */ for (const auto& input_node : mux_graph.inputs()) { /* Fetch fundamental information from MUX graph w.r.t. the input node */ MuxInputId input_index = mux_graph.input_id(input_node); - VTR_ASSERT(MuxInputId::INVALID() != input_index); - + VTR_ASSERT(MuxInputId::INVALID() != input_index); + size_t input_node_level = mux_graph.node_level(input_node); - size_t input_node_index_at_level = mux_graph.node_index_at_level(input_node); + size_t input_node_index_at_level = + mux_graph.node_index_at_level(input_node); - /* Create the port information of the MUX input, which is the input of buffer instance */ - BasicPort instance_input_port(module_input_port.get_name(), size_t(input_index), size_t(input_index)); + /* Create the port information of the MUX input, which is the input of + * buffer instance */ + BasicPort instance_input_port(module_input_port.get_name(), + size_t(input_index), size_t(input_index)); - /* Create the port information of the MUX graph input, which is the output of buffer instance */ - BasicPort instance_output_port(generate_mux_node_name(input_node_level, false), input_node_index_at_level, input_node_index_at_level); + /* Create the port information of the MUX graph input, which is the output + * of buffer instance */ + BasicPort instance_output_port( + generate_mux_node_name(input_node_level, false), + input_node_index_at_level, input_node_index_at_level); /* For last input: - * Add a constant value to the last input, if this MUX needs a constant input + * Add a constant value to the last input, if this MUX needs a constant + * input */ - if ( (MuxInputId(mux_graph.num_inputs() - 1) == mux_graph.input_id(input_node)) - && (true == circuit_lib.mux_add_const_input(circuit_model)) ) { + if ((MuxInputId(mux_graph.num_inputs() - 1) == + mux_graph.input_id(input_node)) && + (true == circuit_lib.mux_add_const_input(circuit_model))) { /* Get the constant input value */ size_t const_value = circuit_lib.mux_const_input_value(circuit_model); - VTR_ASSERT( (0 == const_value) || (1 == const_value) ); + VTR_ASSERT((0 == const_value) || (1 == const_value)); /* For the output of the buffer instance: - * Get the last inputs from the MUX graph and generate the node name in MUX module. + * Get the last inputs from the MUX graph and generate the node name in + * MUX module. */ - print_verilog_comment(fp, std::string("---- BEGIN short-wire a multiplexing structure input to a constant value -----")); - print_verilog_wire_constant_values(fp, instance_output_port, std::vector(1, const_value)); - print_verilog_comment(fp, std::string("---- END short-wire a multiplexing structure input to a constant value -----")); + print_verilog_comment( + fp, std::string("---- BEGIN short-wire a multiplexing structure input " + "to a constant value -----")); + print_verilog_wire_constant_values(fp, instance_output_port, + std::vector(1, const_value)); + print_verilog_comment( + fp, std::string("---- END short-wire a multiplexing structure input to " + "a constant value -----")); fp << std::endl; continue; /* Finish here */ } /* If the inputs are not supposed to be buffered */ if (false == circuit_lib.is_input_buffered(circuit_model)) { - print_verilog_comment(fp, std::string("---- BEGIN short-wire a multiplexing structure input to MUX module input -----")); + print_verilog_comment( + fp, std::string("---- BEGIN short-wire a multiplexing structure input " + "to MUX module input -----")); /* Short wire all the datapath inputs to the MUX inputs */ - print_verilog_wire_connection(fp, instance_output_port, instance_input_port, false); + print_verilog_wire_connection(fp, instance_output_port, + instance_input_port, false); - print_verilog_comment(fp, std::string("---- END short-wire a multiplexing structure input to MUX module input -----")); + print_verilog_comment( + fp, std::string("---- END short-wire a multiplexing structure input to " + "MUX module input -----")); fp << std::endl; continue; /* Finish here */ } - /* Reach here, we need a buffer, create a port-to-port map and output the buffer instance */ - print_verilog_comment(fp, std::string("---- BEGIN Instanciation of an input buffer module -----")); + /* Reach here, we need a buffer, create a port-to-port map and output the + * buffer instance */ + print_verilog_comment( + fp, + std::string("---- BEGIN Instanciation of an input buffer module -----")); /* Now we need to add intermediate buffers by instanciating the modules */ CircuitModelId buffer_model = circuit_lib.input_buffer_model(circuit_model); /* We must have a valid model id */ VTR_ASSERT(CircuitModelId::INVALID() != buffer_model); - print_verilog_buffer_instance(fp, module_manager, circuit_lib, module_id, buffer_model, instance_input_port, instance_output_port); + print_verilog_buffer_instance(fp, module_manager, circuit_lib, module_id, + buffer_model, instance_input_port, + instance_output_port); - print_verilog_comment(fp, std::string("---- END Instanciation of an input buffer module -----")); + print_verilog_comment( + fp, + std::string("---- END Instanciation of an input buffer module -----")); fp << std::endl; - } + } } /******************************************************************** - * Generate the output bufferes for a multiplexer or LUT in Verilog codes + * Generate the output bufferes for a multiplexer or LUT in Verilog codes * 1. If output are required to be buffered (specified by users), * buffers will be added to all the outputs. * 2. If output are required to NOT be buffered (specified by users), - * all the outputs will be short wired to MUX outputs. + * all the outputs will be short wired to MUX outputs. *******************************************************************/ -static -void generate_verilog_cmos_mux_module_output_buffers(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - std::fstream& fp, - const ModuleId& module_id, - const CircuitModelId& circuit_model, - const MuxGraph& mux_graph) { +static void generate_verilog_cmos_mux_module_output_buffers( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + std::fstream& fp, const ModuleId& module_id, + const CircuitModelId& circuit_model, const MuxGraph& mux_graph) { /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); /* Get the output ports from the mux */ - std::vector mux_output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector mux_output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); /* Iterate over all the outputs in the MUX module */ for (const auto& output_port : mux_output_ports) { /* Get the output port from MUX module */ - ModulePortId module_output_port_id = module_manager.find_module_port(module_id, circuit_lib.port_prefix(output_port)); + ModulePortId module_output_port_id = module_manager.find_module_port( + module_id, circuit_lib.port_prefix(output_port)); VTR_ASSERT(ModulePortId::INVALID() != module_output_port_id); /* Get the port from module */ - BasicPort module_output_port = module_manager.module_port(module_id, module_output_port_id); + BasicPort module_output_port = + module_manager.module_port(module_id, module_output_port_id); /* Iterate over each pin of the output port */ for (const auto& pin : circuit_lib.pins(output_port)) { /* Fetch fundamental information from MUX graph w.r.t. the input node */ /* Deposite the last level of the graph, which is a default value */ - size_t output_node_level = mux_graph.num_node_levels() - 1; - /* If there is a fracturable level specified for the output, we find the exact level */ + size_t output_node_level = mux_graph.num_node_levels() - 1; + /* If there is a fracturable level specified for the output, we find the + * exact level */ if (size_t(-1) != circuit_lib.port_lut_frac_level(output_port)) { output_node_level = circuit_lib.port_lut_frac_level(output_port); } /* Deposite a zero, which is a default value */ - size_t output_node_index_at_level = 0; + size_t output_node_index_at_level = 0; /* If there are output masks, we find the node_index */ if (!circuit_lib.port_lut_output_mask(output_port).empty()) { - output_node_index_at_level = circuit_lib.port_lut_output_mask(output_port).at(pin); - } + output_node_index_at_level = + circuit_lib.port_lut_output_mask(output_port).at(pin); + } /* Double check the node exists in the Mux Graph */ - VTR_ASSERT(MuxNodeId::INVALID() != mux_graph.node_id(output_node_level, output_node_index_at_level)); + VTR_ASSERT( + MuxNodeId::INVALID() != + mux_graph.node_id(output_node_level, output_node_index_at_level)); - /* Create the port information of the MUX input, which is the input of buffer instance */ - BasicPort instance_input_port(generate_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level); + /* Create the port information of the MUX input, which is the input of + * buffer instance */ + BasicPort instance_input_port( + generate_mux_node_name(output_node_level, false), + output_node_index_at_level, output_node_index_at_level); - /* Create the port information of the module output at the given pin range, which is the output of buffer instance */ + /* Create the port information of the module output at the given pin + * range, which is the output of buffer instance */ BasicPort instance_output_port(module_output_port.get_name(), pin, pin); /* If the output is not supposed to be buffered */ if (false == circuit_lib.is_output_buffered(circuit_model)) { - print_verilog_comment(fp, std::string("---- BEGIN short-wire a multiplexing structure output to MUX module output -----")); + print_verilog_comment( + fp, std::string("---- BEGIN short-wire a multiplexing structure " + "output to MUX module output -----")); /* Short wire all the datapath inputs to the MUX inputs */ - print_verilog_wire_connection(fp, instance_output_port, instance_input_port, false); + print_verilog_wire_connection(fp, instance_output_port, + instance_input_port, false); - print_verilog_comment(fp, std::string("---- END short-wire a multiplexing structure output to MUX module output -----")); + print_verilog_comment( + fp, std::string("---- END short-wire a multiplexing structure output " + "to MUX module output -----")); fp << std::endl; continue; /* Finish here */ } - /* Reach here, we need a buffer, create a port-to-port map and output the buffer instance */ - print_verilog_comment(fp, std::string("---- BEGIN Instanciation of an output buffer module -----")); + /* Reach here, we need a buffer, create a port-to-port map and output the + * buffer instance */ + print_verilog_comment( + fp, std::string( + "---- BEGIN Instanciation of an output buffer module -----")); /* Now we need to add intermediate buffers by instanciating the modules */ - CircuitModelId buffer_model = circuit_lib.output_buffer_model(circuit_model); + CircuitModelId buffer_model = + circuit_lib.output_buffer_model(circuit_model); /* We must have a valid model id */ VTR_ASSERT(CircuitModelId::INVALID() != buffer_model); - print_verilog_buffer_instance(fp, module_manager, circuit_lib, module_id, buffer_model, instance_input_port, instance_output_port); + print_verilog_buffer_instance(fp, module_manager, circuit_lib, module_id, + buffer_model, instance_input_port, + instance_output_port); - print_verilog_comment(fp, std::string("---- END Instanciation of an output buffer module -----")); + print_verilog_comment( + fp, + std::string("---- END Instanciation of an output buffer module -----")); fp << std::endl; } } } /******************************************************************** - * Generate the 4T1R-based internal logic - * (multiplexing structure) for a multiplexer in Verilog codes - * This function will : + * Generate the 4T1R-based internal logic + * (multiplexing structure) for a multiplexer in Verilog codes + * This function will : * 1. build a multiplexing structure by instanciating the branch circuits * generated before * 2. add intermediate buffers between multiplexing stages if specified. *******************************************************************/ -static -void generate_verilog_rram_mux_module_multiplexing_structure(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - std::fstream& fp, - const ModuleId& module_id, - const CircuitModelId& circuit_model, - const MuxGraph& mux_graph) { +static void generate_verilog_rram_mux_module_multiplexing_structure( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + std::fstream& fp, const ModuleId& module_id, + const CircuitModelId& circuit_model, const MuxGraph& mux_graph) { /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); /* Get the BL and WL ports from the mux */ - std::vector mux_blb_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_BLB, true); - std::vector mux_wl_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_WL, true); + std::vector mux_blb_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_BLB, true); + std::vector mux_wl_ports = + circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_WL, true); /* MUX graph must have only 1 BLB and 1 WL port */ VTR_ASSERT(1 == mux_blb_ports.size()); VTR_ASSERT(1 == mux_wl_ports.size()); /* Build the location map of intermediate buffers */ - std::vector inter_buffer_location_map = build_mux_intermediate_buffer_location_map(circuit_lib, circuit_model, mux_graph.num_node_levels()); + std::vector inter_buffer_location_map = + build_mux_intermediate_buffer_location_map(circuit_lib, circuit_model, + mux_graph.num_node_levels()); - print_verilog_comment(fp, std::string("---- BEGIN Internal Logic of a RRAM-based MUX module -----")); + print_verilog_comment( + fp, + std::string("---- BEGIN Internal Logic of a RRAM-based MUX module -----")); - print_verilog_comment(fp, std::string("---- BEGIN Internal wires of a RRAM-based MUX module -----")); + print_verilog_comment( + fp, + std::string("---- BEGIN Internal wires of a RRAM-based MUX module -----")); /* Print local wires which are the nodes in the mux graph */ for (size_t level = 0; level < mux_graph.num_levels(); ++level) { /* Print the internal wires located at this level */ - BasicPort internal_wire_port(generate_mux_node_name(level, false), mux_graph.num_nodes_at_level(level)); - fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, internal_wire_port) << ";" << std::endl; + BasicPort internal_wire_port(generate_mux_node_name(level, false), + mux_graph.num_nodes_at_level(level)); + fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, internal_wire_port) + << ";" << std::endl; /* Identify if an intermediate buffer is needed */ - if (false == inter_buffer_location_map[level]) { + if (false == inter_buffer_location_map[level]) { continue; } - BasicPort internal_wire_buffered_port(generate_mux_node_name(level, true), mux_graph.num_nodes_at_level(level)); - fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, internal_wire_buffered_port) << std::endl; + BasicPort internal_wire_buffered_port(generate_mux_node_name(level, true), + mux_graph.num_nodes_at_level(level)); + fp << "\t" + << generate_verilog_port(VERILOG_PORT_WIRE, internal_wire_buffered_port) + << std::endl; } - print_verilog_comment(fp, std::string("---- END Internal wires of a RRAM-based MUX module -----")); + print_verilog_comment( + fp, + std::string("---- END Internal wires of a RRAM-based MUX module -----")); fp << std::endl; /* Iterate over all the internal nodes and output nodes in the mux graph */ for (const auto& node : mux_graph.non_input_nodes()) { - print_verilog_comment(fp, std::string("---- BEGIN Instanciation of a branch RRAM-based MUX module -----")); - /* Get the size of branch circuit - * Instanciate an branch circuit by the size (fan-in) of the node + print_verilog_comment( + fp, + std::string( + "---- BEGIN Instanciation of a branch RRAM-based MUX module -----")); + /* Get the size of branch circuit + * Instanciate an branch circuit by the size (fan-in) of the node */ size_t branch_size = mux_graph.node_in_edges(node).size(); @@ -877,7 +996,7 @@ void generate_verilog_rram_mux_module_multiplexing_structure(ModuleManager& modu size_t output_node_index_at_level = mux_graph.node_index_at_level(node); /* Get the nodes which drive the root_node */ - std::vector input_nodes; + std::vector input_nodes; for (const auto& edge : mux_graph.node_in_edges(node)) { /* Get the nodes drive the edge */ for (const auto& src_node : mux_graph.edge_src_nodes(edge)) { @@ -888,7 +1007,7 @@ void generate_verilog_rram_mux_module_multiplexing_structure(ModuleManager& modu VTR_ASSERT(input_nodes.size() == branch_size); /* Get the mems in the branch circuits */ - std::vector mems; + std::vector mems; for (const auto& edge : mux_graph.node_in_edges(node)) { /* Get the mem control the edge */ MuxMemId mem = mux_graph.find_edge_mem(edge); @@ -898,9 +1017,11 @@ void generate_verilog_rram_mux_module_multiplexing_structure(ModuleManager& modu } } - /* Instanciate the branch module which is a tgate-based module + /* Instanciate the branch module which is a tgate-based module */ - std::string branch_module_name= generate_mux_branch_subckt_name(circuit_lib, circuit_model, branch_size, mems.size(), VERILOG_MUX_BASIS_POSTFIX); + std::string branch_module_name = + generate_mux_branch_subckt_name(circuit_lib, circuit_model, branch_size, + mems.size(), VERILOG_MUX_BASIS_POSTFIX); /* Get the moduleId for the submodule */ ModuleId branch_module_id = module_manager.find_module(branch_module_name); /* We must have one */ @@ -908,176 +1029,228 @@ void generate_verilog_rram_mux_module_multiplexing_structure(ModuleManager& modu /* Create a port-to-port map */ std::map port2port_name_map; - /* TODO: the branch module name should NOT be hard-coded. Use the port lib_name given by users! */ + /* TODO: the branch module name should NOT be hard-coded. Use the port + * lib_name given by users! */ /* All the input node names organized in bus */ std::vector branch_node_input_ports; for (const auto& input_node : input_nodes) { /* Generate the port info of each input node */ size_t input_node_level = mux_graph.node_level(input_node); - size_t input_node_index_at_level = mux_graph.node_index_at_level(input_node); - BasicPort branch_node_input_port(generate_mux_node_name(input_node_level, inter_buffer_location_map[input_node_level]), input_node_index_at_level, input_node_index_at_level); - branch_node_input_ports.push_back(branch_node_input_port); - } + size_t input_node_index_at_level = + mux_graph.node_index_at_level(input_node); + BasicPort branch_node_input_port( + generate_mux_node_name(input_node_level, + inter_buffer_location_map[input_node_level]), + input_node_index_at_level, input_node_index_at_level); + branch_node_input_ports.push_back(branch_node_input_port); + } /* Create the port info for the input */ /* TODO: the naming could be more flexible? */ - BasicPort instance_input_port = generate_verilog_bus_port(branch_node_input_ports, std::string(generate_mux_node_name(output_node_level, false) + "_in")); - /* If we have more than 1 port in the combined instance ports , + BasicPort instance_input_port = generate_verilog_bus_port( + branch_node_input_ports, + std::string(generate_mux_node_name(output_node_level, false) + "_in")); + /* If we have more than 1 port in the combined instance ports , * output a local wire */ if (1 < combine_verilog_ports(branch_node_input_ports).size()) { /* Print a local wire for the merged ports */ - fp << "\t" << generate_verilog_local_wire(instance_input_port, branch_node_input_ports) << std::endl; + fp << "\t" + << generate_verilog_local_wire(instance_input_port, + branch_node_input_ports) + << std::endl; } else { /* Safety check */ VTR_ASSERT(1 == combine_verilog_ports(branch_node_input_ports).size()); } /* Link nodes to input ports for the branch module */ - ModulePortId module_input_port_id = module_manager.find_module_port(branch_module_id, "in"); + ModulePortId module_input_port_id = + module_manager.find_module_port(branch_module_id, "in"); VTR_ASSERT(ModulePortId::INVALID() != module_input_port_id); /* Get the port from module */ - BasicPort module_input_port = module_manager.module_port(branch_module_id, module_input_port_id); - port2port_name_map[module_input_port.get_name()] = instance_input_port; + BasicPort module_input_port = + module_manager.module_port(branch_module_id, module_input_port_id); + port2port_name_map[module_input_port.get_name()] = instance_input_port; /* Link nodes to output ports for the branch module */ - BasicPort instance_output_port(generate_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level); - ModulePortId module_output_port_id = module_manager.find_module_port(branch_module_id, "out"); + BasicPort instance_output_port( + generate_mux_node_name(output_node_level, false), + output_node_index_at_level, output_node_index_at_level); + ModulePortId module_output_port_id = + module_manager.find_module_port(branch_module_id, "out"); VTR_ASSERT(ModulePortId::INVALID() != module_output_port_id); /* Get the port from module */ - BasicPort module_output_port = module_manager.module_port(branch_module_id, module_output_port_id); - port2port_name_map[module_output_port.get_name()] = instance_output_port; + BasicPort module_output_port = + module_manager.module_port(branch_module_id, module_output_port_id); + port2port_name_map[module_output_port.get_name()] = instance_output_port; - /* All the mem node names organized in bus - * RRAM-based MUX uses BLB and WL to control memories + /* All the mem node names organized in bus + * RRAM-based MUX uses BLB and WL to control memories */ std::vector branch_node_blb_ports; for (const auto& mem : mems) { /* Generate the port info of each mem node: */ - BasicPort branch_node_blb_port(circuit_lib.port_prefix(mux_blb_ports[0]), size_t(mem), size_t(mem)); - branch_node_blb_ports.push_back(branch_node_blb_port); - } - /* Every stage, we have an additonal BLB and WL in controlling purpose - * The additional BLB is arranged at the tail of BLB port - * For example: + BasicPort branch_node_blb_port(circuit_lib.port_prefix(mux_blb_ports[0]), + size_t(mem), size_t(mem)); + branch_node_blb_ports.push_back(branch_node_blb_port); + } + /* Every stage, we have an additonal BLB and WL in controlling purpose + * The additional BLB is arranged at the tail of BLB port + * For example: * The total port width is BLB[0 ... + - 1] * The regular BLB used by branches are BLB[0 .. - 1] - * The additional BLB used by branches are BLB[ .. + - 1] + * The additional BLB used by branches are BLB[ .. + + * - 1] * * output_node_level is always larger than the mem_level by 1 */ - branch_node_blb_ports.push_back(BasicPort(circuit_lib.port_prefix(mux_blb_ports[0]), - mux_graph.num_memory_bits() + output_node_level - 1, - mux_graph.num_memory_bits() + output_node_level - 1) - ); + branch_node_blb_ports.push_back( + BasicPort(circuit_lib.port_prefix(mux_blb_ports[0]), + mux_graph.num_memory_bits() + output_node_level - 1, + mux_graph.num_memory_bits() + output_node_level - 1)); /* Create the port info for the input */ /* TODO: the naming could be more flexible? */ - BasicPort instance_blb_port = generate_verilog_bus_port(branch_node_blb_ports, std::string(generate_mux_node_name(output_node_level, false) + "_blb")); - /* If we have more than 1 port in the combined instance ports , + BasicPort instance_blb_port = generate_verilog_bus_port( + branch_node_blb_ports, + std::string(generate_mux_node_name(output_node_level, false) + "_blb")); + /* If we have more than 1 port in the combined instance ports , * output a local wire */ if (1 < combine_verilog_ports(branch_node_blb_ports).size()) { /* Print a local wire for the merged ports */ - fp << "\t" << generate_verilog_local_wire(instance_blb_port, branch_node_blb_ports) << std::endl; + fp << "\t" + << generate_verilog_local_wire(instance_blb_port, + branch_node_blb_ports) + << std::endl; } else { /* Safety check */ VTR_ASSERT(1 == combine_verilog_ports(branch_node_blb_ports).size()); } /* Link nodes to BLB ports for the branch module */ - ModulePortId module_blb_port_id = module_manager.find_module_port(branch_module_id, circuit_lib.port_prefix(mux_blb_ports[0])); + ModulePortId module_blb_port_id = module_manager.find_module_port( + branch_module_id, circuit_lib.port_prefix(mux_blb_ports[0])); VTR_ASSERT(ModulePortId::INVALID() != module_blb_port_id); /* Get the port from module */ - BasicPort module_blb_port = module_manager.module_port(branch_module_id, module_blb_port_id); - port2port_name_map[module_blb_port.get_name()] = instance_blb_port; + BasicPort module_blb_port = + module_manager.module_port(branch_module_id, module_blb_port_id); + port2port_name_map[module_blb_port.get_name()] = instance_blb_port; std::vector branch_node_wl_ports; for (const auto& mem : mems) { /* Generate the port info of each mem node: */ - BasicPort branch_node_blb_port(circuit_lib.port_prefix(mux_wl_ports[0]), size_t(mem), size_t(mem)); - branch_node_wl_ports.push_back(branch_node_blb_port); - } - /* Every stage, we have an additonal BLB and WL in controlling purpose - * The additional BLB is arranged at the tail of BLB port - * For example: + BasicPort branch_node_blb_port(circuit_lib.port_prefix(mux_wl_ports[0]), + size_t(mem), size_t(mem)); + branch_node_wl_ports.push_back(branch_node_blb_port); + } + /* Every stage, we have an additonal BLB and WL in controlling purpose + * The additional BLB is arranged at the tail of BLB port + * For example: * The total port width is WL[0 ... + - 1] * The regular BLB used by branches are WL[0 .. - 1] - * The additional BLB used by branches are WL[ .. + - 1] + * The additional BLB used by branches are WL[ .. + + * - 1] * * output_node_level is always larger than the mem_level by 1 */ - branch_node_wl_ports.push_back(BasicPort(circuit_lib.port_prefix(mux_wl_ports[0]), - mux_graph.num_memory_bits() + output_node_level - 1, - mux_graph.num_memory_bits() + output_node_level - 1) - ); + branch_node_wl_ports.push_back( + BasicPort(circuit_lib.port_prefix(mux_wl_ports[0]), + mux_graph.num_memory_bits() + output_node_level - 1, + mux_graph.num_memory_bits() + output_node_level - 1)); /* Create the port info for the WL */ /* TODO: the naming could be more flexible? */ - BasicPort instance_wl_port = generate_verilog_bus_port(branch_node_wl_ports, std::string(generate_mux_node_name(output_node_level, false) + "_wl")); - /* If we have more than 1 port in the combined instance ports , + BasicPort instance_wl_port = generate_verilog_bus_port( + branch_node_wl_ports, + std::string(generate_mux_node_name(output_node_level, false) + "_wl")); + /* If we have more than 1 port in the combined instance ports , * output a local wire */ if (1 < combine_verilog_ports(branch_node_wl_ports).size()) { /* Print a local wire for the merged ports */ - fp << "\t" << generate_verilog_local_wire(instance_wl_port, branch_node_wl_ports) << std::endl; + fp << "\t" + << generate_verilog_local_wire(instance_wl_port, branch_node_wl_ports) + << std::endl; } else { /* Safety check */ VTR_ASSERT(1 == combine_verilog_ports(branch_node_wl_ports).size()); } /* Link nodes to BLB ports for the branch module */ - ModulePortId module_wl_port_id = module_manager.find_module_port(branch_module_id, circuit_lib.port_prefix(mux_wl_ports[0])); + ModulePortId module_wl_port_id = module_manager.find_module_port( + branch_module_id, circuit_lib.port_prefix(mux_wl_ports[0])); VTR_ASSERT(ModulePortId::INVALID() != module_wl_port_id); /* Get the port from module */ - BasicPort module_wl_port = module_manager.module_port(branch_module_id, module_wl_port_id); - port2port_name_map[module_wl_port.get_name()] = instance_wl_port; + BasicPort module_wl_port = + module_manager.module_port(branch_module_id, module_wl_port_id); + port2port_name_map[module_wl_port.get_name()] = instance_wl_port; /* Output an instance of the module */ - print_verilog_module_instance(fp, module_manager, module_id, branch_module_id, port2port_name_map, circuit_lib.dump_explicit_port_map(circuit_model)); + print_verilog_module_instance( + fp, module_manager, module_id, branch_module_id, port2port_name_map, + circuit_lib.dump_explicit_port_map(circuit_model)); /* IMPORTANT: this update MUST be called after the instance outputting!!!! - * update the module manager with the relationship between the parent and child modules + * update the module manager with the relationship between the parent and + * child modules */ module_manager.add_child_module(module_id, branch_module_id); - print_verilog_comment(fp, std::string("---- END Instanciation of a branch RRAM-based MUX module -----")); + print_verilog_comment( + fp, std::string( + "---- END Instanciation of a branch RRAM-based MUX module -----")); fp << std::endl; if (false == inter_buffer_location_map[output_node_level]) { continue; /* No need for intermediate buffers */ } - print_verilog_comment(fp, std::string("---- BEGIN Instanciation of an intermediate buffer modules -----")); + print_verilog_comment( + fp, + std::string( + "---- BEGIN Instanciation of an intermediate buffer modules -----")); /* Now we need to add intermediate buffers by instanciating the modules */ - CircuitModelId buffer_model = circuit_lib.lut_intermediate_buffer_model(circuit_model); + CircuitModelId buffer_model = + circuit_lib.lut_intermediate_buffer_model(circuit_model); /* We must have a valid model id */ VTR_ASSERT(CircuitModelId::INVALID() != buffer_model); - - BasicPort buffer_instance_input_port(generate_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level); - BasicPort buffer_instance_output_port(generate_mux_node_name(output_node_level, true), output_node_index_at_level, output_node_index_at_level); - print_verilog_buffer_instance(fp, module_manager, circuit_lib, module_id, buffer_model, buffer_instance_input_port, buffer_instance_output_port); + BasicPort buffer_instance_input_port( + generate_mux_node_name(output_node_level, false), + output_node_index_at_level, output_node_index_at_level); + BasicPort buffer_instance_output_port( + generate_mux_node_name(output_node_level, true), + output_node_index_at_level, output_node_index_at_level); - print_verilog_comment(fp, std::string("---- END Instanciation of an intermediate buffer module -----")); + print_verilog_buffer_instance(fp, module_manager, circuit_lib, module_id, + buffer_model, buffer_instance_input_port, + buffer_instance_output_port); + + print_verilog_comment( + fp, std::string( + "---- END Instanciation of an intermediate buffer module -----")); fp << std::endl; } - print_verilog_comment(fp, std::string("---- END Internal Logic of a RRAM-based MUX module -----")); + print_verilog_comment( + fp, + std::string("---- END Internal Logic of a RRAM-based MUX module -----")); fp << std::endl; } /********************************************************************* - * Generate Verilog codes modeling a RRAM-based multiplexer with the given size + * Generate Verilog codes modeling a RRAM-based multiplexer with the given size * The Verilog module will consist of three parts: - * 1. instances of the branch circuits of multiplexers which are generated before - * This builds up the 4T1R-based multiplexing structure + * 1. instances of the branch circuits of multiplexers which are generated + *before This builds up the 4T1R-based multiplexing structure * * BLB WL * | | ... * v v - * +--------+ - * in[0]-->| | BLB WL + * +--------+ + * in[0]-->| | BLB WL * ...| Branch |-----+ | | * in -->| 0 | | v v * [N-1] +--------+ | +--------+ @@ -1094,42 +1267,46 @@ void generate_verilog_rram_mux_module_multiplexing_structure(ModuleManager& modu * 2. Input buffers/inverters * 3. Output buffers/inverters *********************************************************************/ -static -void generate_verilog_rram_mux_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - std::fstream& fp, - const CircuitModelId& circuit_model, - const std::string& module_name, - const MuxGraph& mux_graph, - const e_verilog_default_net_type& default_net_type) { +static void generate_verilog_rram_mux_module( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + std::fstream& fp, const CircuitModelId& circuit_model, + const std::string& module_name, const MuxGraph& mux_graph, + const e_verilog_default_net_type& default_net_type) { /* Error out for the conditions where we are not yet supported! */ if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)) { /* RRAM LUT is not supported now... */ - VTR_LOGF_ERROR(__FILE__, __LINE__, + VTR_LOGF_ERROR(__FILE__, __LINE__, "RRAM-based LUT is not supported for circuit model '%s'!\n", circuit_lib.model_name(circuit_model).c_str()); exit(1); } /* Get the global ports required by MUX (and any submodules) */ - std::vector mux_global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector mux_global_ports = + circuit_lib.model_global_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); /* Get the input ports from the mux */ - std::vector mux_input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector mux_input_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true); /* Get the output ports from the mux */ - std::vector mux_output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector mux_output_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true); /* Get the BL and WL ports from the mux */ - std::vector mux_blb_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_BLB, true); - std::vector mux_wl_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_WL, true); + std::vector mux_blb_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_BLB, true); + std::vector mux_wl_ports = + circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_WL, true); /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); /* Generate the Verilog netlist according to the mux_graph */ - /* Find out the number of data-path inputs */ - size_t num_inputs = find_mux_num_datapath_inputs(circuit_lib, circuit_model, mux_graph.num_inputs()); - /* Find out the number of outputs */ + /* Find out the number of data-path inputs */ + size_t num_inputs = find_mux_num_datapath_inputs(circuit_lib, circuit_model, + mux_graph.num_inputs()); + /* Find out the number of outputs */ size_t num_outputs = mux_graph.num_outputs(); - /* Find out the number of memory bits */ + /* Find out the number of memory bits */ size_t num_mems = mux_graph.num_memory_bits(); /* Check codes to ensure the port of Verilog netlists will match */ @@ -1138,21 +1315,25 @@ void generate_verilog_rram_mux_module(ModuleManager& module_manager, VTR_ASSERT(1 == mux_blb_ports.size()); VTR_ASSERT(1 == mux_wl_ports.size()); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId module_id = module_manager.add_module(module_name); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId module_id = module_manager.add_module(module_name); VTR_ASSERT(ModuleId::INVALID() != module_id); /* Add module ports */ /* Add each global port */ for (const auto& port : mux_global_ports) { /* Configure each global port */ - BasicPort global_port(circuit_lib.port_prefix(port), circuit_lib.port_size(port)); - module_manager.add_port(module_id, global_port, ModuleManager::MODULE_GLOBAL_PORT); + BasicPort global_port(circuit_lib.port_prefix(port), + circuit_lib.port_size(port)); + module_manager.add_port(module_id, global_port, + ModuleManager::MODULE_GLOBAL_PORT); } /* Add each input port */ size_t input_port_cnt = 0; for (const auto& port : mux_input_ports) { BasicPort input_port(circuit_lib.port_prefix(port), num_inputs); - module_manager.add_port(module_id, input_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(module_id, input_port, + ModuleManager::MODULE_INPUT_PORT); /* Update counter */ input_port_cnt++; } @@ -1164,89 +1345,98 @@ void generate_verilog_rram_mux_module(ModuleManager& module_manager, if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)) { output_port.set_width(circuit_lib.port_size(port)); } - module_manager.add_port(module_id, output_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(module_id, output_port, + ModuleManager::MODULE_OUTPUT_PORT); } /* BLB port */ for (const auto& port : mux_blb_ports) { - /* IMPORTANT: RRAM-based MUX has an additional BLB pin per level - * So, the actual port width of BLB should be added by the number of levels of the MUX graph + /* IMPORTANT: RRAM-based MUX has an additional BLB pin per level + * So, the actual port width of BLB should be added by the number of levels + * of the MUX graph */ - BasicPort blb_port(circuit_lib.port_prefix(port), num_mems + mux_graph.num_levels()); - module_manager.add_port(module_id, blb_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort blb_port(circuit_lib.port_prefix(port), + num_mems + mux_graph.num_levels()); + module_manager.add_port(module_id, blb_port, + ModuleManager::MODULE_INPUT_PORT); } /* WL port */ for (const auto& port : mux_wl_ports) { - /* IMPORTANT: RRAM-based MUX has an additional WL pin per level - * So, the actual port width of WL should be added by the number of levels of the MUX graph + /* IMPORTANT: RRAM-based MUX has an additional WL pin per level + * So, the actual port width of WL should be added by the number of levels + * of the MUX graph */ - BasicPort wl_port(circuit_lib.port_prefix(port), num_mems + mux_graph.num_levels()); - module_manager.add_port(module_id, wl_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort wl_port(circuit_lib.port_prefix(port), + num_mems + mux_graph.num_levels()); + module_manager.add_port(module_id, wl_port, + ModuleManager::MODULE_INPUT_PORT); } - + /* dump module definition + ports */ - print_verilog_module_declaration(fp, module_manager, module_id, default_net_type); + print_verilog_module_declaration(fp, module_manager, module_id, + default_net_type); /* TODO: Print the internal logic in Verilog codes */ - generate_verilog_rram_mux_module_multiplexing_structure(module_manager, circuit_lib, fp, module_id, circuit_model, mux_graph); + generate_verilog_rram_mux_module_multiplexing_structure( + module_manager, circuit_lib, fp, module_id, circuit_model, mux_graph); /* Print the input and output buffers in Verilog codes */ - /* TODO, we should rename the follow functions to a generic name? Since they are applicable to both MUXes */ - generate_verilog_cmos_mux_module_input_buffers(module_manager, circuit_lib, fp, module_id, circuit_model, mux_graph); - generate_verilog_cmos_mux_module_output_buffers(module_manager, circuit_lib, fp, module_id, circuit_model, mux_graph); + /* TODO, we should rename the follow functions to a generic name? Since they + * are applicable to both MUXes */ + generate_verilog_cmos_mux_module_input_buffers( + module_manager, circuit_lib, fp, module_id, circuit_model, mux_graph); + generate_verilog_cmos_mux_module_output_buffers( + module_manager, circuit_lib, fp, module_id, circuit_model, mux_graph); /* Put an end to the Verilog module */ print_verilog_module_end(fp, module_name); } - /*********************************************** - * Generate Verilog codes modeling a multiplexer + * Generate Verilog codes modeling a multiplexer * with the given graph-level description **********************************************/ -static -void generate_verilog_mux_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - std::fstream& fp, - const CircuitModelId& mux_model, - const MuxGraph& mux_graph, - const bool& use_explicit_port_map, - const e_verilog_default_net_type& default_net_type) { - std::string module_name = generate_mux_subckt_name(circuit_lib, mux_model, - find_mux_num_datapath_inputs(circuit_lib, mux_model, mux_graph.num_inputs()), - std::string("")); - - /* Multiplexers built with different technology is in different organization */ +static void generate_verilog_mux_module( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + std::fstream& fp, const CircuitModelId& mux_model, const MuxGraph& mux_graph, + const bool& use_explicit_port_map, + const e_verilog_default_net_type& default_net_type) { + std::string module_name = + generate_mux_subckt_name(circuit_lib, mux_model, + find_mux_num_datapath_inputs( + circuit_lib, mux_model, mux_graph.num_inputs()), + std::string("")); + + /* Multiplexers built with different technology is in different organization + */ switch (circuit_lib.design_tech_type(mux_model)) { - case CIRCUIT_MODEL_DESIGN_CMOS: { - /* Use Verilog writer to print the module to file */ - ModuleId mux_module = module_manager.find_module(module_name); - VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); - write_verilog_module_to_file(fp, module_manager, mux_module, - ( use_explicit_port_map - || circuit_lib.dump_explicit_port_map(mux_model) - || circuit_lib.dump_explicit_port_map(circuit_lib.pass_gate_logic_model(mux_model)) ), - default_net_type); - /* Add an empty line as a splitter */ - fp << std::endl; - break; - } - case CIRCUIT_MODEL_DESIGN_RRAM: - /* TODO: RRAM-based Multiplexer Verilog module generation */ - generate_verilog_rram_mux_module(module_manager, - circuit_lib, - fp, - mux_model, - module_name, - mux_graph, - default_net_type); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid design technology of multiplexer '%s'\n", - circuit_lib.model_name(mux_model).c_str()); - exit(1); + case CIRCUIT_MODEL_DESIGN_CMOS: { + /* Use Verilog writer to print the module to file */ + ModuleId mux_module = module_manager.find_module(module_name); + VTR_ASSERT(true == module_manager.valid_module_id(mux_module)); + write_verilog_module_to_file( + fp, module_manager, mux_module, + (use_explicit_port_map || + circuit_lib.dump_explicit_port_map(mux_model) || + circuit_lib.dump_explicit_port_map( + circuit_lib.pass_gate_logic_model(mux_model))), + default_net_type); + /* Add an empty line as a splitter */ + fp << std::endl; + break; + } + case CIRCUIT_MODEL_DESIGN_RRAM: + /* TODO: RRAM-based Multiplexer Verilog module generation */ + generate_verilog_rram_mux_module(module_manager, circuit_lib, fp, + mux_model, module_name, mux_graph, + default_net_type); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid design technology of multiplexer '%s'\n", + circuit_lib.model_name(mux_model).c_str()); + exit(1); } } @@ -1254,15 +1444,12 @@ void generate_verilog_mux_module(ModuleManager& module_manager, * Generate primitive Verilog modules for all the unique * multiplexers in the FPGA device **********************************************/ -static -void print_verilog_submodule_mux_primitives(ModuleManager& module_manager, - NetlistManager& netlist_manager, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const std::string& submodule_dir, - const std::string& submodule_dir_name, - const FabricVerilogOption& options) { - /* Output primitive cells for MUX modules */ +static void print_verilog_submodule_mux_primitives( + ModuleManager& module_manager, NetlistManager& netlist_manager, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, + const std::string& submodule_dir, const std::string& submodule_dir_name, + const FabricVerilogOption& options) { + /* Output primitive cells for MUX modules */ std::string verilog_fname(MUX_PRIMITIVES_VERILOG_FILE_NAME); std::string verilog_fpath(submodule_dir + verilog_fname); @@ -1272,30 +1459,33 @@ void print_verilog_submodule_mux_primitives(ModuleManager& module_manager, check_file_stream(verilog_fpath.c_str(), fp); - /* Print out debugging information for if the file is not opened/created properly */ + /* Print out debugging information for if the file is not opened/created + * properly */ VTR_LOG("Writing Verilog netlist for Multiplexer primitives '%s' ...", - verilog_fpath.c_str()); + verilog_fpath.c_str()); - print_verilog_file_header(fp, "Multiplexer primitives", options.time_stamp()); + print_verilog_file_header(fp, "Multiplexer primitives", options.time_stamp()); /* Record if the branch module has been outputted - * since different sizes of routing multiplexers may share the same branch module + * since different sizes of routing multiplexers may share the same branch + * module */ std::map branch_mux_module_is_outputted; - /* Generate basis sub-circuit for unique branches shared by the multiplexers */ + /* Generate basis sub-circuit for unique branches shared by the multiplexers + */ for (auto mux : mux_lib.muxes()) { const MuxGraph& mux_graph = mux_lib.mux_graph(mux); - CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); + CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); /* Create a mux graph for the branch circuit */ - std::vector branch_mux_graphs = mux_graph.build_mux_branch_graphs(); + std::vector branch_mux_graphs = + mux_graph.build_mux_branch_graphs(); /* Create branch circuits, which are N:1 one-level or 2:1 tree-like MUXes */ for (auto branch_mux_graph : branch_mux_graphs) { - generate_verilog_mux_branch_module(module_manager, circuit_lib, fp, mux_circuit_model, - branch_mux_graph, - options.explicit_port_mapping(), - options.default_net_type(), - branch_mux_module_is_outputted); + generate_verilog_mux_branch_module( + module_manager, circuit_lib, fp, mux_circuit_model, branch_mux_graph, + options.explicit_port_mapping(), options.default_net_type(), + branch_mux_module_is_outputted); } } @@ -1319,15 +1509,12 @@ void print_verilog_submodule_mux_primitives(ModuleManager& module_manager, * Generate top-level Verilog modules for all the unique * multiplexers in the FPGA device **********************************************/ -static -void print_verilog_submodule_mux_top_modules(ModuleManager& module_manager, - NetlistManager& netlist_manager, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const std::string& submodule_dir, - const std::string& submodule_dir_name, - const FabricVerilogOption& options) { - /* Output top-level MUX modules */ +static void print_verilog_submodule_mux_top_modules( + ModuleManager& module_manager, NetlistManager& netlist_manager, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, + const std::string& submodule_dir, const std::string& submodule_dir_name, + const FabricVerilogOption& options) { + /* Output top-level MUX modules */ std::string verilog_fname(MUXES_VERILOG_FILE_NAME); std::string verilog_fpath(submodule_dir + verilog_fname); @@ -1337,24 +1524,21 @@ void print_verilog_submodule_mux_top_modules(ModuleManager& module_manager, check_file_stream(verilog_fpath.c_str(), fp); - /* Print out debugging information for if the file is not opened/created properly */ + /* Print out debugging information for if the file is not opened/created + * properly */ VTR_LOG("Writing Verilog netlist for Multiplexers '%s' ...", - verilog_fpath.c_str()); + verilog_fpath.c_str()); - print_verilog_file_header(fp, "Multiplexers", options.time_stamp()); + print_verilog_file_header(fp, "Multiplexers", options.time_stamp()); /* Generate unique Verilog modules for the multiplexers */ for (auto mux : mux_lib.muxes()) { const MuxGraph& mux_graph = mux_lib.mux_graph(mux); - CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); + CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux); /* Create MUX circuits */ - generate_verilog_mux_module(module_manager, - circuit_lib, - fp, - mux_circuit_model, - mux_graph, - options.explicit_port_mapping(), - options.default_net_type()); + generate_verilog_mux_module( + module_manager, circuit_lib, fp, mux_circuit_model, mux_graph, + options.explicit_port_mapping(), options.default_net_type()); } /* Close the file stream */ @@ -1389,21 +1573,13 @@ void print_verilog_submodule_muxes(ModuleManager& module_manager, const std::string& submodule_dir, const std::string& submodule_dir_name, const FabricVerilogOption& options) { - print_verilog_submodule_mux_primitives(module_manager, - netlist_manager, - mux_lib, - circuit_lib, - submodule_dir, - submodule_dir_name, - options); + print_verilog_submodule_mux_primitives(module_manager, netlist_manager, + mux_lib, circuit_lib, submodule_dir, + submodule_dir_name, options); - print_verilog_submodule_mux_top_modules(module_manager, - netlist_manager, - mux_lib, - circuit_lib, - submodule_dir, - submodule_dir_name, - options); + print_verilog_submodule_mux_top_modules(module_manager, netlist_manager, + mux_lib, circuit_lib, submodule_dir, + submodule_dir_name, options); } } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_mux.h b/openfpga/src/fpga_verilog/verilog_mux.h index a1e03ef92..f21c99f5a 100644 --- a/openfpga/src/fpga_verilog/verilog_mux.h +++ b/openfpga/src/fpga_verilog/verilog_mux.h @@ -8,11 +8,11 @@ #include #include "circuit_library.h" +#include "fabric_verilog_options.h" +#include "module_manager.h" #include "mux_graph.h" #include "mux_library.h" -#include "module_manager.h" #include "netlist_manager.h" -#include "fabric_verilog_options.h" /******************************************************************** * Function declaration diff --git a/openfpga/src/fpga_verilog/verilog_port_types.h b/openfpga/src/fpga_verilog/verilog_port_types.h index 11e70622a..bba6e7052 100644 --- a/openfpga/src/fpga_verilog/verilog_port_types.h +++ b/openfpga/src/fpga_verilog/verilog_port_types.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files required by the data structure definition *******************************************************************/ -#include #include +#include /* Begin namespace openfpga */ namespace openfpga { @@ -15,7 +15,9 @@ enum e_verilog_default_net_type { VERILOG_DEFAULT_NET_TYPE_WIRE, NUM_VERILOG_DEFAULT_NET_TYPES, }; -constexpr std::array VERILOG_DEFAULT_NET_TYPE_STRING = {{"none", "wire"}}; //String versions of default net types +constexpr std::array + VERILOG_DEFAULT_NET_TYPE_STRING = { + {"none", "wire"}}; // String versions of default net types enum e_dump_verilog_port_type { VERILOG_PORT_INPUT, @@ -26,9 +28,11 @@ enum e_dump_verilog_port_type { VERILOG_PORT_CONKT, NUM_VERILOG_PORT_TYPES }; -constexpr std::array VERILOG_PORT_TYPE_STRING = {{"input", "output", "inout", "wire", "reg", ""}}; /* string version of enum e_verilog_port_type */ +constexpr std::array + VERILOG_PORT_TYPE_STRING = { + {"input", "output", "inout", "wire", "reg", + ""}}; /* string version of enum e_verilog_port_type */ } /* End namespace openfpga*/ #endif - diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp index aaec1ceb7..c0d3ef4d7 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp @@ -5,26 +5,22 @@ #include /* Headers from vtrutil library */ +#include "command_exit_codes.h" #include "vtr_assert.h" #include "vtr_log.h" #include "vtr_time.h" -#include "command_exit_codes.h" - /* Headers from openfpgautil library */ -#include "openfpga_port.h" -#include "openfpga_digest.h" -#include "openfpga_reserved_words.h" - #include "bitstream_manager_utils.h" #include "openfpga_atom_netlist_utils.h" - +#include "openfpga_digest.h" #include "openfpga_naming.h" - +#include "openfpga_port.h" +#include "openfpga_reserved_words.h" #include "verilog_constants.h" -#include "verilog_writer_utils.h" -#include "verilog_testbench_utils.h" #include "verilog_preconfig_top_module.h" +#include "verilog_testbench_utils.h" +#include "verilog_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -34,18 +30,16 @@ namespace openfpga { * FPGA top module * The module ports do exactly match the input benchmark *******************************************************************/ -static -void print_verilog_preconfig_top_module_ports(std::fstream &fp, - const std::string &circuit_name, - const AtomContext &atom_ctx, - const VprNetlistAnnotation &netlist_annotation, - const BusGroup& bus_group) { - +static void print_verilog_preconfig_top_module_ports( + std::fstream &fp, const std::string &circuit_name, + const AtomContext &atom_ctx, const VprNetlistAnnotation &netlist_annotation, + const BusGroup &bus_group) { /* Validate the file stream */ valid_file_stream(fp); /* Module declaration */ - fp << "module " << circuit_name << std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX); + fp << "module " << circuit_name + << std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX); fp << " (" << std::endl; /* Port type-to-type mapping */ @@ -61,21 +55,25 @@ void print_verilog_preconfig_top_module_ports(std::fstream &fp, /* Print all the I/Os of the circuit implementation to be tested*/ for (const AtomBlockId &atom_blk : atom_ctx.nlist.blocks()) { /* We only care I/O logical blocks !*/ - if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) && (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk))) { + if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) && + (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk))) { continue; } std::string block_name = atom_ctx.nlist.block_name(atom_blk); - /* The block may be renamed as it contains special characters which violate Verilog syntax */ + /* The block may be renamed as it contains special characters which violate + * Verilog syntax */ if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); } /* For output block, remove the prefix which is added by VPR */ std::vector output_port_prefix_to_remove; - output_port_prefix_to_remove.push_back(std::string(VPR_BENCHMARK_OUT_PORT_PREFIX)); - output_port_prefix_to_remove.push_back(std::string(OPENFPGA_BENCHMARK_OUT_PORT_PREFIX)); + output_port_prefix_to_remove.push_back( + std::string(VPR_BENCHMARK_OUT_PORT_PREFIX)); + output_port_prefix_to_remove.push_back( + std::string(OPENFPGA_BENCHMARK_OUT_PORT_PREFIX)); if (AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)) { - for (const std::string& prefix_to_remove : output_port_prefix_to_remove) { + for (const std::string &prefix_to_remove : output_port_prefix_to_remove) { if (!prefix_to_remove.empty()) { if (0 == block_name.find(prefix_to_remove)) { block_name.erase(0, prefix_to_remove.length()); @@ -94,7 +92,8 @@ void print_verilog_preconfig_top_module_ports(std::fstream &fp, */ BusGroupId bus_id = bus_group.find_pin_bus(block_name); if (bus_id) { - if (port_list.end() == std::find(port_list.begin(), port_list.end(), bus_group.bus_port(bus_id))) { + if (port_list.end() == std::find(port_list.begin(), port_list.end(), + bus_group.bus_port(bus_id))) { port_list.push_back(bus_group.bus_port(bus_id)); port_types.push_back(atom_ctx.nlist.block_type(atom_blk)); port_big_endian.push_back(bus_group.is_big_endian(bus_id)); @@ -118,7 +117,8 @@ void print_verilog_preconfig_top_module_ports(std::fstream &fp, fp << "," << std::endl; } - fp << generate_verilog_port(port_type2type_map[port_type], module_port, true, port_big_endian[iport]); + fp << generate_verilog_port(port_type2type_map[port_type], module_port, + true, port_big_endian[iport]); /* Update port counter */ port_counter++; @@ -135,20 +135,26 @@ void print_verilog_preconfig_top_module_ports(std::fstream &fp, * The internal wires are tailored for the ports of FPGA top module * which will be different in various configuration protocols *******************************************************************/ -static -void print_verilog_preconfig_top_module_internal_wires(std::fstream &fp, - const ModuleManager &module_manager, - const ModuleId &top_module) { +static void print_verilog_preconfig_top_module_internal_wires( + std::fstream &fp, const ModuleManager &module_manager, + const ModuleId &top_module) { /* Validate the file stream */ valid_file_stream(fp); /* Global ports of top-level module */ - print_verilog_comment(fp, std::string("----- Local wires for FPGA fabric -----")); - for (const ModulePortId &module_port_id : module_manager.module_ports(top_module)) { - BasicPort module_port = module_manager.module_port(top_module, module_port_id); - /* Add a postfix to the internal wires to be different from other reserved ports */ - module_port.set_name(module_port.get_name() + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)); - fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" << std::endl; + print_verilog_comment(fp, + std::string("----- Local wires for FPGA fabric -----")); + for (const ModulePortId &module_port_id : + module_manager.module_ports(top_module)) { + BasicPort module_port = + module_manager.module_port(top_module, module_port_id); + /* Add a postfix to the internal wires to be different from other reserved + * ports */ + module_port.set_name( + module_port.get_name() + + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)); + fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" + << std::endl; } /* Add an empty line as a splitter */ fp << std::endl; @@ -159,37 +165,53 @@ void print_verilog_preconfig_top_module_internal_wires(std::fstream &fp, * 1. operating clock, which should be wired to the clock port of * this pre-configured FPGA top module *******************************************************************/ -static -int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp, - const ModuleManager &module_manager, - const ModuleId &top_module, - const PinConstraints& pin_constraints, - const FabricGlobalPortInfo &fabric_global_ports, - const std::vector &benchmark_clock_port_names) { +static int print_verilog_preconfig_top_module_connect_global_ports( + std::fstream &fp, const ModuleManager &module_manager, + const ModuleId &top_module, const PinConstraints &pin_constraints, + const FabricGlobalPortInfo &fabric_global_ports, + const std::vector &benchmark_clock_port_names) { /* Validate the file stream */ valid_file_stream(fp); - print_verilog_comment(fp, std::string("----- Begin Connect Global ports of FPGA top module -----")); + print_verilog_comment( + fp, + std::string("----- Begin Connect Global ports of FPGA top module -----")); - for (const FabricGlobalPortId& global_port_id : fabric_global_ports.global_ports()) { - ModulePortId module_global_port_id = fabric_global_ports.global_module_port(global_port_id); - VTR_ASSERT(ModuleManager::MODULE_GLOBAL_PORT == module_manager.port_type(top_module, module_global_port_id)); - BasicPort module_global_port = module_manager.module_port(top_module, module_global_port_id); - /* Now, for operating clock port, we should wire it to the clock of benchmark! */ - if ((true == fabric_global_ports.global_port_is_clock(global_port_id)) - && (false == fabric_global_ports.global_port_is_prog(global_port_id))) { - /* Wiring to each pin of the global port: benchmark clock is always 1-bit */ - for (size_t pin_id = 0; pin_id < module_global_port.pins().size(); ++pin_id) { - BasicPort module_clock_pin(module_global_port.get_name() + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), module_global_port.pins()[pin_id], module_global_port.pins()[pin_id]); + for (const FabricGlobalPortId &global_port_id : + fabric_global_ports.global_ports()) { + ModulePortId module_global_port_id = + fabric_global_ports.global_module_port(global_port_id); + VTR_ASSERT(ModuleManager::MODULE_GLOBAL_PORT == + module_manager.port_type(top_module, module_global_port_id)); + BasicPort module_global_port = + module_manager.module_port(top_module, module_global_port_id); + /* Now, for operating clock port, we should wire it to the clock of + * benchmark! */ + if ((true == fabric_global_ports.global_port_is_clock(global_port_id)) && + (false == fabric_global_ports.global_port_is_prog(global_port_id))) { + /* Wiring to each pin of the global port: benchmark clock is always 1-bit + */ + for (size_t pin_id = 0; pin_id < module_global_port.pins().size(); + ++pin_id) { + BasicPort module_clock_pin( + module_global_port.get_name() + + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), + module_global_port.pins()[pin_id], module_global_port.pins()[pin_id]); - /* If the clock port name is in the pin constraints, we should wire it to the constrained pin */ - std::string constrained_net_name = pin_constraints.pin_net(BasicPort(module_global_port.get_name(), module_global_port.pins()[pin_id], module_global_port.pins()[pin_id])); + /* If the clock port name is in the pin constraints, we should wire it + * to the constrained pin */ + std::string constrained_net_name = pin_constraints.pin_net(BasicPort( + module_global_port.get_name(), module_global_port.pins()[pin_id], + module_global_port.pins()[pin_id])); - /* If constrained to an open net or there is no clock in the benchmark, we assign it to a default value */ - if ( (true == pin_constraints.unmapped_net(constrained_net_name)) - || (true == benchmark_clock_port_names.empty())) { - std::vector default_values(1, fabric_global_ports.global_port_default_value(global_port_id)); - print_verilog_wire_constant_values(fp, module_clock_pin, default_values); + /* If constrained to an open net or there is no clock in the benchmark, + * we assign it to a default value */ + if ((true == pin_constraints.unmapped_net(constrained_net_name)) || + (true == benchmark_clock_port_names.empty())) { + std::vector default_values( + 1, fabric_global_ports.global_port_default_value(global_port_id)); + print_verilog_wire_constant_values(fp, module_clock_pin, + default_values); continue; } @@ -197,56 +219,80 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp, if (!pin_constraints.unconstrained_net(constrained_net_name)) { clock_name_to_connect = constrained_net_name; } else { - /* Otherwise, we must have a clear one-to-one clock net corresponding!!! */ - if (benchmark_clock_port_names.size() != module_global_port.get_width()) { - VTR_LOG_ERROR("Unable to map %lu benchmark clocks to %lu clock pins of FPGA!\nRequire clear pin constraints!\n", - benchmark_clock_port_names.size(), - module_global_port.get_width()); + /* Otherwise, we must have a clear one-to-one clock net + * corresponding!!! */ + if (benchmark_clock_port_names.size() != + module_global_port.get_width()) { + VTR_LOG_ERROR( + "Unable to map %lu benchmark clocks to %lu clock pins of " + "FPGA!\nRequire clear pin constraints!\n", + benchmark_clock_port_names.size(), + module_global_port.get_width()); return CMD_EXEC_FATAL_ERROR; } - clock_name_to_connect = benchmark_clock_port_names[pin_id]; + clock_name_to_connect = benchmark_clock_port_names[pin_id]; } BasicPort benchmark_clock_pin(clock_name_to_connect, 1); - print_verilog_wire_connection(fp, module_clock_pin, benchmark_clock_pin, false); + print_verilog_wire_connection(fp, module_clock_pin, benchmark_clock_pin, + false); } /* Finish, go to the next */ continue; } /* For other ports, give an default value */ - for (size_t pin_id = 0; pin_id < module_global_port.pins().size(); ++pin_id) { + for (size_t pin_id = 0; pin_id < module_global_port.pins().size(); + ++pin_id) { BasicPort module_global_pin(module_global_port.get_name(), module_global_port.pins()[pin_id], module_global_port.pins()[pin_id]); - /* If the global port name is in the pin constraints, we should wire it to the constrained pin */ - std::string constrained_net_name = pin_constraints.pin_net(module_global_pin); + /* If the global port name is in the pin constraints, we should wire it to + * the constrained pin */ + std::string constrained_net_name = + pin_constraints.pin_net(module_global_pin); - module_global_pin.set_name(module_global_port.get_name() + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)); + module_global_pin.set_name( + module_global_port.get_name() + + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)); - /* - If constrained to a given net in the benchmark, we connect the global pin to the net - * - If constrained to an open net in the benchmark, we assign it to a default value + /* - If constrained to a given net in the benchmark, we connect the global + * pin to the net + * - If constrained to an open net in the benchmark, we assign it to a + * default value */ - if ( (false == pin_constraints.unconstrained_net(constrained_net_name)) - && (false == pin_constraints.unmapped_net(constrained_net_name))) { + if ((false == pin_constraints.unconstrained_net(constrained_net_name)) && + (false == pin_constraints.unmapped_net(constrained_net_name))) { BasicPort benchmark_pin(constrained_net_name, 1); - print_verilog_wire_connection(fp, module_global_pin, benchmark_pin, false); + print_verilog_wire_connection(fp, module_global_pin, benchmark_pin, + false); } else { - VTR_ASSERT_SAFE(std::string(PIN_CONSTRAINT_OPEN_NET) == constrained_net_name); - std::vector default_values(module_global_pin.get_width(), fabric_global_ports.global_port_default_value(global_port_id)); - /* For configuration done signals, we should enable them in preconfigured wrapper */ + VTR_ASSERT_SAFE(std::string(PIN_CONSTRAINT_OPEN_NET) == + constrained_net_name); + std::vector default_values( + module_global_pin.get_width(), + fabric_global_ports.global_port_default_value(global_port_id)); + /* For configuration done signals, we should enable them in + * preconfigured wrapper */ if (fabric_global_ports.global_port_is_config_enable(global_port_id)) { - VTR_LOG("Config-enable port '%s' is detected with default value '%ld'", module_global_pin.get_name().c_str(), fabric_global_ports.global_port_default_value(global_port_id)); + VTR_LOG( + "Config-enable port '%s' is detected with default value '%ld'", + module_global_pin.get_name().c_str(), + fabric_global_ports.global_port_default_value(global_port_id)); default_values.clear(); - default_values.resize(module_global_pin.get_width(), 1 - fabric_global_ports.global_port_default_value(global_port_id)); + default_values.resize( + module_global_pin.get_width(), + 1 - fabric_global_ports.global_port_default_value(global_port_id)); } - print_verilog_wire_constant_values(fp, module_global_pin, default_values); + print_verilog_wire_constant_values(fp, module_global_pin, + default_values); } } } - print_verilog_comment(fp, std::string("----- End Connect Global ports of FPGA top module -----")); + print_verilog_comment( + fp, std::string("----- End Connect Global ports of FPGA top module -----")); /* Add an empty line as a splitter */ fp << std::endl; @@ -259,16 +305,16 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp, * This function uses 'assign' syntax to impost the bitstream at mem port * while uses 'force' syntax to impost the bitstream at mem_inv port *******************************************************************/ -static -void print_verilog_preconfig_top_module_force_bitstream(std::fstream &fp, - const ModuleManager &module_manager, - const ModuleId &top_module, - const BitstreamManager &bitstream_manager, - const bool& output_datab_bits) { +static void print_verilog_preconfig_top_module_force_bitstream( + std::fstream &fp, const ModuleManager &module_manager, + const ModuleId &top_module, const BitstreamManager &bitstream_manager, + const bool &output_datab_bits) { /* Validate the file stream */ valid_file_stream(fp); - print_verilog_comment(fp, std::string("----- Begin assign bitstream to configuration memories -----")); + print_verilog_comment( + fp, std::string( + "----- Begin assign bitstream to configuration memories -----")); fp << "initial begin" << std::endl; @@ -278,10 +324,15 @@ void print_verilog_preconfig_top_module_force_bitstream(std::fstream &fp, continue; } /* Build the hierarchical path of the configuration bit in modules */ - std::vector block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id); - /* Drop the first block, which is the top module, it should be replaced by the instance name here */ + std::vector block_hierarchy = + find_bitstream_manager_block_hierarchy(bitstream_manager, + config_block_id); + /* Drop the first block, which is the top module, it should be replaced by + * the instance name here */ /* Ensure that this is the module we want to drop! */ - VTR_ASSERT(0 == module_manager.module_name(top_module).compare(bitstream_manager.block_name(block_hierarchy[0]))); + VTR_ASSERT(0 == + module_manager.module_name(top_module) + .compare(bitstream_manager.block_name(block_hierarchy[0]))); block_hierarchy.erase(block_hierarchy.begin()); /* Build the full hierarchy path */ std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME); @@ -292,48 +343,58 @@ void print_verilog_preconfig_top_module_force_bitstream(std::fstream &fp, bit_hierarchy_path += std::string("."); /* Find the bit index in the parent block */ - BasicPort config_data_port(bit_hierarchy_path + generate_configurable_memory_data_out_name(), - bitstream_manager.block_bits(config_block_id).size()); + BasicPort config_data_port( + bit_hierarchy_path + generate_configurable_memory_data_out_name(), + bitstream_manager.block_bits(config_block_id).size()); - /* Wire it to the configuration bit: access both data out and data outb ports */ + /* Wire it to the configuration bit: access both data out and data outb + * ports */ std::vector config_data_values; - for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id)) { + for (const ConfigBitId config_bit : + bitstream_manager.block_bits(config_block_id)) { config_data_values.push_back(bitstream_manager.bit_value(config_bit)); } - print_verilog_force_wire_constant_values(fp, config_data_port, config_data_values); + print_verilog_force_wire_constant_values(fp, config_data_port, + config_data_values); if (true == output_datab_bits) { /* Find the bit index in the parent block */ - BasicPort config_datab_port(bit_hierarchy_path + generate_configurable_memory_inverted_data_out_name(), - bitstream_manager.block_bits(config_block_id).size()); + BasicPort config_datab_port( + bit_hierarchy_path + + generate_configurable_memory_inverted_data_out_name(), + bitstream_manager.block_bits(config_block_id).size()); std::vector config_datab_values; - for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id)) { + for (const ConfigBitId config_bit : + bitstream_manager.block_bits(config_block_id)) { config_datab_values.push_back(!bitstream_manager.bit_value(config_bit)); } - print_verilog_force_wire_constant_values(fp, config_datab_port, config_datab_values); + print_verilog_force_wire_constant_values(fp, config_datab_port, + config_datab_values); } } fp << "end" << std::endl; - print_verilog_comment(fp, std::string("----- End assign bitstream to configuration memories -----")); + print_verilog_comment( + fp, + std::string("----- End assign bitstream to configuration memories -----")); } /******************************************************************** * Impose the bitstream on the configuration memories * This function uses '$deposit' syntax to do so *******************************************************************/ -static -void print_verilog_preconfig_top_module_deposit_bitstream(std::fstream &fp, - const ModuleManager &module_manager, - const ModuleId &top_module, - const BitstreamManager &bitstream_manager, - const bool& output_datab_bits) { +static void print_verilog_preconfig_top_module_deposit_bitstream( + std::fstream &fp, const ModuleManager &module_manager, + const ModuleId &top_module, const BitstreamManager &bitstream_manager, + const bool &output_datab_bits) { /* Validate the file stream */ valid_file_stream(fp); - print_verilog_comment(fp, std::string("----- Begin deposit bitstream to configuration memories -----")); + print_verilog_comment( + fp, std::string( + "----- Begin deposit bitstream to configuration memories -----")); fp << "initial begin" << std::endl; @@ -343,10 +404,15 @@ void print_verilog_preconfig_top_module_deposit_bitstream(std::fstream &fp, continue; } /* Build the hierarchical path of the configuration bit in modules */ - std::vector block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id); - /* Drop the first block, which is the top module, it should be replaced by the instance name here */ + std::vector block_hierarchy = + find_bitstream_manager_block_hierarchy(bitstream_manager, + config_block_id); + /* Drop the first block, which is the top module, it should be replaced by + * the instance name here */ /* Ensure that this is the module we want to drop! */ - VTR_ASSERT(0 == module_manager.module_name(top_module).compare(bitstream_manager.block_name(block_hierarchy[0]))); + VTR_ASSERT(0 == + module_manager.module_name(top_module) + .compare(bitstream_manager.block_name(block_hierarchy[0]))); block_hierarchy.erase(block_hierarchy.begin()); /* Build the full hierarchy path */ std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME); @@ -357,35 +423,44 @@ void print_verilog_preconfig_top_module_deposit_bitstream(std::fstream &fp, bit_hierarchy_path += std::string("."); /* Find the bit index in the parent block */ - BasicPort config_data_port(bit_hierarchy_path + generate_configurable_memory_data_out_name(), - bitstream_manager.block_bits(config_block_id).size()); + BasicPort config_data_port( + bit_hierarchy_path + generate_configurable_memory_data_out_name(), + bitstream_manager.block_bits(config_block_id).size()); - /* Wire it to the configuration bit: access both data out and data outb ports */ + /* Wire it to the configuration bit: access both data out and data outb + * ports */ std::vector config_data_values; - for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id)) { + for (const ConfigBitId config_bit : + bitstream_manager.block_bits(config_block_id)) { config_data_values.push_back(bitstream_manager.bit_value(config_bit)); } - print_verilog_deposit_wire_constant_values(fp, config_data_port, config_data_values); + print_verilog_deposit_wire_constant_values(fp, config_data_port, + config_data_values); /* Skip datab ports if specified */ if (false == output_datab_bits) { continue; } - BasicPort config_datab_port(bit_hierarchy_path + generate_configurable_memory_inverted_data_out_name(), - bitstream_manager.block_bits(config_block_id).size()); - + BasicPort config_datab_port( + bit_hierarchy_path + + generate_configurable_memory_inverted_data_out_name(), + bitstream_manager.block_bits(config_block_id).size()); std::vector config_datab_values; - for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id)) { + for (const ConfigBitId config_bit : + bitstream_manager.block_bits(config_block_id)) { config_datab_values.push_back(!bitstream_manager.bit_value(config_bit)); } - print_verilog_deposit_wire_constant_values(fp, config_datab_port, config_datab_values); + print_verilog_deposit_wire_constant_values(fp, config_datab_port, + config_datab_values); } fp << "end" << std::endl; - print_verilog_comment(fp, std::string("----- End deposit bitstream to configuration memories -----")); + print_verilog_comment( + fp, + std::string("----- End deposit bitstream to configuration memories -----")); } /******************************************************************** @@ -394,41 +469,41 @@ void print_verilog_preconfig_top_module_deposit_bitstream(std::fstream &fp, * 1. iVerilog Icarus prefers using 'assign' syntax to force the values * 2. Mentor Modelsim prefers using '$deposit' syntax to do so *******************************************************************/ -static -void print_verilog_preconfig_top_module_load_bitstream(std::fstream &fp, - const ModuleManager &module_manager, - const ModuleId &top_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& mem_model, - const BitstreamManager &bitstream_manager, - const e_embedded_bitstream_hdl_type& embedded_bitstream_hdl_type) { - +static void print_verilog_preconfig_top_module_load_bitstream( + std::fstream &fp, const ModuleManager &module_manager, + const ModuleId &top_module, const CircuitLibrary &circuit_lib, + const CircuitModelId &mem_model, const BitstreamManager &bitstream_manager, + const e_embedded_bitstream_hdl_type &embedded_bitstream_hdl_type) { /* Skip the datab port if there is only 1 output port in memory model - * Currently, it assumes that the data output port is always defined while datab is optional - * If we see only 1 port, we assume datab is not defined by default. - * TODO: this switch could be smarter: it should identify if only data or datab - * ports are defined. + * Currently, it assumes that the data output port is always defined while + * datab is optional If we see only 1 port, we assume datab is not defined by + * default. + * TODO: this switch could be smarter: it should identify if only data or + * datab ports are defined. */ bool output_datab_bits = true; - if (1 == circuit_lib.model_ports_by_type(mem_model, CIRCUIT_MODEL_PORT_OUTPUT).size()) { + if (1 == circuit_lib.model_ports_by_type(mem_model, CIRCUIT_MODEL_PORT_OUTPUT) + .size()) { output_datab_bits = false; } - print_verilog_comment(fp, std::string("----- Begin load bitstream to configuration memories -----")); + print_verilog_comment( + fp, + std::string("----- Begin load bitstream to configuration memories -----")); /* Use assign syntax for Icarus simulator */ if (EMBEDDED_BITSTREAM_HDL_IVERILOG == embedded_bitstream_hdl_type) { - print_verilog_preconfig_top_module_force_bitstream(fp, module_manager, top_module, - bitstream_manager, - output_datab_bits); - /* Use deposit syntax for other simulators */ + print_verilog_preconfig_top_module_force_bitstream( + fp, module_manager, top_module, bitstream_manager, output_datab_bits); + /* Use deposit syntax for other simulators */ } else if (EMBEDDED_BITSTREAM_HDL_MODELSIM == embedded_bitstream_hdl_type) { - print_verilog_preconfig_top_module_deposit_bitstream(fp, module_manager, top_module, - bitstream_manager, - output_datab_bits); + print_verilog_preconfig_top_module_deposit_bitstream( + fp, module_manager, top_module, bitstream_manager, output_datab_bits); } - print_verilog_comment(fp, std::string("----- End load bitstream to configuration memories -----")); + print_verilog_comment( + fp, + std::string("----- End load bitstream to configuration memories -----")); } /******************************************************************** @@ -463,21 +538,20 @@ void print_verilog_preconfig_top_module_load_bitstream(std::fstream &fp, * It includes wires to force constant values to part of FPGA datapath I/Os * All these are hard to implement as a module in module manager *******************************************************************/ -int print_verilog_preconfig_top_module(const ModuleManager &module_manager, - const BitstreamManager &bitstream_manager, - const ConfigProtocol &config_protocol, - const CircuitLibrary &circuit_lib, - const FabricGlobalPortInfo &global_ports, - const AtomContext &atom_ctx, - const PlacementContext &place_ctx, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const IoLocationMap &io_location_map, - const VprNetlistAnnotation &netlist_annotation, - const std::string &circuit_name, - const std::string &verilog_fname, - const VerilogTestbenchOption& options) { - std::string timer_message = std::string("Write pre-configured FPGA top-level Verilog netlist for design '") + circuit_name + std::string("'"); +int print_verilog_preconfig_top_module( + const ModuleManager &module_manager, + const BitstreamManager &bitstream_manager, + const ConfigProtocol &config_protocol, const CircuitLibrary &circuit_lib, + const FabricGlobalPortInfo &global_ports, const AtomContext &atom_ctx, + const PlacementContext &place_ctx, const PinConstraints &pin_constraints, + const BusGroup &bus_group, const IoLocationMap &io_location_map, + const VprNetlistAnnotation &netlist_annotation, + const std::string &circuit_name, const std::string &verilog_fname, + const VerilogTestbenchOption &options) { + std::string timer_message = + std::string( + "Write pre-configured FPGA top-level Verilog netlist for design '") + + circuit_name + std::string("'"); int status = CMD_EXEC_SUCCESS; @@ -492,74 +566,78 @@ int print_verilog_preconfig_top_module(const ModuleManager &module_manager, check_file_stream(verilog_fname.c_str(), fp); /* Generate a brief description on the Verilog file*/ - std::string title = std::string("Verilog netlist for pre-configured FPGA fabric by design: ") + circuit_name; + std::string title = + std::string("Verilog netlist for pre-configured FPGA fabric by design: ") + + circuit_name; print_verilog_file_header(fp, title, options.time_stamp()); - print_verilog_default_net_type_declaration(fp, - options.default_net_type()); + print_verilog_default_net_type_declaration(fp, options.default_net_type()); /* Print module declaration and ports */ - print_verilog_preconfig_top_module_ports(fp, circuit_name, atom_ctx, netlist_annotation, bus_group); + print_verilog_preconfig_top_module_ports(fp, circuit_name, atom_ctx, + netlist_annotation, bus_group); /* Find the top_module */ - ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name()); + ModuleId top_module = + module_manager.find_module(generate_fpga_top_module_name()); VTR_ASSERT(true == module_manager.valid_module_id(top_module)); /* Print internal wires */ - print_verilog_preconfig_top_module_internal_wires(fp, module_manager, top_module); + print_verilog_preconfig_top_module_internal_wires(fp, module_manager, + top_module); /* Instanciate FPGA top-level module */ - print_verilog_testbench_fpga_instance(fp, module_manager, top_module, - std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME), - std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), - options.explicit_port_mapping()); + print_verilog_testbench_fpga_instance( + fp, module_manager, top_module, + std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME), + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), + options.explicit_port_mapping()); /* Find clock ports in benchmark */ - std::vector benchmark_clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); + std::vector benchmark_clock_port_names = + find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); - /* Connect FPGA top module global ports to constant or benchmark global signals! */ - status = print_verilog_preconfig_top_module_connect_global_ports(fp, module_manager, top_module, - pin_constraints, global_ports, - benchmark_clock_port_names); + /* Connect FPGA top module global ports to constant or benchmark global + * signals! */ + status = print_verilog_preconfig_top_module_connect_global_ports( + fp, module_manager, top_module, pin_constraints, global_ports, + benchmark_clock_port_names); if (CMD_EXEC_FATAL_ERROR == status) { return status; } /* Connect I/Os to benchmark I/Os or constant driver */ - print_verilog_testbench_connect_fpga_ios(fp, module_manager, top_module, - atom_ctx, place_ctx, io_location_map, - netlist_annotation, - bus_group, - std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), - std::string(), - std::string(), - std::vector(), - (size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE); + print_verilog_testbench_connect_fpga_ios( + fp, module_manager, top_module, atom_ctx, place_ctx, io_location_map, + netlist_annotation, bus_group, + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), std::string(), + std::string(), std::vector(), + (size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE); /* Assign the SRAM model applied to the FPGA fabric */ - CircuitModelId sram_model = config_protocol.memory_model(); + CircuitModelId sram_model = config_protocol.memory_model(); VTR_ASSERT(true == circuit_lib.valid_model_id(sram_model)); - /* Assign FPGA internal SRAM/Memory ports to bitstream values, only output when needed */ - print_verilog_preconfig_top_module_load_bitstream(fp, module_manager, top_module, - circuit_lib, sram_model, - bitstream_manager, - options.embedded_bitstream_hdl_type()); + /* Assign FPGA internal SRAM/Memory ports to bitstream values, only output + * when needed */ + print_verilog_preconfig_top_module_load_bitstream( + fp, module_manager, top_module, circuit_lib, sram_model, bitstream_manager, + options.embedded_bitstream_hdl_type()); - /* Add signal initialization: - * Bypass writing codes to files due to the autogenerated codes are very large. + /* Add signal initialization: + * Bypass writing codes to files due to the autogenerated codes are very + * large. */ if (true == options.include_signal_init()) { - print_verilog_testbench_signal_initialization(fp, - std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME), - circuit_lib, - module_manager, - top_module, - false); + print_verilog_testbench_signal_initialization( + fp, std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME), circuit_lib, + module_manager, top_module, false); } /* Testbench ends*/ - print_verilog_module_end(fp, std::string(circuit_name) + std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX)); + print_verilog_module_end( + fp, std::string(circuit_name) + + std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX)); /* Close the file stream */ fp.close(); diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h index 39e1d9f28..a309f9fae 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h @@ -4,19 +4,20 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include #include -#include "circuit_library.h" -#include "vpr_context.h" -#include "module_manager.h" +#include + #include "bitstream_manager.h" -#include "pin_constraints.h" -#include "io_location_map.h" -#include "fabric_global_port_info.h" -#include "config_protocol.h" #include "bus_group.h" -#include "vpr_netlist_annotation.h" +#include "circuit_library.h" +#include "config_protocol.h" +#include "fabric_global_port_info.h" +#include "io_location_map.h" +#include "module_manager.h" +#include "pin_constraints.h" #include "verilog_testbench_options.h" +#include "vpr_context.h" +#include "vpr_netlist_annotation.h" /******************************************************************** * Function declaration @@ -25,20 +26,16 @@ /* begin namespace openfpga */ namespace openfpga { -int print_verilog_preconfig_top_module(const ModuleManager& module_manager, - const BitstreamManager& bitstream_manager, - const ConfigProtocol &config_protocol, - const CircuitLibrary& circuit_lib, - const FabricGlobalPortInfo &global_ports, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const IoLocationMap& io_location_map, - const VprNetlistAnnotation& netlist_annotation, - const std::string& circuit_name, - const std::string& verilog_fname, - const VerilogTestbenchOption& options); +int print_verilog_preconfig_top_module( + const ModuleManager& module_manager, + const BitstreamManager& bitstream_manager, + const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib, + const FabricGlobalPortInfo& global_ports, const AtomContext& atom_ctx, + const PlacementContext& place_ctx, const PinConstraints& pin_constraints, + const BusGroup& bus_group, const IoLocationMap& io_location_map, + const VprNetlistAnnotation& netlist_annotation, + const std::string& circuit_name, const std::string& verilog_fname, + const VerilogTestbenchOption& options); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_routing.cpp b/openfpga/src/fpga_verilog/verilog_routing.cpp index babf96ac0..fe93a9fd4 100644 --- a/openfpga/src/fpga_verilog/verilog_routing.cpp +++ b/openfpga/src/fpga_verilog/verilog_routing.cpp @@ -1,11 +1,11 @@ /********************************************************************* - * This file includes functions that are used for - * Verilog generation of FPGA routing architecture (global routing) + * This file includes functions that are used for + * Verilog generation of FPGA routing architecture (global routing) *********************************************************************/ /* Headers from vtrutil library */ #include "vtr_assert.h" -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from openfpgautil library */ #include "openfpga_digest.h" @@ -13,23 +13,23 @@ /* Include FPGA-Verilog header files*/ #include "openfpga_naming.h" #include "verilog_constants.h" -#include "verilog_writer_utils.h" #include "verilog_module_writer.h" #include "verilog_routing.h" +#include "verilog_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { -/******************************************************************** +/******************************************************************** * Print the sub-circuit of a connection Box (Type: [CHANX|CHANY]) * Actually it is very similiar to switch box but * the difference is connection boxes connect Grid INPUT Pins to channels * NOTE: direct connection between CLBs should NOT be included inside this - * module! They should be added in the top-level module as their connection - * is not limited to adjacent CLBs!!! + * module! They should be added in the top-level module as their + *connection is not limited to adjacent CLBs!!! * * Location of a X- and Y-direction Connection Block in FPGA fabric - * +------------+ +-------------+ + * +------------+ +-------------+ * | |------>| | * | CLB |<------| Y-direction | * | | ... | Connection | @@ -39,15 +39,16 @@ namespace openfpga { * v | v v | v * +-------------------+ +-------------+ * --->| |--->| | - * <---| X-direction |<---| Switch | + * <---| X-direction |<---| Switch | * ...| Connection block |... | Block | * --->| |--->| | * +-------------------+ +-------------+ * * Internal structure: - * This is an example of a X-direction connection block - * Note that middle output ports are shorted wire from inputs of routing tracks, - * which are also the inputs of routing multiplexer of the connection block + * This is an example of a X-direction connection block + * Note that middle output ports are shorted wire from inputs of routing + *tracks, which are also the inputs of routing multiplexer of the connection + *block * * CLB Input Pins * (IPINs) @@ -55,11 +56,11 @@ namespace openfpga { * | | ... | * +--------------------------+ * | ^ ^ ^ | - * | | | ... | | - * | +--------------------+ | + * | | | ... | | + * | +--------------------+ | * | | routing | | * | | multiplexers | | - * | +--------------------+ | + * | +--------------------+ | * | middle outputs | * | of routing channel | * | ^ ^ ^ ^ ^ ^ ^ ^ | @@ -72,19 +73,18 @@ namespace openfpga { * +--------------------------+ * * W: routing channel width - * + * ********************************************************************/ -static -void print_verilog_routing_connection_box_unique_module(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const std::string& subckt_dir, - const std::string& subckt_dir_name, - const RRGSB& rr_gsb, - const t_rr_type& cb_type, - const FabricVerilogOption& options) { +static void print_verilog_routing_connection_box_unique_module( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const std::string& subckt_dir, const std::string& subckt_dir_name, + const RRGSB& rr_gsb, const t_rr_type& cb_type, + const FabricVerilogOption& options) { /* Create the netlist */ - vtr::Point gsb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); - std::string verilog_fname(generate_connection_block_netlist_name(cb_type, gsb_coordinate, std::string(VERILOG_NETLIST_FILE_POSTFIX))); + vtr::Point gsb_coordinate(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); + std::string verilog_fname(generate_connection_block_netlist_name( + cb_type, gsb_coordinate, std::string(VERILOG_NETLIST_FILE_POSTFIX))); std::string verilog_fpath(subckt_dir + verilog_fname); /* Create the file stream */ @@ -93,20 +93,24 @@ void print_verilog_routing_connection_box_unique_module(NetlistManager& netlist_ check_file_stream(verilog_fpath.c_str(), fp); - print_verilog_file_header(fp, - std::string("Verilog modules for Unique Connection Blocks[" + std::to_string(rr_gsb.get_cb_x(cb_type)) + "]["+ std::to_string(rr_gsb.get_cb_y(cb_type)) + "]"), - options.time_stamp()); + print_verilog_file_header( + fp, + std::string("Verilog modules for Unique Connection Blocks[" + + std::to_string(rr_gsb.get_cb_x(cb_type)) + "][" + + std::to_string(rr_gsb.get_cb_y(cb_type)) + "]"), + options.time_stamp()); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId cb_module = module_manager.find_module(generate_connection_block_module_name(cb_type, gsb_coordinate)); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId cb_module = module_manager.find_module( + generate_connection_block_module_name(cb_type, gsb_coordinate)); VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); /* Write the verilog module */ - write_verilog_module_to_file(fp, - module_manager, cb_module, + write_verilog_module_to_file(fp, module_manager, cb_module, options.explicit_port_mapping(), options.default_net_type()); - + /* Add an empty line as a splitter */ fp << std::endl; @@ -121,13 +125,14 @@ void print_verilog_routing_connection_box_unique_module(NetlistManager& netlist_ nlist_id = netlist_manager.add_netlist(verilog_fpath); } VTR_ASSERT(nlist_id); - netlist_manager.set_netlist_type(nlist_id, NetlistManager::ROUTING_MODULE_NETLIST); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::ROUTING_MODULE_NETLIST); } /********************************************************************* * Generate the Verilog module for a Switch Box. * A Switch Box module consists of following ports: - * 1. Channel Y [x][y] inputs + * 1. Channel Y [x][y] inputs * 2. Channel X [x+1][y] inputs * 3. Channel Y [x][y-1] outputs * 4. Channel X [x][y] outputs @@ -149,7 +154,7 @@ void print_verilog_routing_connection_box_unique_module(NetlistManager& netlist_ * | | | | * -------------- -------------- * ---------- - * ChanX | Switch | ChanX + * ChanX | Switch | ChanX * [x][y] | Box | [x+1][y] * | [x][y] | * ---------- @@ -162,41 +167,37 @@ void print_verilog_routing_connection_box_unique_module(NetlistManager& netlist_ * * Switch Block pin location map * - * Grid[x][y+1] ChanY[x][y+1] Grid[x+1][y+1] + * Grid[x][y+1] ChanY[x][y+1] Grid[x+1][y+1] * right_pins inputs/outputs left_pins * | ^ | * | | | * v v v * +-----------------------------------------------+ * | | - * Grid[x][y+1] | | Grid[x+1][y+1] - * bottom_pins---->| |<---- bottom_pins - * | | - * ChanX[x][y] | Switch Box [x][y] | ChanX[x+1][y] - * inputs/outputs<--->| |<---> inputs/outputs - * | | - * Grid[x][y+1] | | Grid[x+1][y+1] - * top_pins---->| |<---- top_pins - * | | + * Grid[x][y+1] | | + *Grid[x+1][y+1] bottom_pins---->| |<---- bottom_pins | | ChanX[x][y] | + *Switch Box [x][y] | ChanX[x+1][y] inputs/outputs<--->| + *|<---> inputs/outputs | | + * Grid[x][y+1] | | + *Grid[x+1][y+1] top_pins---->| |<---- top_pins | | * +-----------------------------------------------+ * ^ ^ ^ * | | | * | v | - * Grid[x][y] ChanY[x][y] Grid[x+1][y] + * Grid[x][y] ChanY[x][y] Grid[x+1][y] * right_pins inputs/outputs left_pins * * ********************************************************************/ -static -void print_verilog_routing_switch_box_unique_module(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const std::string& subckt_dir, - const std::string& subckt_dir_name, - const RRGSB& rr_gsb, - const FabricVerilogOption& options) { +static void print_verilog_routing_switch_box_unique_module( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const std::string& subckt_dir, const std::string& subckt_dir_name, + const RRGSB& rr_gsb, const FabricVerilogOption& options) { /* Create the netlist */ vtr::Point gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); - std::string verilog_fname(generate_routing_block_netlist_name(SB_VERILOG_FILE_NAME_PREFIX, gsb_coordinate, std::string(VERILOG_NETLIST_FILE_POSTFIX))); + std::string verilog_fname(generate_routing_block_netlist_name( + SB_VERILOG_FILE_NAME_PREFIX, gsb_coordinate, + std::string(VERILOG_NETLIST_FILE_POSTFIX))); std::string verilog_fpath(subckt_dir + verilog_fname); /* Create the file stream */ @@ -205,21 +206,24 @@ void print_verilog_routing_switch_box_unique_module(NetlistManager& netlist_mana check_file_stream(verilog_fpath.c_str(), fp); - print_verilog_file_header(fp, - std::string("Verilog modules for Unique Switch Blocks[" + std::to_string(rr_gsb.get_sb_x()) + "]["+ std::to_string(rr_gsb.get_sb_y()) + "]"), - options.time_stamp()); + print_verilog_file_header( + fp, + std::string("Verilog modules for Unique Switch Blocks[" + + std::to_string(rr_gsb.get_sb_x()) + "][" + + std::to_string(rr_gsb.get_sb_y()) + "]"), + options.time_stamp()); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId sb_module = module_manager.find_module(generate_switch_block_module_name(gsb_coordinate)); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId sb_module = module_manager.find_module( + generate_switch_block_module_name(gsb_coordinate)); VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); /* Write the verilog module */ - write_verilog_module_to_file(fp, - module_manager, - sb_module, + write_verilog_module_to_file(fp, module_manager, sb_module, options.explicit_port_mapping(), options.default_net_type()); - + /* Close file handler */ fp.close(); @@ -231,40 +235,35 @@ void print_verilog_routing_switch_box_unique_module(NetlistManager& netlist_mana nlist_id = netlist_manager.add_netlist(verilog_fpath); } VTR_ASSERT(nlist_id); - netlist_manager.set_netlist_type(nlist_id, NetlistManager::ROUTING_MODULE_NETLIST); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::ROUTING_MODULE_NETLIST); } /******************************************************************** * Iterate over all the connection blocks in a device - * and build a module for each of them + * and build a module for each of them *******************************************************************/ -static -void print_verilog_flatten_connection_block_modules(NetlistManager& netlist_manager, - const ModuleManager& module_manager, - const DeviceRRGSB& device_rr_gsb, - const std::string& subckt_dir, - const std::string& subckt_dir_name, - const t_rr_type& cb_type, - const FabricVerilogOption& options) { +static void print_verilog_flatten_connection_block_modules( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const DeviceRRGSB& device_rr_gsb, const std::string& subckt_dir, + const std::string& subckt_dir_name, const t_rr_type& cb_type, + const FabricVerilogOption& options) { /* Build unique X-direction connection block modules */ vtr::Point cb_range = device_rr_gsb.get_gsb_range(); for (size_t ix = 0; ix < cb_range.x(); ++ix) { for (size_t iy = 0; iy < cb_range.y(); ++iy) { /* Check if the connection block exists in the device! - * Some of them do NOT exist due to heterogeneous blocks (height > 1) + * Some of them do NOT exist due to heterogeneous blocks (height > 1) * We will skip those modules */ const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); if (true != rr_gsb.is_cb_exist(cb_type)) { continue; } - print_verilog_routing_connection_box_unique_module(netlist_manager, - module_manager, - subckt_dir, - subckt_dir_name, - rr_gsb, cb_type, - options); + print_verilog_routing_connection_box_unique_module( + netlist_manager, module_manager, subckt_dir, subckt_dir_name, rr_gsb, + cb_type, options); } } } @@ -284,7 +283,8 @@ void print_verilog_flatten_routing_modules(NetlistManager& netlist_manager, const std::string& subckt_dir, const std::string& subckt_dir_name, const FabricVerilogOption& options) { - /* Create a vector to contain all the Verilog netlist names that have been generated in this function */ + /* Create a vector to contain all the Verilog netlist names that have been + * generated in this function */ std::vector netlist_names; vtr::Point sb_range = device_rr_gsb.get_gsb_range(); @@ -296,41 +296,29 @@ void print_verilog_flatten_routing_modules(NetlistManager& netlist_manager, if (true != rr_gsb.is_sb_exist()) { continue; } - print_verilog_routing_switch_box_unique_module(netlist_manager, - module_manager, - subckt_dir, - subckt_dir_name, - rr_gsb, - options); + print_verilog_routing_switch_box_unique_module( + netlist_manager, module_manager, subckt_dir, subckt_dir_name, rr_gsb, + options); } } - print_verilog_flatten_connection_block_modules(netlist_manager, - module_manager, - device_rr_gsb, - subckt_dir, - subckt_dir_name, - CHANX, - options); + print_verilog_flatten_connection_block_modules( + netlist_manager, module_manager, device_rr_gsb, subckt_dir, subckt_dir_name, + CHANX, options); - print_verilog_flatten_connection_block_modules(netlist_manager, - module_manager, - device_rr_gsb, - subckt_dir, - subckt_dir_name, - CHANY, - options); + print_verilog_flatten_connection_block_modules( + netlist_manager, module_manager, device_rr_gsb, subckt_dir, subckt_dir_name, + CHANY, options); } - /******************************************************************** * A top-level function of this file * Print all the unique modules for global routing architecture of a FPGA fabric - * in Verilog format, including: + * in Verilog format, including: * 1. Connection blocks * 2. Switch blocks * - * Note: this function SHOULD be called only when + * Note: this function SHOULD be called only when * the option compact_routing_hierarchy is turned on!!! *******************************************************************/ void print_verilog_unique_routing_modules(NetlistManager& netlist_manager, @@ -339,42 +327,36 @@ void print_verilog_unique_routing_modules(NetlistManager& netlist_manager, const std::string& subckt_dir, const std::string& subckt_dir_name, const FabricVerilogOption& options) { - /* Create a vector to contain all the Verilog netlist names that have been generated in this function */ + /* Create a vector to contain all the Verilog netlist names that have been + * generated in this function */ std::vector netlist_names; /* Build unique switch block modules */ for (size_t isb = 0; isb < device_rr_gsb.get_num_sb_unique_module(); ++isb) { const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(isb); - print_verilog_routing_switch_box_unique_module(netlist_manager, - module_manager, - subckt_dir, - subckt_dir_name, - unique_mirror, - options); + print_verilog_routing_switch_box_unique_module( + netlist_manager, module_manager, subckt_dir, subckt_dir_name, + unique_mirror, options); } /* Build unique X-direction connection block modules */ - for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANX); ++icb) { + for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANX); + ++icb) { const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(CHANX, icb); - print_verilog_routing_connection_box_unique_module(netlist_manager, - module_manager, - subckt_dir, - subckt_dir_name, - unique_mirror, CHANX, - options); + print_verilog_routing_connection_box_unique_module( + netlist_manager, module_manager, subckt_dir, subckt_dir_name, + unique_mirror, CHANX, options); } /* Build unique X-direction connection block modules */ - for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANY); ++icb) { + for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANY); + ++icb) { const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(CHANY, icb); - print_verilog_routing_connection_box_unique_module(netlist_manager, - module_manager, - subckt_dir, - subckt_dir_name, - unique_mirror, CHANY, - options); + print_verilog_routing_connection_box_unique_module( + netlist_manager, module_manager, subckt_dir, subckt_dir_name, + unique_mirror, CHANY, options); } VTR_LOG("\n"); diff --git a/openfpga/src/fpga_verilog/verilog_routing.h b/openfpga/src/fpga_verilog/verilog_routing.h index acd61bade..f33c44d43 100644 --- a/openfpga/src/fpga_verilog/verilog_routing.h +++ b/openfpga/src/fpga_verilog/verilog_routing.h @@ -5,11 +5,11 @@ * Include header files that are required by function declaration *******************************************************************/ -#include "mux_library.h" -#include "module_manager.h" -#include "netlist_manager.h" #include "device_rr_gsb.h" #include "fabric_verilog_options.h" +#include "module_manager.h" +#include "mux_library.h" +#include "netlist_manager.h" /******************************************************************** * Function declaration diff --git a/openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp b/openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp index 34fbbc0ab..f2c0e02e6 100644 --- a/openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp +++ b/openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp @@ -1,44 +1,39 @@ /********************************************************************* - * This file includes functions to generate Verilog submodules for + * This file includes functions to generate Verilog submodules for * the memories that are affiliated to multiplexers and other programmable * circuit models, such as IOPADs, LUTs, etc. ********************************************************************/ -#include #include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" #include "vtr_log.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - -#include "mux_graph.h" -#include "module_manager.h" #include "circuit_library_utils.h" +#include "module_manager.h" +#include "mux_graph.h" #include "mux_utils.h" - +#include "openfpga_digest.h" #include "openfpga_naming.h" - #include "verilog_constants.h" -#include "verilog_writer_utils.h" #include "verilog_module_writer.h" #include "verilog_shift_register_banks.h" +#include "verilog_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { /********************************************************************* - * Generate Verilog modules for + * Generate Verilog modules for * the shift register banks that are used to control BL/WLs ********************************************************************/ -void print_verilog_submodule_shift_register_banks(const ModuleManager& module_manager, - NetlistManager& netlist_manager, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const std::string& submodule_dir, - const std::string& submodule_dir_name, - const FabricVerilogOption& options) { - +void print_verilog_submodule_shift_register_banks( + const ModuleManager& module_manager, NetlistManager& netlist_manager, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const std::string& submodule_dir, const std::string& submodule_dir_name, + const FabricVerilogOption& options) { /* Plug in with the mux subckt */ std::string verilog_fname(SHIFT_REGISTER_BANKS_VERILOG_FILE_NAME); std::string verilog_fpath(submodule_dir + verilog_fname); @@ -49,17 +44,19 @@ void print_verilog_submodule_shift_register_banks(const ModuleManager& module_ma check_file_stream(verilog_fpath.c_str(), fp); - /* Print out debugging information for if the file is not opened/created properly */ + /* Print out debugging information for if the file is not opened/created + * properly */ VTR_LOG("Writing Verilog netlist for shift register banks '%s' ...", - verilog_fpath.c_str()); + verilog_fpath.c_str()); - print_verilog_file_header(fp, "Shift register banks used in FPGA", options.time_stamp()); + print_verilog_file_header(fp, "Shift register banks used in FPGA", + options.time_stamp()); /* Create the memory circuits for the multiplexer */ for (const ModuleId& sr_module : blwl_sr_banks.bl_bank_unique_modules()) { VTR_ASSERT(true == module_manager.valid_module_id(sr_module)); /* Write the module content in Verilog format */ - write_verilog_module_to_file(fp, module_manager, sr_module, + write_verilog_module_to_file(fp, module_manager, sr_module, options.explicit_port_mapping(), options.default_net_type()); @@ -70,7 +67,7 @@ void print_verilog_submodule_shift_register_banks(const ModuleManager& module_ma for (const ModuleId& sr_module : blwl_sr_banks.wl_bank_unique_modules()) { VTR_ASSERT(true == module_manager.valid_module_id(sr_module)); /* Write the module content in Verilog format */ - write_verilog_module_to_file(fp, module_manager, sr_module, + write_verilog_module_to_file(fp, module_manager, sr_module, options.explicit_port_mapping(), options.default_net_type()); diff --git a/openfpga/src/fpga_verilog/verilog_shift_register_banks.h b/openfpga/src/fpga_verilog/verilog_shift_register_banks.h index dc880dc69..2a0e25097 100644 --- a/openfpga/src/fpga_verilog/verilog_shift_register_banks.h +++ b/openfpga/src/fpga_verilog/verilog_shift_register_banks.h @@ -6,10 +6,10 @@ *******************************************************************/ #include +#include "fabric_verilog_options.h" #include "memory_bank_shift_register_banks.h" #include "module_manager.h" #include "netlist_manager.h" -#include "fabric_verilog_options.h" /******************************************************************** * Function declaration @@ -18,12 +18,11 @@ /* begin namespace openfpga */ namespace openfpga { -void print_verilog_submodule_shift_register_banks(const ModuleManager& module_manager, - NetlistManager& netlist_manager, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const std::string& submodule_dir, - const std::string& submodule_dir_name, - const FabricVerilogOption& options); +void print_verilog_submodule_shift_register_banks( + const ModuleManager& module_manager, NetlistManager& netlist_manager, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const std::string& submodule_dir, const std::string& submodule_dir_name, + const FabricVerilogOption& options); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_simulation_info_writer.cpp b/openfpga/src/fpga_verilog/verilog_simulation_info_writer.cpp index 7f85918a7..3eb2a209e 100644 --- a/openfpga/src/fpga_verilog/verilog_simulation_info_writer.cpp +++ b/openfpga/src/fpga_verilog/verilog_simulation_info_writer.cpp @@ -1,6 +1,6 @@ /********************************************************************* * This function includes the writer for generating exchangeable - * information, in order to interface different simulators + * information, in order to interface different simulators ********************************************************************/ #include #include @@ -13,14 +13,11 @@ #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_scale.h" #include "openfpga_digest.h" -#include "openfpga_reserved_words.h" - #include "openfpga_naming.h" - +#include "openfpga_reserved_words.h" +#include "openfpga_scale.h" #include "simulation_utils.h" - #include "verilog_constants.h" #include "verilog_simulation_info_writer.h" @@ -31,21 +28,17 @@ namespace openfpga { * Top-level function to write an ini file which contains exchangeable * information, in order to interface different Verilog simulators ********************************************************************/ -void print_verilog_simulation_info(const std::string& ini_fname, - const VerilogTestbenchOption& options, - const std::string& circuit_name, - const std::string& src_dir, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const IoLocationMap& io_location_map, - const ModuleManager& module_manager, - const e_config_protocol_type& config_protocol_type, - const size_t& num_program_clock_cycles, - const int& num_operating_clock_cycles, - const float& prog_clock_freq, - const float& op_clock_freq) { - - std::string timer_message = std::string("Write exchangeable file containing simulation information '") + ini_fname + std::string("'"); +void print_verilog_simulation_info( + const std::string& ini_fname, const VerilogTestbenchOption& options, + const std::string& circuit_name, const std::string& src_dir, + const AtomContext& atom_ctx, const PlacementContext& place_ctx, + const IoLocationMap& io_location_map, const ModuleManager& module_manager, + const e_config_protocol_type& config_protocol_type, + const size_t& num_program_clock_cycles, const int& num_operating_clock_cycles, + const float& prog_clock_freq, const float& op_clock_freq) { + std::string timer_message = + std::string("Write exchangeable file containing simulation information '") + + ini_fname + std::string("'"); std::string ini_dir_path = format_dir_path(find_path_dir_name(ini_fname)); @@ -60,30 +53,30 @@ void print_verilog_simulation_info(const std::string& ini_fname, mINI::INIStructure ini; - /* Compute simulation time period: full testbench and pre-configured testbench has different length - * Currently, we only support the two types. And one of them must be enabled when outputting this file + /* Compute simulation time period: full testbench and pre-configured testbench + * has different length Currently, we only support the two types. And one of + * them must be enabled when outputting this file */ float simulation_time_period = 0.; if (options.print_top_testbench()) { - simulation_time_period = find_simulation_time_period(options.time_unit(), - num_program_clock_cycles, - 1. / prog_clock_freq, - num_operating_clock_cycles, - 1. / op_clock_freq); + simulation_time_period = find_simulation_time_period( + options.time_unit(), num_program_clock_cycles, 1. / prog_clock_freq, + num_operating_clock_cycles, 1. / op_clock_freq); } else { VTR_ASSERT(options.print_preconfig_top_testbench()); - simulation_time_period = find_operating_phase_simulation_time(num_operating_clock_cycles, - 1. / op_clock_freq, - options.time_unit()); + simulation_time_period = find_operating_phase_simulation_time( + num_operating_clock_cycles, 1. / op_clock_freq, options.time_unit()); } /* Identify the testbench file name depending on the type */ std::string top_tb_name; if (options.print_top_testbench()) { - top_tb_name = circuit_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX); + top_tb_name = + circuit_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX); } else { VTR_ASSERT(options.print_preconfig_top_testbench()); - top_tb_name = circuit_name + std::string(FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX); + top_tb_name = + circuit_name + std::string(FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX); } /* Basic information */ @@ -93,51 +86,61 @@ void print_verilog_simulation_info(const std::string& ini_fname, ini["SIMULATION_DECK"]["SIMTIME "] = std::to_string(simulation_time_period); ini["SIMULATION_DECK"]["UNIT "] = unit_to_string(options.time_unit()); ini["SIMULATION_DECK"]["VERILOG_PATH "] = std::string(src_dir); - ini["SIMULATION_DECK"]["VERILOG_FILE1"] = std::string(DEFINES_VERILOG_FILE_NAME); - ini["SIMULATION_DECK"]["VERILOG_FILE2"] = std::string(circuit_name + std::string(TOP_VERILOG_TESTBENCH_INCLUDE_NETLIST_FILE_NAME_POSTFIX)); - ini["SIMULATION_DECK"]["CONFIG_PROTOCOL"] = std::string(CONFIG_PROTOCOL_TYPE_STRING[config_protocol_type]); + ini["SIMULATION_DECK"]["VERILOG_FILE1"] = + std::string(DEFINES_VERILOG_FILE_NAME); + ini["SIMULATION_DECK"]["VERILOG_FILE2"] = std::string( + circuit_name + + std::string(TOP_VERILOG_TESTBENCH_INCLUDE_NETLIST_FILE_NAME_POSTFIX)); + ini["SIMULATION_DECK"]["CONFIG_PROTOCOL"] = + std::string(CONFIG_PROTOCOL_TYPE_STRING[config_protocol_type]); /* Information required by UVM */ if (CONFIG_MEM_FRAME_BASED == config_protocol_type) { /* Find the top_module */ - ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name()); + ModuleId top_module = + module_manager.find_module(generate_fpga_top_module_name()); VTR_ASSERT(true == module_manager.valid_module_id(top_module)); /* Address port */ - ModulePortId addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_ADDRESS_PORT_NAME)); + ModulePortId addr_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_ADDRESS_PORT_NAME)); BasicPort addr_port = module_manager.module_port(top_module, addr_port_id); - ini["SIMULATION_DECK"]["ADDR_WIDTH"] = std::to_string(addr_port.get_width()); + ini["SIMULATION_DECK"]["ADDR_WIDTH"] = + std::to_string(addr_port.get_width()); /* I/O port */ - std::vector module_io_ports = module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GPIO_PORT); + std::vector module_io_ports = + module_manager.module_ports_by_type(top_module, + ModuleManager::MODULE_GPIO_PORT); size_t total_gpio_width = 0; for (const BasicPort& module_io_port : module_io_ports) { total_gpio_width += module_io_port.get_width(); } ini["SIMULATION_DECK"]["GPIO_WIDTH"] = std::to_string(total_gpio_width); - /* I/O direction map: - * - '0' output + /* I/O direction map: + * - '0' output * - '1' input * For unused ports, by default we assume it is configured as inputs * TODO: this should be reworked to be consistent with bitstream */ - for (const BasicPort& module_io_port : module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GPIO_PORT)) { + for (const BasicPort& module_io_port : module_manager.module_ports_by_type( + top_module, ModuleManager::MODULE_GPIO_PORT)) { std::string io_direction(module_io_port.get_width(), '1'); for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) { /* Bypass non-I/O atom blocks ! */ - if ( (AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) - && (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)) ) { + if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) && + (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk))) { continue; } /* Find the index of the mapped GPIO in top-level FPGA fabric */ - size_t io_index = io_location_map.io_index(place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.x, - place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.y, - place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.sub_tile, - module_io_port.get_name()); + size_t io_index = io_location_map.io_index( + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.x, + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.y, + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.sub_tile, + module_io_port.get_name()); if (size_t(-1) == io_index) { continue; @@ -146,13 +149,14 @@ void print_verilog_simulation_info(const std::string& ini_fname, if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) { io_direction[io_index] = '1'; } else { - VTR_ASSERT(AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)); + VTR_ASSERT(AtomBlockType::OUTPAD == + atom_ctx.nlist.block_type(atom_blk)); io_direction[io_index] = '0'; } - + std::string io_tag = "IO" + module_io_port.get_name(); - - /* Organize the vector to string */ + + /* Organize the vector to string */ ini["SIMULATION_DECK"][io_tag] = io_direction; } } diff --git a/openfpga/src/fpga_verilog/verilog_simulation_info_writer.h b/openfpga/src/fpga_verilog/verilog_simulation_info_writer.h index 9493a4e68..e2a06c7b4 100644 --- a/openfpga/src/fpga_verilog/verilog_simulation_info_writer.h +++ b/openfpga/src/fpga_verilog/verilog_simulation_info_writer.h @@ -5,11 +5,12 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "module_manager.h" + #include "config_protocol.h" -#include "vpr_context.h" #include "io_location_map.h" +#include "module_manager.h" #include "verilog_testbench_options.h" +#include "vpr_context.h" /******************************************************************** * Function declaration @@ -18,19 +19,14 @@ /* begin namespace openfpga */ namespace openfpga { -void print_verilog_simulation_info(const std::string& ini_fname, - const VerilogTestbenchOption& options, - const std::string& circuit_name, - const std::string& src_dir, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const IoLocationMap& io_location_map, - const ModuleManager& module_manager, - const e_config_protocol_type& config_protocol_type, - const size_t& num_program_clock_cycles, - const int& num_operating_clock_cycles, - const float& prog_clock_freq, - const float& op_clock_freq); +void print_verilog_simulation_info( + const std::string& ini_fname, const VerilogTestbenchOption& options, + const std::string& circuit_name, const std::string& src_dir, + const AtomContext& atom_ctx, const PlacementContext& place_ctx, + const IoLocationMap& io_location_map, const ModuleManager& module_manager, + const e_config_protocol_type& config_protocol_type, + const size_t& num_program_clock_cycles, const int& num_operating_clock_cycles, + const float& prog_clock_freq, const float& op_clock_freq); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_submodule.cpp b/openfpga/src/fpga_verilog/verilog_submodule.cpp index 9798e3b75..c73da4304 100644 --- a/openfpga/src/fpga_verilog/verilog_submodule.cpp +++ b/openfpga/src/fpga_verilog/verilog_submodule.cpp @@ -4,111 +4,86 @@ ********************************************************************/ /* Headers from vtrutil library */ -#include "vtr_assert.h" -#include "vtr_log.h" - -#include "verilog_submodule_utils.h" -#include "verilog_essential_gates.h" -#include "verilog_decoders.h" -#include "verilog_mux.h" -#include "verilog_lut.h" -#include "verilog_wire.h" -#include "verilog_memory.h" -#include "verilog_shift_register_banks.h" -#include "verilog_writer_utils.h" +#include "verilog_submodule.h" #include "verilog_constants.h" -#include "verilog_submodule.h" +#include "verilog_decoders.h" +#include "verilog_essential_gates.h" +#include "verilog_lut.h" +#include "verilog_memory.h" +#include "verilog_mux.h" +#include "verilog_shift_register_banks.h" +#include "verilog_submodule_utils.h" +#include "verilog_wire.h" +#include "verilog_writer_utils.h" +#include "vtr_assert.h" +#include "vtr_log.h" /* begin namespace openfpga */ namespace openfpga { /********************************************************************* * Top-level function to generate primitive modules: - * 1. Logic gates: AND/OR, inverter, buffer and transmission-gate/pass-transistor + * 1. Logic gates: AND/OR, inverter, buffer and + *transmission-gate/pass-transistor * 2. Routing multiplexers * 3. Local encoders for routing multiplexers * 4. Wires * 5. Configuration memory blocks * 6. Verilog template ********************************************************************/ -void print_verilog_submodule(ModuleManager& module_manager, - NetlistManager& netlist_manager, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const MuxLibrary& mux_lib, - const DecoderLibrary& decoder_lib, - const CircuitLibrary& circuit_lib, - const std::string& submodule_dir, - const std::string& submodule_dir_name, - const FabricVerilogOption& fpga_verilog_opts) { - - print_verilog_submodule_essentials(const_cast(module_manager), - netlist_manager, - submodule_dir, - submodule_dir_name, - circuit_lib, - fpga_verilog_opts); +void print_verilog_submodule( + ModuleManager& module_manager, NetlistManager& netlist_manager, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const MuxLibrary& mux_lib, + const DecoderLibrary& decoder_lib, const CircuitLibrary& circuit_lib, + const std::string& submodule_dir, const std::string& submodule_dir_name, + const FabricVerilogOption& fpga_verilog_opts) { + print_verilog_submodule_essentials( + const_cast(module_manager), netlist_manager, + submodule_dir, submodule_dir_name, circuit_lib, fpga_verilog_opts); /* Decoders for architecture */ - print_verilog_submodule_arch_decoders(const_cast(module_manager), - netlist_manager, - decoder_lib, - submodule_dir, - submodule_dir_name, - fpga_verilog_opts); + print_verilog_submodule_arch_decoders( + const_cast(module_manager), netlist_manager, + decoder_lib, submodule_dir, submodule_dir_name, fpga_verilog_opts); /* Routing multiplexers */ - /* NOTE: local decoders generation must go before the MUX generation!!! - * because local decoders modules will be instanciated in the MUX modules + /* NOTE: local decoders generation must go before the MUX generation!!! + * because local decoders modules will be instanciated in the MUX + * modules */ - print_verilog_submodule_mux_local_decoders(const_cast(module_manager), - netlist_manager, - mux_lib, circuit_lib, - submodule_dir, - submodule_dir_name, - fpga_verilog_opts); - print_verilog_submodule_muxes(module_manager, netlist_manager, mux_lib, circuit_lib, - submodule_dir, - submodule_dir_name, + print_verilog_submodule_mux_local_decoders( + const_cast(module_manager), netlist_manager, mux_lib, + circuit_lib, submodule_dir, submodule_dir_name, fpga_verilog_opts); + print_verilog_submodule_muxes(module_manager, netlist_manager, mux_lib, + circuit_lib, submodule_dir, submodule_dir_name, fpga_verilog_opts); - + /* LUTes */ print_verilog_submodule_luts(const_cast(module_manager), - netlist_manager, circuit_lib, - submodule_dir, - submodule_dir_name, - fpga_verilog_opts); + netlist_manager, circuit_lib, submodule_dir, + submodule_dir_name, fpga_verilog_opts); /* Hard wires */ - print_verilog_submodule_wires(const_cast(module_manager), - netlist_manager, circuit_lib, - submodule_dir, - submodule_dir_name, - fpga_verilog_opts); + print_verilog_submodule_wires( + const_cast(module_manager), netlist_manager, + circuit_lib, submodule_dir, submodule_dir_name, fpga_verilog_opts); /* Memories */ - print_verilog_submodule_memories(const_cast(module_manager), - netlist_manager, - mux_lib, circuit_lib, - submodule_dir, - submodule_dir_name, - fpga_verilog_opts); + print_verilog_submodule_memories( + const_cast(module_manager), netlist_manager, mux_lib, + circuit_lib, submodule_dir, submodule_dir_name, fpga_verilog_opts); /* Shift register banks */ - print_verilog_submodule_shift_register_banks(const_cast(module_manager), - netlist_manager, - blwl_sr_banks, - submodule_dir, - submodule_dir_name, - fpga_verilog_opts); - + print_verilog_submodule_shift_register_banks( + const_cast(module_manager), netlist_manager, + blwl_sr_banks, submodule_dir, submodule_dir_name, fpga_verilog_opts); /* Dump template for all the modules */ - if (true == fpga_verilog_opts.print_user_defined_template()) { - print_verilog_submodule_templates(const_cast(module_manager), - circuit_lib, - submodule_dir, - fpga_verilog_opts); + if (true == fpga_verilog_opts.print_user_defined_template()) { + print_verilog_submodule_templates( + const_cast(module_manager), circuit_lib, + submodule_dir, fpga_verilog_opts); } } diff --git a/openfpga/src/fpga_verilog/verilog_submodule.h b/openfpga/src/fpga_verilog/verilog_submodule.h index 209793684..13f50d73a 100644 --- a/openfpga/src/fpga_verilog/verilog_submodule.h +++ b/openfpga/src/fpga_verilog/verilog_submodule.h @@ -4,12 +4,12 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "module_manager.h" -#include "netlist_manager.h" -#include "mux_library.h" #include "decoder_library.h" -#include "memory_bank_shift_register_banks.h" #include "fabric_verilog_options.h" +#include "memory_bank_shift_register_banks.h" +#include "module_manager.h" +#include "mux_library.h" +#include "netlist_manager.h" /******************************************************************** * Function declaration @@ -18,15 +18,12 @@ /* begin namespace openfpga */ namespace openfpga { -void print_verilog_submodule(ModuleManager& module_manager, - NetlistManager& netlist_manager, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const MuxLibrary& mux_lib, - const DecoderLibrary& decoder_lib, - const CircuitLibrary& circuit_lib, - const std::string& submodule_dir, - const std::string& submodule_dir_name, - const FabricVerilogOption& fpga_verilog_opts); +void print_verilog_submodule( + ModuleManager& module_manager, NetlistManager& netlist_manager, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const MuxLibrary& mux_lib, + const DecoderLibrary& decoder_lib, const CircuitLibrary& circuit_lib, + const std::string& submodule_dir, const std::string& submodule_dir_name, + const FabricVerilogOption& fpga_verilog_opts); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_submodule_utils.cpp b/openfpga/src/fpga_verilog/verilog_submodule_utils.cpp index 91e5548af..362cd3dd2 100644 --- a/openfpga/src/fpga_verilog/verilog_submodule_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_submodule_utils.cpp @@ -1,50 +1,49 @@ /************************************************ - * This file includes most utilized functions for + * This file includes most utilized functions for * generating Verilog sub-modules * such as timing matrix and signal initialization ***********************************************/ #include -#include #include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" #include "vtr_log.h" /* Headers from openfpgautil library */ -#include "openfpga_port.h" #include "openfpga_digest.h" +#include "openfpga_port.h" /* Headers from readarchopenfpga library */ #include "circuit_types.h" - #include "module_manager_utils.h" #include "verilog_constants.h" -#include "verilog_writer_utils.h" #include "verilog_submodule_utils.h" +#include "verilog_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { /* All values are printed with this precision value. The higher the * value, the more accurate timing assignment is. Using a number of 6 - * guarentees that a precision of femtosecond which is sufficent for - * electrical simulation (simulation timescale is 10-9 + * guarentees that a precision of femtosecond which is sufficent for + * electrical simulation (simulation timescale is 10-9 */ /* constexpr int FLOAT_PRECISION = std::numeric_limits::max_digits10; */ -constexpr int FLOAT_PRECISION = 6; +constexpr int FLOAT_PRECISION = 6; /************************************************ * Print a timing matrix defined in theecircuit model - * into a Verilog format. + * into a Verilog format. * This function print all the timing edges available * in the circuit model (any pin-to-pin delay) ***********************************************/ -void print_verilog_submodule_timing(std::fstream& fp, +void print_verilog_submodule_timing(std::fstream& fp, const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model) { /* return if there is no delay info */ - if ( 0 == circuit_lib.num_delay_info(circuit_model)) { + if (0 == circuit_lib.num_delay_info(circuit_model)) { return; } @@ -58,36 +57,48 @@ void print_verilog_submodule_timing(std::fstream& fp, fp << std::endl; fp << "`ifdef " << VERILOG_TIMING_PREPROC_FLAG << std::endl; - print_verilog_comment(fp, std::string("------ BEGIN Pin-to-pin Timing constraints -----")); + print_verilog_comment( + fp, std::string("------ BEGIN Pin-to-pin Timing constraints -----")); fp << "\tspecify" << std::endl; - /* Read out pin-to-pin delays by finding out all the edges belonging to a circuit model */ - for (const auto& timing_edge : circuit_lib.timing_edges_by_model(circuit_model)) { - CircuitPortId src_port = circuit_lib.timing_edge_src_port(timing_edge); - size_t src_pin = circuit_lib.timing_edge_src_pin(timing_edge); - BasicPort src_port_info(circuit_lib.port_lib_name(src_port), src_pin, src_pin); - src_port_info.set_origin_port_width(src_port_info.get_width()); + /* Read out pin-to-pin delays by finding out all the edges belonging to a + * circuit model */ + for (const auto& timing_edge : + circuit_lib.timing_edges_by_model(circuit_model)) { + CircuitPortId src_port = circuit_lib.timing_edge_src_port(timing_edge); + size_t src_pin = circuit_lib.timing_edge_src_pin(timing_edge); + BasicPort src_port_info(circuit_lib.port_lib_name(src_port), src_pin, + src_pin); + src_port_info.set_origin_port_width(src_port_info.get_width()); - CircuitPortId sink_port = circuit_lib.timing_edge_sink_port(timing_edge); - size_t sink_pin = circuit_lib.timing_edge_sink_pin(timing_edge); - BasicPort sink_port_info(circuit_lib.port_lib_name(sink_port), sink_pin, sink_pin); - sink_port_info.set_origin_port_width(sink_port_info.get_width()); - - fp << "\t\t"; - fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, src_port_info, false); - fp << " => "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, sink_port_info, false) << ")"; - fp << " = "; - fp << "(" << std::setprecision(FLOAT_PRECISION) << circuit_lib.timing_edge_delay(timing_edge, CIRCUIT_MODEL_DELAY_RISE) / VERILOG_SIM_TIMESCALE; - fp << ", "; - fp << std::setprecision(FLOAT_PRECISION) << circuit_lib.timing_edge_delay(timing_edge, CIRCUIT_MODEL_DELAY_FALL) / VERILOG_SIM_TIMESCALE << ")"; - fp << ";" << std::endl; + CircuitPortId sink_port = circuit_lib.timing_edge_sink_port(timing_edge); + size_t sink_pin = circuit_lib.timing_edge_sink_pin(timing_edge); + BasicPort sink_port_info(circuit_lib.port_lib_name(sink_port), sink_pin, + sink_pin); + sink_port_info.set_origin_port_width(sink_port_info.get_width()); + + fp << "\t\t"; + fp << "(" + << generate_verilog_port(VERILOG_PORT_CONKT, src_port_info, false); + fp << " => "; + fp << generate_verilog_port(VERILOG_PORT_CONKT, sink_port_info, false) + << ")"; + fp << " = "; + fp << "(" << std::setprecision(FLOAT_PRECISION) + << circuit_lib.timing_edge_delay(timing_edge, CIRCUIT_MODEL_DELAY_RISE) / + VERILOG_SIM_TIMESCALE; + fp << ", "; + fp << std::setprecision(FLOAT_PRECISION) + << circuit_lib.timing_edge_delay(timing_edge, CIRCUIT_MODEL_DELAY_FALL) / + VERILOG_SIM_TIMESCALE + << ")"; + fp << ";" << std::endl; } fp << "\tendspecify" << std::endl; - print_verilog_comment(fp, std::string("------ END Pin-to-pin Timing constraints -----")); + print_verilog_comment( + fp, std::string("------ END Pin-to-pin Timing constraints -----")); fp << "`endif" << std::endl; - } /********************************************************************* @@ -95,7 +106,7 @@ void print_verilog_submodule_timing(std::fstream& fp, * Walk through the circuit library and add user-defined circuit models * to the module_manager ********************************************************************/ -void add_user_defined_verilog_modules(ModuleManager& module_manager, +void add_user_defined_verilog_modules(ModuleManager& module_manager, const CircuitLibrary& circuit_lib) { VTR_LOG("Registering user-defined modules..."); @@ -105,15 +116,17 @@ void add_user_defined_verilog_modules(ModuleManager& module_manager, if (true == circuit_lib.model_verilog_netlist(model).empty()) { continue; } - /* Skip Routing channel wire models because they need a different name. Do it later */ + /* Skip Routing channel wire models because they need a different name. Do + * it later */ if (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) { continue; } - /* Reach here, the model requires a user-defined Verilog netlist, - * Try to find it in the module manager - * If not found, register it in the module_manager + /* Reach here, the model requires a user-defined Verilog netlist, + * Try to find it in the module manager + * If not found, register it in the module_manager */ - ModuleId module_id = module_manager.find_module(circuit_lib.model_name(model)); + ModuleId module_id = + module_manager.find_module(circuit_lib.model_name(model)); if (ModuleId::INVALID() == module_id) { add_circuit_model_to_module_manager(module_manager, circuit_lib, model); VTR_LOG("Registered user-defined circuit model '%s'\n", @@ -131,15 +144,15 @@ void add_user_defined_verilog_modules(ModuleManager& module_manager, * module definition, which can be correctly instanciated (with correct * port mapping) in the FPGA fabric ********************************************************************/ -static -void print_one_verilog_template_module(const ModuleManager& module_manager, - std::fstream& fp, - const std::string& module_name, - const e_verilog_default_net_type& default_net_type) { +static void print_one_verilog_template_module( + const ModuleManager& module_manager, std::fstream& fp, + const std::string& module_name, + const e_verilog_default_net_type& default_net_type) { /* Ensure a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); - print_verilog_comment(fp, std::string("----- Template Verilog module for " + module_name + " -----")); + print_verilog_comment(fp, std::string("----- Template Verilog module for " + + module_name + " -----")); /* Find the module in module manager, which should be already registered */ /* TODO: routing channel wire model may have a different name! */ @@ -147,15 +160,18 @@ void print_one_verilog_template_module(const ModuleManager& module_manager, VTR_ASSERT(ModuleId::INVALID() != template_module); /* dump module definition + ports */ - print_verilog_module_declaration(fp, module_manager, template_module, default_net_type); + print_verilog_module_declaration(fp, module_manager, template_module, + default_net_type); /* Finish dumping ports */ - print_verilog_comment(fp, std::string("----- Internal logic should start here -----")); + print_verilog_comment( + fp, std::string("----- Internal logic should start here -----")); /* Add some empty lines as placeholders for the internal logic*/ fp << std::endl << std::endl; - - print_verilog_comment(fp, std::string("----- Internal logic should end here -----")); + + print_verilog_comment( + fp, std::string("----- Internal logic should end here -----")); /* Put an end to the Verilog module */ print_verilog_module_end(fp, module_name); @@ -175,7 +191,8 @@ void print_verilog_submodule_templates(const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const std::string& submodule_dir, const FabricVerilogOption& options) { - std::string verilog_fname(submodule_dir + USER_DEFINED_TEMPLATE_VERILOG_FILE_NAME); + std::string verilog_fname(submodule_dir + + USER_DEFINED_TEMPLATE_VERILOG_FILE_NAME); /* Create the file stream */ std::fstream fp; @@ -183,32 +200,35 @@ void print_verilog_submodule_templates(const ModuleManager& module_manager, check_file_stream(verilog_fname.c_str(), fp); - /* Print out debugging information for if the file is not opened/created properly */ + /* Print out debugging information for if the file is not opened/created + * properly */ VTR_LOG("Creating template for user-defined Verilog modules '%s'...", - verilog_fname.c_str()); + verilog_fname.c_str()); - print_verilog_file_header(fp, "Template for user-defined Verilog modules", options.time_stamp()); + print_verilog_file_header(fp, "Template for user-defined Verilog modules", + options.time_stamp()); /* Output essential models*/ for (const auto& model : circuit_lib.models()) { - /* Focus on user-defined modules, which must have a Verilog netlist defined */ + /* Focus on user-defined modules, which must have a Verilog netlist defined + */ if (circuit_lib.model_verilog_netlist(model).empty()) { continue; } - /* Skip Routing channel wire models because they need a different name. Do it later */ + /* Skip Routing channel wire models because they need a different name. Do + * it later */ if (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) { continue; } /* Print a Verilog template for the circuit model */ - print_one_verilog_template_module(module_manager, - fp, + print_one_verilog_template_module(module_manager, fp, circuit_lib.model_name(model), - options.default_net_type()); + options.default_net_type()); } /* close file stream */ fp.close(); - + /* No need to add the template to the subckt include files! */ VTR_LOG("Done\n"); } diff --git a/openfpga/src/fpga_verilog/verilog_submodule_utils.h b/openfpga/src/fpga_verilog/verilog_submodule_utils.h index 3f266231a..9cb7f75bd 100644 --- a/openfpga/src/fpga_verilog/verilog_submodule_utils.h +++ b/openfpga/src/fpga_verilog/verilog_submodule_utils.h @@ -6,10 +6,11 @@ *******************************************************************/ #include #include -#include "module_manager.h" + #include "circuit_library.h" -#include "verilog_port_types.h" #include "fabric_verilog_options.h" +#include "module_manager.h" +#include "verilog_port_types.h" /******************************************************************** * Function declaration @@ -18,11 +19,11 @@ /* begin namespace openfpga */ namespace openfpga { -void print_verilog_submodule_timing(std::fstream& fp, +void print_verilog_submodule_timing(std::fstream& fp, const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model); -void add_user_defined_verilog_modules(ModuleManager& module_manager, +void add_user_defined_verilog_modules(ModuleManager& module_manager, const CircuitLibrary& circuit_lib); void print_verilog_submodule_templates(const ModuleManager& module_manager, diff --git a/openfpga/src/fpga_verilog/verilog_testbench_options.cpp b/openfpga/src/fpga_verilog/verilog_testbench_options.cpp index 6104006e8..885ddc744 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_options.cpp +++ b/openfpga/src/fpga_verilog/verilog_testbench_options.cpp @@ -1,11 +1,11 @@ /****************************************************************************** * Memember functions for data structure VerilogTestbenchOption ******************************************************************************/ +#include "verilog_testbench_options.h" + #include "vtr_assert.h" #include "vtr_log.h" -#include "verilog_testbench_options.h" - /* begin namespace openfpga */ namespace openfpga { @@ -31,7 +31,7 @@ VerilogTestbenchOption::VerilogTestbenchOption() { } /************************************************** - * Public Accessors + * Public Accessors *************************************************/ std::string VerilogTestbenchOption::output_directory() const { return output_directory_; @@ -85,47 +85,46 @@ e_verilog_default_net_type VerilogTestbenchOption::default_net_type() const { return default_net_type_; } -float VerilogTestbenchOption::time_unit() const { - return time_unit_; +float VerilogTestbenchOption::time_unit() const { return time_unit_; } + +e_embedded_bitstream_hdl_type +VerilogTestbenchOption::embedded_bitstream_hdl_type() const { + return embedded_bitstream_hdl_type_; } -e_embedded_bitstream_hdl_type VerilogTestbenchOption::embedded_bitstream_hdl_type() const { - return embedded_bitstream_hdl_type_; -} - -bool VerilogTestbenchOption::time_stamp() const { - return time_stamp_; -} +bool VerilogTestbenchOption::time_stamp() const { return time_stamp_; } bool VerilogTestbenchOption::use_relative_path() const { return use_relative_path_; } -bool VerilogTestbenchOption::verbose_output() const { - return verbose_output_; -} +bool VerilogTestbenchOption::verbose_output() const { return verbose_output_; } /****************************************************************************** * Private Mutators ******************************************************************************/ -void VerilogTestbenchOption::set_output_directory(const std::string& output_dir) { +void VerilogTestbenchOption::set_output_directory( + const std::string& output_dir) { output_directory_ = output_dir; } -void VerilogTestbenchOption::set_fabric_netlist_file_path(const std::string& fabric_netlist_file_path) { +void VerilogTestbenchOption::set_fabric_netlist_file_path( + const std::string& fabric_netlist_file_path) { fabric_netlist_file_path_ = fabric_netlist_file_path; } -void VerilogTestbenchOption::set_reference_benchmark_file_path(const std::string& reference_benchmark_file_path) { +void VerilogTestbenchOption::set_reference_benchmark_file_path( + const std::string& reference_benchmark_file_path) { reference_benchmark_file_path_ = reference_benchmark_file_path; - /* Chain effect on other options: + /* Chain effect on other options: * Enable/disable the print_preconfig_top_testbench and print_top_testbench */ - set_print_preconfig_top_testbench(print_preconfig_top_testbench_); - set_print_top_testbench(print_top_testbench_); + set_print_preconfig_top_testbench(print_preconfig_top_testbench_); + set_print_top_testbench(print_top_testbench_); } - -void VerilogTestbenchOption::set_print_formal_verification_top_netlist(const bool& enabled) { + +void VerilogTestbenchOption::set_print_formal_verification_top_netlist( + const bool& enabled) { print_formal_verification_top_netlist_ = enabled; } @@ -133,13 +132,17 @@ void VerilogTestbenchOption::set_fast_configuration(const bool& enabled) { fast_configuration_ = enabled; } -void VerilogTestbenchOption::set_print_preconfig_top_testbench(const bool& enabled) { - print_preconfig_top_testbench_ = enabled - && (!reference_benchmark_file_path_.empty()); +void VerilogTestbenchOption::set_print_preconfig_top_testbench( + const bool& enabled) { + print_preconfig_top_testbench_ = + enabled && (!reference_benchmark_file_path_.empty()); /* Enable print formal verification top_netlist if this is enabled */ if (true == print_preconfig_top_testbench_) { - if (false == print_formal_verification_top_netlist_) { - VTR_LOG_WARN("Forcely enable to print top-level Verilog netlist in formal verification purpose as print pre-configured top-level Verilog testbench is enabled\n"); + if (false == print_formal_verification_top_netlist_) { + VTR_LOG_WARN( + "Forcely enable to print top-level Verilog netlist in formal " + "verification purpose as print pre-configured top-level Verilog " + "testbench is enabled\n"); print_formal_verification_top_netlist_ = true; } } @@ -149,7 +152,8 @@ void VerilogTestbenchOption::set_print_top_testbench(const bool& enabled) { print_top_testbench_ = enabled && (!reference_benchmark_file_path_.empty()); } -void VerilogTestbenchOption::set_print_simulation_ini(const std::string& simulation_ini_path) { +void VerilogTestbenchOption::set_print_simulation_ini( + const std::string& simulation_ini_path) { simulation_ini_path_ = simulation_ini_path; } @@ -161,34 +165,48 @@ void VerilogTestbenchOption::set_include_signal_init(const bool& enabled) { include_signal_init_ = enabled; } -void VerilogTestbenchOption::set_default_net_type(const std::string& default_net_type) { +void VerilogTestbenchOption::set_default_net_type( + const std::string& default_net_type) { /* Decode from net type string */; - if (default_net_type == std::string(VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_NONE])) { + if (default_net_type == + std::string( + VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_NONE])) { default_net_type_ = VERILOG_DEFAULT_NET_TYPE_NONE; - } else if (default_net_type == std::string(VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_WIRE])) { + } else if (default_net_type == + std::string(VERILOG_DEFAULT_NET_TYPE_STRING + [VERILOG_DEFAULT_NET_TYPE_WIRE])) { default_net_type_ = VERILOG_DEFAULT_NET_TYPE_WIRE; } else { - VTR_LOG_WARN("Invalid default net type: '%s'! Expect ['%s'|'%s']\n", - default_net_type.c_str(), - VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_NONE], - VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_WIRE]); + VTR_LOG_WARN( + "Invalid default net type: '%s'! Expect ['%s'|'%s']\n", + default_net_type.c_str(), + VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_NONE], + VERILOG_DEFAULT_NET_TYPE_STRING[VERILOG_DEFAULT_NET_TYPE_WIRE]); } } -void VerilogTestbenchOption::set_embedded_bitstream_hdl_type(const std::string& embedded_bitstream_hdl_type) { +void VerilogTestbenchOption::set_embedded_bitstream_hdl_type( + const std::string& embedded_bitstream_hdl_type) { /* Decode from HDL type string */; - if (embedded_bitstream_hdl_type == std::string(EMBEDDED_BITSTREAM_HDL_TYPE_STRING[NUM_EMBEDDED_BITSTREAM_HDL_TYPES])) { + if (embedded_bitstream_hdl_type == + std::string( + EMBEDDED_BITSTREAM_HDL_TYPE_STRING[NUM_EMBEDDED_BITSTREAM_HDL_TYPES])) { embedded_bitstream_hdl_type_ = NUM_EMBEDDED_BITSTREAM_HDL_TYPES; - } else if (embedded_bitstream_hdl_type == std::string(EMBEDDED_BITSTREAM_HDL_TYPE_STRING[EMBEDDED_BITSTREAM_HDL_IVERILOG])) { + } else if (embedded_bitstream_hdl_type == + std::string(EMBEDDED_BITSTREAM_HDL_TYPE_STRING + [EMBEDDED_BITSTREAM_HDL_IVERILOG])) { embedded_bitstream_hdl_type_ = EMBEDDED_BITSTREAM_HDL_IVERILOG; - } else if (embedded_bitstream_hdl_type == std::string(EMBEDDED_BITSTREAM_HDL_TYPE_STRING[EMBEDDED_BITSTREAM_HDL_MODELSIM])) { + } else if (embedded_bitstream_hdl_type == + std::string(EMBEDDED_BITSTREAM_HDL_TYPE_STRING + [EMBEDDED_BITSTREAM_HDL_MODELSIM])) { embedded_bitstream_hdl_type_ = EMBEDDED_BITSTREAM_HDL_MODELSIM; } else { - VTR_LOG_WARN("Invalid embedded bitstream type: '%s'! Expect ['%s'|'%s'|'%s']\n", - embedded_bitstream_hdl_type.c_str(), - EMBEDDED_BITSTREAM_HDL_TYPE_STRING[NUM_EMBEDDED_BITSTREAM_HDL_TYPES], - EMBEDDED_BITSTREAM_HDL_TYPE_STRING[EMBEDDED_BITSTREAM_HDL_IVERILOG], - EMBEDDED_BITSTREAM_HDL_TYPE_STRING[EMBEDDED_BITSTREAM_HDL_MODELSIM]); + VTR_LOG_WARN( + "Invalid embedded bitstream type: '%s'! Expect ['%s'|'%s'|'%s']\n", + embedded_bitstream_hdl_type.c_str(), + EMBEDDED_BITSTREAM_HDL_TYPE_STRING[NUM_EMBEDDED_BITSTREAM_HDL_TYPES], + EMBEDDED_BITSTREAM_HDL_TYPE_STRING[EMBEDDED_BITSTREAM_HDL_IVERILOG], + EMBEDDED_BITSTREAM_HDL_TYPE_STRING[EMBEDDED_BITSTREAM_HDL_MODELSIM]); } } diff --git a/openfpga/src/fpga_verilog/verilog_testbench_options.h b/openfpga/src/fpga_verilog/verilog_testbench_options.h index d7f28596e..7610f95b9 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_options.h +++ b/openfpga/src/fpga_verilog/verilog_testbench_options.h @@ -5,6 +5,7 @@ * Include header files required by the data structure definition *******************************************************************/ #include + #include "verilog_port_types.h" /* Begin namespace openfpga */ @@ -17,7 +18,9 @@ enum e_embedded_bitstream_hdl_type { NUM_EMBEDDED_BITSTREAM_HDL_TYPES }; -constexpr std::array EMBEDDED_BITSTREAM_HDL_TYPE_STRING = {{"iverilog", "modelsim", "none"}}; //String versions of default net types +constexpr std::array + EMBEDDED_BITSTREAM_HDL_TYPE_STRING = { + {"iverilog", "modelsim", "none"}}; // String versions of default net types /******************************************************************** * Options for Verilog Testbench generator @@ -28,74 +31,84 @@ constexpr std::array EMBEDDED * *******************************************************************/ class VerilogTestbenchOption { - public: /* Public constructor */ - /* Set default options */ - VerilogTestbenchOption(); - public: /* Public accessors */ - std::string output_directory() const; - std::string fabric_netlist_file_path() const; - std::string reference_benchmark_file_path() const; - bool fast_configuration() const; - bool print_formal_verification_top_netlist() const; - bool print_preconfig_top_testbench() const; - bool print_top_testbench() const; - bool print_simulation_ini() const; - std::string simulation_ini_path() const; - bool explicit_port_mapping() const; - bool include_signal_init() const; - bool no_self_checking() const; - e_verilog_default_net_type default_net_type() const; - e_embedded_bitstream_hdl_type embedded_bitstream_hdl_type() const; - float time_unit() const; - bool time_stamp() const; - bool use_relative_path() const; - bool verbose_output() const; - public: /* Public validator */ - bool validate() const; - public: /* Public mutators */ - void set_output_directory(const std::string& output_dir); - /* The reference verilog file path is the key parameters that will have an impact on other options: - * - print_preconfig_top_testbench - * - print_top_testbench - * If the file path is empty, the above testbench generation will not be enabled - */ - void set_reference_benchmark_file_path(const std::string& reference_benchmark_file_path); - /* The fabric netlist file path is an optional parameter - * to allow users to specify a fabric netlist at another location - */ - void set_fabric_netlist_file_path(const std::string& fabric_netlist_file_path); - void set_print_formal_verification_top_netlist(const bool& enabled); - /* The preconfig top testbench generation can be enabled only when formal verification top netlist is enabled */ - void set_print_preconfig_top_testbench(const bool& enabled); - void set_fast_configuration(const bool& enabled); - void set_print_top_testbench(const bool& enabled); - void set_print_simulation_ini(const std::string& simulation_ini_path); - void set_explicit_port_mapping(const bool& enabled); - void set_include_signal_init(const bool& enabled); - void set_default_net_type(const std::string& default_net_type); - void set_time_unit(const float& time_unit); - void set_embedded_bitstream_hdl_type(const std::string& embedded_bitstream_hdl_type); - void set_time_stamp(const bool& enabled); - void set_use_relative_path(const bool& enabled); - void set_verbose_output(const bool& enabled); - private: /* Internal Data */ - std::string output_directory_; - std::string fabric_netlist_file_path_; - std::string reference_benchmark_file_path_; - bool fast_configuration_; - bool print_formal_verification_top_netlist_; - bool print_preconfig_top_testbench_; - bool print_top_testbench_; - /* Print simulation ini is enabled only when the path is not empty */ - std::string simulation_ini_path_; - bool explicit_port_mapping_; - bool include_signal_init_; - e_verilog_default_net_type default_net_type_; - e_embedded_bitstream_hdl_type embedded_bitstream_hdl_type_; - float time_unit_; - bool time_stamp_; - bool use_relative_path_; - bool verbose_output_; + public: /* Public constructor */ + /* Set default options */ + VerilogTestbenchOption(); + + public: /* Public accessors */ + std::string output_directory() const; + std::string fabric_netlist_file_path() const; + std::string reference_benchmark_file_path() const; + bool fast_configuration() const; + bool print_formal_verification_top_netlist() const; + bool print_preconfig_top_testbench() const; + bool print_top_testbench() const; + bool print_simulation_ini() const; + std::string simulation_ini_path() const; + bool explicit_port_mapping() const; + bool include_signal_init() const; + bool no_self_checking() const; + e_verilog_default_net_type default_net_type() const; + e_embedded_bitstream_hdl_type embedded_bitstream_hdl_type() const; + float time_unit() const; + bool time_stamp() const; + bool use_relative_path() const; + bool verbose_output() const; + + public: /* Public validator */ + bool validate() const; + + public: /* Public mutators */ + void set_output_directory(const std::string& output_dir); + /* The reference verilog file path is the key parameters that will have an + * impact on other options: + * - print_preconfig_top_testbench + * - print_top_testbench + * If the file path is empty, the above testbench generation will not be + * enabled + */ + void set_reference_benchmark_file_path( + const std::string& reference_benchmark_file_path); + /* The fabric netlist file path is an optional parameter + * to allow users to specify a fabric netlist at another location + */ + void set_fabric_netlist_file_path( + const std::string& fabric_netlist_file_path); + void set_print_formal_verification_top_netlist(const bool& enabled); + /* The preconfig top testbench generation can be enabled only when formal + * verification top netlist is enabled */ + void set_print_preconfig_top_testbench(const bool& enabled); + void set_fast_configuration(const bool& enabled); + void set_print_top_testbench(const bool& enabled); + void set_print_simulation_ini(const std::string& simulation_ini_path); + void set_explicit_port_mapping(const bool& enabled); + void set_include_signal_init(const bool& enabled); + void set_default_net_type(const std::string& default_net_type); + void set_time_unit(const float& time_unit); + void set_embedded_bitstream_hdl_type( + const std::string& embedded_bitstream_hdl_type); + void set_time_stamp(const bool& enabled); + void set_use_relative_path(const bool& enabled); + void set_verbose_output(const bool& enabled); + + private: /* Internal Data */ + std::string output_directory_; + std::string fabric_netlist_file_path_; + std::string reference_benchmark_file_path_; + bool fast_configuration_; + bool print_formal_verification_top_netlist_; + bool print_preconfig_top_testbench_; + bool print_top_testbench_; + /* Print simulation ini is enabled only when the path is not empty */ + std::string simulation_ini_path_; + bool explicit_port_mapping_; + bool include_signal_init_; + e_verilog_default_net_type default_net_type_; + e_embedded_bitstream_hdl_type embedded_bitstream_hdl_type_; + float time_unit_; + bool time_stamp_; + bool use_relative_path_; + bool verbose_output_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp index bfa53df80..6e70f8008 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp @@ -13,20 +13,16 @@ #include "vtr_assert.h" /* Headers from openfpgautil library */ -#include "openfpga_port.h" -#include "openfpga_digest.h" - -#include "openfpga_naming.h" - -#include "verilog_port_types.h" - -#include "module_manager_utils.h" #include "fabric_global_port_info_utils.h" +#include "module_manager_utils.h" #include "openfpga_atom_netlist_utils.h" - +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" #include "verilog_constants.h" -#include "verilog_writer_utils.h" +#include "verilog_port_types.h" #include "verilog_testbench_utils.h" +#include "verilog_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -48,13 +44,16 @@ void print_verilog_testbench_fpga_instance(std::fstream& fp, valid_file_stream(fp); /* Include defined top-level module */ - print_verilog_comment(fp, std::string("----- FPGA top-level module to be capsulated -----")); + print_verilog_comment( + fp, std::string("----- FPGA top-level module to be capsulated -----")); /* Create an empty port-to-port name mapping, because we use default names */ std::map port2port_name_map; - if (!net_postfix.empty()) { - for (const ModulePortId &module_port_id : module_manager.module_ports(top_module)) { - BasicPort module_port = module_manager.module_port(top_module, module_port_id); + if (!net_postfix.empty()) { + for (const ModulePortId& module_port_id : + module_manager.module_ports(top_module)) { + BasicPort module_port = + module_manager.module_port(top_module, module_port_id); BasicPort net_port = module_port; net_port.set_name(module_port.get_name() + net_postfix); port2port_name_map[module_port.get_name()] = net_port; @@ -62,10 +61,9 @@ void print_verilog_testbench_fpga_instance(std::fstream& fp, } /* Use explicit port mapping for a clean instanciation */ - print_verilog_module_instance(fp, module_manager, top_module, - top_instance_name, - port2port_name_map, - explicit_port_mapping); + print_verilog_module_instance(fp, module_manager, top_module, + top_instance_name, port2port_name_map, + explicit_port_mapping); /* Add an empty line as a splitter */ fp << std::endl; @@ -74,19 +72,16 @@ void print_verilog_testbench_fpga_instance(std::fstream& fp, /******************************************************************** * Instanciate the input benchmark module *******************************************************************/ -void print_verilog_testbench_benchmark_instance(std::fstream& fp, - const std::string& module_name, - const std::string& instance_name, - const std::string& module_input_port_postfix, - const std::string& module_output_port_postfix, - const std::string& input_port_postfix, - const std::string& output_port_postfix, - const std::vector& clock_port_names, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const bool& use_explicit_port_map) { +void print_verilog_testbench_benchmark_instance( + std::fstream& fp, const std::string& module_name, + const std::string& instance_name, + const std::string& module_input_port_postfix, + const std::string& module_output_port_postfix, + const std::string& input_port_postfix, const std::string& output_port_postfix, + const std::vector& clock_port_names, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const PinConstraints& pin_constraints, const BusGroup& bus_group, + const bool& use_explicit_port_map) { /* Validate the file stream */ valid_file_stream(fp); @@ -98,19 +93,20 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp, for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) { /* Bypass non-I/O atom blocks ! */ - if ( (AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) - && (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)) ) { + if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) && + (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk))) { continue; } - /* The block may be renamed as it contains special characters which violate Verilog syntax */ + /* The block may be renamed as it contains special characters which violate + * Verilog syntax */ std::string block_name = atom_ctx.nlist.block_name(atom_blk); if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); - } + } - /* Note that VPR added a prefix "out_" or "out:" to the name of output blocks - * We can remove this when specified through input argument + /* Note that VPR added a prefix "out_" or "out:" to the name of output + * blocks We can remove this when specified through input argument */ if (AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)) { block_name = remove_atom_block_name_prefix(block_name); @@ -125,14 +121,17 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp, */ BusGroupId bus_id = bus_group.find_pin_bus(block_name); if (bus_id) { - if (port_names.end() == std::find(port_names.begin(), port_names.end(), bus_group.bus_port(bus_id).get_name())) { + if (port_names.end() == + std::find(port_names.begin(), port_names.end(), + bus_group.bus_port(bus_id).get_name())) { port_names.push_back(bus_group.bus_port(bus_id).get_name()); port_types.push_back(atom_ctx.nlist.block_type(atom_blk)); } continue; } - /* Input port follows the logical block name while output port requires a special postfix */ + /* Input port follows the logical block name while output port requires a + * special postfix */ port_names.push_back(block_name); port_types.push_back(atom_ctx.nlist.block_type(atom_blk)); } @@ -141,7 +140,7 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp, size_t port_counter = 0; for (size_t iport = 0; iport < port_names.size(); ++iport) { /* The first port does not need a comma */ - if (0 < port_counter){ + if (0 < port_counter) { fp << "," << std::endl; } @@ -156,7 +155,8 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp, if (bus_id) { fp << "{"; int pin_counter = 0; - /* Include all the pins: If it follows little endian, reverse the pin sequence */ + /* Include all the pins: If it follows little endian, reverse the pin + * sequence */ std::vector bus_pins = bus_group.bus_pins(bus_id); if (!bus_group.is_big_endian(bus_id)) { std::reverse(bus_pins.begin(), bus_pins.end()); @@ -165,19 +165,23 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp, if (0 < pin_counter) { fp << ", "; } - /* Polarity of some input may have to be inverted, as defined in pin constraints - * For example, the reset signal of the benchmark is active low - * while the reset signal of the FPGA fabric is active high (inside FPGA, the reset signal will be inverted) - * However, to ensure correct stimuli to the benchmark, we have to invert the signal + /* Polarity of some input may have to be inverted, as defined in pin + * constraints For example, the reset signal of the benchmark is + * active low while the reset signal of the FPGA fabric is active high + * (inside FPGA, the reset signal will be inverted) However, to ensure + * correct stimuli to the benchmark, we have to invert the signal */ - if (PinConstraints::LOGIC_HIGH == pin_constraints.net_default_value(bus_group.pin_name(pin))) { + if (PinConstraints::LOGIC_HIGH == + pin_constraints.net_default_value(bus_group.pin_name(pin))) { fp << "~"; } fp << bus_group.pin_name(pin); /* For clock ports, skip postfix */ - if (clock_port_names.end() == std::find(clock_port_names.begin(), clock_port_names.end(), port_names[iport])) { + if (clock_port_names.end() == std::find(clock_port_names.begin(), + clock_port_names.end(), + port_names[iport])) { fp << input_port_postfix; } @@ -185,18 +189,22 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp, } fp << "}"; } else { - /* Polarity of some input may have to be inverted, as defined in pin constraints - * For example, the reset signal of the benchmark is active low - * while the reset signal of the FPGA fabric is active high (inside FPGA, the reset signal will be inverted) - * However, to ensure correct stimuli to the benchmark, we have to invert the signal + /* Polarity of some input may have to be inverted, as defined in pin + * constraints For example, the reset signal of the benchmark is active + * low while the reset signal of the FPGA fabric is active high (inside + * FPGA, the reset signal will be inverted) However, to ensure correct + * stimuli to the benchmark, we have to invert the signal */ - if (PinConstraints::LOGIC_HIGH == pin_constraints.net_default_value(port_names[iport])) { + if (PinConstraints::LOGIC_HIGH == + pin_constraints.net_default_value(port_names[iport])) { fp << "~"; } fp << port_names[iport]; /* For clock ports, skip postfix */ - if (clock_port_names.end() == std::find(clock_port_names.begin(), clock_port_names.end(), port_names[iport])) { + if (clock_port_names.end() == std::find(clock_port_names.begin(), + clock_port_names.end(), + port_names[iport])) { fp << input_port_postfix; } } @@ -216,7 +224,8 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp, if (bus_id) { fp << "{"; int pin_counter = 0; - /* Include all the pins: If it follows little endian, reverse the pin sequence */ + /* Include all the pins: If it follows little endian, reverse the pin + * sequence */ std::vector bus_pins = bus_group.bus_pins(bus_id); if (!bus_group.is_big_endian(bus_id)) { std::reverse(bus_pins.begin(), bus_pins.end()); @@ -235,7 +244,7 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp, if (true == use_explicit_port_map) { fp << ")"; } - } + } /* Update the counter */ port_counter++; @@ -248,30 +257,31 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp, * 1. For mapped I/Os, this function will wire them to the input ports * of the pre-configured FPGA top module * 2. For unmapped I/Os, this function will assign a constant value - * by default + * by default *******************************************************************/ -void print_verilog_testbench_connect_fpga_ios(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const IoLocationMap& io_location_map, - const VprNetlistAnnotation& netlist_annotation, - const BusGroup& bus_group, - const std::string& net_name_postfix, - const std::string& io_input_port_name_postfix, - const std::string& io_output_port_name_postfix, - const std::vector& clock_port_names, - const size_t& unused_io_value) { +void print_verilog_testbench_connect_fpga_ios( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, const AtomContext& atom_ctx, + const PlacementContext& place_ctx, const IoLocationMap& io_location_map, + const VprNetlistAnnotation& netlist_annotation, const BusGroup& bus_group, + const std::string& net_name_postfix, + const std::string& io_input_port_name_postfix, + const std::string& io_output_port_name_postfix, + const std::vector& clock_port_names, + const size_t& unused_io_value) { /* Validate the file stream */ valid_file_stream(fp); /* Only mappable i/o ports can be considered */ std::vector module_io_ports; - for (const ModuleManager::e_module_port_type& module_io_port_type : MODULE_IO_PORT_TYPES) { - for (const ModulePortId& gpio_port_id : module_manager.module_port_ids_by_type(top_module, module_io_port_type)) { + for (const ModuleManager::e_module_port_type& module_io_port_type : + MODULE_IO_PORT_TYPES) { + for (const ModulePortId& gpio_port_id : + module_manager.module_port_ids_by_type(top_module, + module_io_port_type)) { /* Only care mappable I/O */ - if (false == module_manager.port_is_mappable_io(top_module, gpio_port_id)) { + if (false == + module_manager.port_is_mappable_io(top_module, gpio_port_id)) { continue; } module_io_ports.push_back(gpio_port_id); @@ -280,42 +290,51 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp, /* Keep tracking which I/Os have been used */ std::map> io_used; - for (const ModulePortId& module_io_port_id : module_io_ports) { - const BasicPort& module_io_port = module_manager.module_port(top_module, module_io_port_id); - io_used[module_io_port_id] = std::vector(module_io_port.get_width(), false); + for (const ModulePortId& module_io_port_id : module_io_ports) { + const BasicPort& module_io_port = + module_manager.module_port(top_module, module_io_port_id); + io_used[module_io_port_id] = + std::vector(module_io_port.get_width(), false); } /* Type mapping between VPR block and Module port */ - std::map atom_block_type_to_module_port_type; - atom_block_type_to_module_port_type[AtomBlockType::INPAD] = ModuleManager::MODULE_GPIN_PORT; - atom_block_type_to_module_port_type[AtomBlockType::OUTPAD] = ModuleManager::MODULE_GPOUT_PORT; + std::map + atom_block_type_to_module_port_type; + atom_block_type_to_module_port_type[AtomBlockType::INPAD] = + ModuleManager::MODULE_GPIN_PORT; + atom_block_type_to_module_port_type[AtomBlockType::OUTPAD] = + ModuleManager::MODULE_GPOUT_PORT; /* See if this I/O should be wired to a benchmark input/output */ /* Add signals from blif benchmark and short-wire them to FPGA I/O PADs - * This brings convenience to checking functionality + * This brings convenience to checking functionality */ - print_verilog_comment(fp, std::string("----- Link BLIF Benchmark I/Os to FPGA I/Os -----")); + print_verilog_comment( + fp, std::string("----- Link BLIF Benchmark I/Os to FPGA I/Os -----")); for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) { /* Bypass non-I/O atom blocks ! */ - if ( (AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) - && (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)) ) { + if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) && + (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk))) { continue; } - + /* If there is a GPIO port, use it directly * Otherwise, should find a GPIN for INPAD * or should find a GPOUT for OUTPAD - */ - std::pair mapped_module_io_info = std::make_pair(ModulePortId::INVALID(), -1); + */ + std::pair mapped_module_io_info = + std::make_pair(ModulePortId::INVALID(), -1); for (const ModulePortId& module_io_port_id : module_io_ports) { - const BasicPort& module_io_port = module_manager.module_port(top_module, module_io_port_id); + const BasicPort& module_io_port = + module_manager.module_port(top_module, module_io_port_id); /* Find the index of the mapped GPIO in top-level FPGA fabric */ - size_t temp_io_index = io_location_map.io_index(place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.x, - place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.y, - place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.sub_tile, - module_io_port.get_name()); + size_t temp_io_index = io_location_map.io_index( + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.x, + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.y, + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.sub_tile, + module_io_port.get_name()); /* Bypass invalid index (not mapped to this GPIO port) */ if (size_t(-1) == temp_io_index) { @@ -323,74 +342,100 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp, } /* If the port is an GPIO port, just use it */ - if (ModuleManager::MODULE_GPIO_PORT == module_manager.port_type(top_module, module_io_port_id)) { - mapped_module_io_info = std::make_pair(module_io_port_id, temp_io_index); + if (ModuleManager::MODULE_GPIO_PORT == + module_manager.port_type(top_module, module_io_port_id)) { + mapped_module_io_info = + std::make_pair(module_io_port_id, temp_io_index); break; } /* If this is an INPAD, we can use an GPIN port (if available) */ - if (atom_block_type_to_module_port_type[atom_ctx.nlist.block_type(atom_blk)] == module_manager.port_type(top_module, module_io_port_id)) { - mapped_module_io_info = std::make_pair(module_io_port_id, temp_io_index); + if (atom_block_type_to_module_port_type[atom_ctx.nlist.block_type( + atom_blk)] == + module_manager.port_type(top_module, module_io_port_id)) { + mapped_module_io_info = + std::make_pair(module_io_port_id, temp_io_index); break; } } /* We must find a valid one */ - VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, mapped_module_io_info.first)); + VTR_ASSERT(true == module_manager.valid_module_port_id( + top_module, mapped_module_io_info.first)); VTR_ASSERT(size_t(-1) != mapped_module_io_info.second); /* Ensure that IO index is in range */ - BasicPort module_mapped_io_port = module_manager.module_port(top_module, mapped_module_io_info.first); + BasicPort module_mapped_io_port = + module_manager.module_port(top_module, mapped_module_io_info.first); size_t io_index = mapped_module_io_info.second; - /* Set the port pin index */ + /* Set the port pin index */ VTR_ASSERT(io_index < module_mapped_io_port.get_width()); - module_mapped_io_port.set_name(module_mapped_io_port.get_name() + net_name_postfix); + module_mapped_io_port.set_name(module_mapped_io_port.get_name() + + net_name_postfix); module_mapped_io_port.set_width(io_index, io_index); - /* The block may be renamed as it contains special characters which violate Verilog syntax */ + /* The block may be renamed as it contains special characters which violate + * Verilog syntax */ std::string block_name = atom_ctx.nlist.block_name(atom_blk); if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); - } + } /* Note that VPR added a prefix to the name of output blocks - * We can remove this when specified through input argument + * We can remove this when specified through input argument */ if (AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)) { block_name = remove_atom_block_name_prefix(block_name); } - /* Create the port for benchmark I/O, due to BLIF benchmark, each I/O always has a size of 1 - * In addition, the input and output ports may have different postfix in naming - * due to verification context! Here, we give full customization on naming + /* Create the port for benchmark I/O, due to BLIF benchmark, each I/O always + * has a size of 1 In addition, the input and output ports may have + * different postfix in naming due to verification context! Here, we give + * full customization on naming */ BasicPort benchmark_io_port; - /* If this benchmark pin belongs to any bus group, use the bus pin instead */ + /* If this benchmark pin belongs to any bus group, use the bus pin instead + */ BusGroupId bus_id = bus_group.find_pin_bus(block_name); BusPinId bus_pin_id = bus_group.find_pin(block_name); if (bus_id) { - block_name = bus_group.bus_port(bus_id).get_name(); + block_name = bus_group.bus_port(bus_id).get_name(); VTR_ASSERT_SAFE(bus_pin_id); - benchmark_io_port.set_width(bus_group.pin_index(bus_pin_id), bus_group.pin_index(bus_pin_id)); + benchmark_io_port.set_width(bus_group.pin_index(bus_pin_id), + bus_group.pin_index(bus_pin_id)); } else { benchmark_io_port.set_width(1); } if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) { /* If the port is a clock, do not add a postfix */ - if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), block_name)) { - benchmark_io_port.set_name(block_name); + if (clock_port_names.end() != std::find(clock_port_names.begin(), + clock_port_names.end(), + block_name)) { + benchmark_io_port.set_name(block_name); } else { - benchmark_io_port.set_name(std::string(block_name + io_input_port_name_postfix)); + benchmark_io_port.set_name( + std::string(block_name + io_input_port_name_postfix)); } - print_verilog_comment(fp, std::string("----- Blif Benchmark input " + block_name + " is mapped to FPGA IOPAD " + module_mapped_io_port.get_name() + "[" + std::to_string(io_index) + "] -----")); - print_verilog_wire_connection(fp, module_mapped_io_port, benchmark_io_port, false); + print_verilog_comment( + fp, std::string("----- Blif Benchmark input " + block_name + + " is mapped to FPGA IOPAD " + + module_mapped_io_port.get_name() + "[" + + std::to_string(io_index) + "] -----")); + print_verilog_wire_connection(fp, module_mapped_io_port, + benchmark_io_port, false); } else { VTR_ASSERT(AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)); - benchmark_io_port.set_name(std::string(block_name + io_output_port_name_postfix)); - print_verilog_comment(fp, std::string("----- Blif Benchmark output " + block_name + " is mapped to FPGA IOPAD " + module_mapped_io_port.get_name() + "[" + std::to_string(io_index) + "] -----")); - print_verilog_wire_connection(fp, benchmark_io_port, module_mapped_io_port, false); + benchmark_io_port.set_name( + std::string(block_name + io_output_port_name_postfix)); + print_verilog_comment( + fp, std::string("----- Blif Benchmark output " + block_name + + " is mapped to FPGA IOPAD " + + module_mapped_io_port.get_name() + "[" + + std::to_string(io_index) + "] -----")); + print_verilog_wire_connection(fp, benchmark_io_port, + module_mapped_io_port, false); } /* Mark this I/O has been used/wired */ @@ -401,27 +446,34 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp, } /* Wire the unused iopads to a constant */ - print_verilog_comment(fp, std::string("----- Wire unused FPGA I/Os to constants -----")); + print_verilog_comment( + fp, std::string("----- Wire unused FPGA I/Os to constants -----")); for (const ModulePortId& module_io_port_id : module_io_ports) { - for (size_t io_index = 0; io_index < io_used[module_io_port_id].size(); ++io_index) { + for (size_t io_index = 0; io_index < io_used[module_io_port_id].size(); + ++io_index) { /* Bypass used iopads */ if (true == io_used[module_io_port_id][io_index]) { continue; } /* Bypass unused output pads */ - if (ModuleManager::MODULE_GPOUT_PORT == module_manager.port_type(top_module, module_io_port_id)) { + if (ModuleManager::MODULE_GPOUT_PORT == + module_manager.port_type(top_module, module_io_port_id)) { continue; } /* Wire to a contant */ - BasicPort module_unused_io_port = module_manager.module_port(top_module, module_io_port_id); - /* Set the port pin index */ - module_unused_io_port.set_name(module_unused_io_port.get_name() + net_name_postfix); + BasicPort module_unused_io_port = + module_manager.module_port(top_module, module_io_port_id); + /* Set the port pin index */ + module_unused_io_port.set_name(module_unused_io_port.get_name() + + net_name_postfix); module_unused_io_port.set_width(io_index, io_index); - std::vector default_values(module_unused_io_port.get_width(), unused_io_value); - print_verilog_wire_constant_values(fp, module_unused_io_port, default_values); + std::vector default_values(module_unused_io_port.get_width(), + unused_io_value); + print_verilog_wire_constant_values(fp, module_unused_io_port, + default_values); } /* Add an empty line as a splitter */ @@ -430,29 +482,30 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp, } /******************************************************************** - * Print Verilog codes to set up a timeout for the simulation + * Print Verilog codes to set up a timeout for the simulation * and dump the waveform to VCD files * * Note that: these codes are tuned for Icarus simulator!!! *******************************************************************/ -void print_verilog_timeout_and_vcd(std::fstream& fp, - const std::string& module_name, - const std::string& vcd_fname, - const std::string& simulation_start_counter_name, - const std::string& error_counter_name, - const float& simulation_time, - const bool& no_self_checking) { +void print_verilog_timeout_and_vcd( + std::fstream& fp, const std::string& module_name, + const std::string& vcd_fname, + const std::string& simulation_start_counter_name, + const std::string& error_counter_name, const float& simulation_time, + const bool& no_self_checking) { /* Validate the file stream */ valid_file_stream(fp); - print_verilog_comment(fp, std::string("----- Begin output waveform to VCD file-------")); + print_verilog_comment( + fp, std::string("----- Begin output waveform to VCD file-------")); fp << "\tinitial begin" << std::endl; fp << "\t\t$dumpfile(\"" << vcd_fname << "\");" << std::endl; fp << "\t\t$dumpvars(1, " << module_name << ");" << std::endl; fp << "\tend" << std::endl; - print_verilog_comment(fp, std::string("----- END output waveform to VCD file -------")); + print_verilog_comment( + fp, std::string("----- END output waveform to VCD file -------")); /* Add an empty line as splitter */ fp << std::endl; @@ -462,19 +515,23 @@ void print_verilog_timeout_and_vcd(std::fstream& fp, fp << "initial begin" << std::endl; if (!no_self_checking) { - fp << "\t" << generate_verilog_port(VERILOG_PORT_CONKT, sim_start_port) << " <= 1'b1;" << std::endl; + fp << "\t" << generate_verilog_port(VERILOG_PORT_CONKT, sim_start_port) + << " <= 1'b1;" << std::endl; } fp << "\t$timeformat(-9, 2, \"ns\", 20);" << std::endl; fp << "\t$display(\"Simulation start\");" << std::endl; - print_verilog_comment(fp, std::string("----- Can be changed by the user for his/her need -------")); + print_verilog_comment( + fp, + std::string("----- Can be changed by the user for his/her need -------")); fp << "\t#" << std::setprecision(10) << simulation_time << std::endl; if (!no_self_checking) { fp << "\tif(" << error_counter_name << " == 0) begin" << std::endl; fp << "\t\t$display(\"Simulation Succeed\");" << std::endl; fp << "\tend else begin" << std::endl; - fp << "\t\t$display(\"Simulation Failed with " << std::string("%d") << " error(s)\", " << error_counter_name << ");" << std::endl; + fp << "\t\t$display(\"Simulation Failed with " << std::string("%d") + << " error(s)\", " << error_counter_name << ");" << std::endl; fp << "\tend" << std::endl; } else { VTR_ASSERT_SAFE(no_self_checking); @@ -494,14 +551,15 @@ void print_verilog_timeout_and_vcd(std::fstream& fp, * Restrictions: * Assume this is a single clock benchmark *******************************************************************/ -std::vector generate_verilog_testbench_clock_port(const std::vector& clock_port_names, - const std::string& default_clock_name) { +std::vector generate_verilog_testbench_clock_port( + const std::vector& clock_port_names, + const std::string& default_clock_name) { std::vector clock_ports; if (0 == clock_port_names.size()) { - clock_ports.push_back(BasicPort(default_clock_name, 1)); + clock_ports.push_back(BasicPort(default_clock_name, 1)); } else { for (const std::string& clock_port_name : clock_port_names) { - clock_ports.push_back(BasicPort(clock_port_name, 1)); + clock_ports.push_back(BasicPort(clock_port_name, 1)); } } @@ -509,80 +567,90 @@ std::vector generate_verilog_testbench_clock_port(const std::vector& clock_port_names, - const std::string& default_clock_name) { - +void print_verilog_testbench_check( + std::fstream& fp, const std::string& simulation_start_counter_name, + const std::string& benchmark_port_postfix, + const std::string& fpga_port_postfix, + const std::string& check_flag_port_postfix, + const std::string& config_done_name, const std::string& error_counter_name, + const AtomContext& atom_ctx, const VprNetlistAnnotation& netlist_annotation, + const std::vector& clock_port_names, + const std::string& default_clock_name) { /* Validate the file stream */ valid_file_stream(fp); /* Add output autocheck */ - print_verilog_comment(fp, std::string("----- Begin checking output vectors -------")); + print_verilog_comment( + fp, std::string("----- Begin checking output vectors -------")); - std::vector clock_ports = generate_verilog_testbench_clock_port(clock_port_names, default_clock_name); + std::vector clock_ports = + generate_verilog_testbench_clock_port(clock_port_names, default_clock_name); - print_verilog_comment(fp, std::string("----- Skip the first falling edge of clock, it is for initialization -------")); + print_verilog_comment(fp, + std::string("----- Skip the first falling edge of " + "clock, it is for initialization -------")); BasicPort sim_start_port(simulation_start_counter_name, 1); - fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, sim_start_port) << ";" << std::endl; + fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, sim_start_port) << ";" + << std::endl; fp << std::endl; /* TODO: This is limitation when multiple clock signals exist - * Ideally, all the input signals are generated by different clock edges, + * Ideally, all the input signals are generated by different clock edges, * depending which clock domain the signals belong to * Currently, as we lack the information, we only use the first clock signal */ VTR_ASSERT(1 <= clock_ports.size()); - fp << "\talways@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, clock_ports[0]) << ") begin" << std::endl; - fp << "\t\tif (1'b1 == " << generate_verilog_port(VERILOG_PORT_CONKT, sim_start_port) << ") begin" << std::endl; + fp << "\talways@(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, clock_ports[0]) << ") begin" + << std::endl; + fp << "\t\tif (1'b1 == " + << generate_verilog_port(VERILOG_PORT_CONKT, sim_start_port) << ") begin" + << std::endl; fp << "\t\t"; print_verilog_register_connection(fp, sim_start_port, sim_start_port, true); fp << "\t\tend else " << std::endl; - /* If there is a config done signal specified, consider it as a trigger on checking */ + /* 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 << "if (1'b1 == " << config_done_name << ") "; } fp << "begin" << std::endl; for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) { /* Bypass non-I/O atom blocks ! */ - if ( (AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) - && (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)) ) { + if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) && + (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk))) { continue; } - /* The block may be renamed as it contains special characters which violate Verilog syntax */ + /* The block may be renamed as it contains special characters which violate + * Verilog syntax */ std::string block_name = atom_ctx.nlist.block_name(atom_blk); if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); - } + } if (AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)) { - block_name = remove_atom_block_name_prefix(block_name); - fp << "\t\t\tif(!(" << block_name << fpga_port_postfix; - fp << " === " << block_name << benchmark_port_postfix; - fp << ") && !(" << block_name << benchmark_port_postfix; - fp << " === 1'bx)) begin" << std::endl; - fp << "\t\t\t\t" << block_name << check_flag_port_postfix << " <= 1'b1;" << std::endl; - fp << "\t\t\tend else begin" << std::endl; - fp << "\t\t\t\t" << block_name << check_flag_port_postfix << "<= 1'b0;" << std::endl; - fp << "\t\t\tend" << std::endl; + block_name = remove_atom_block_name_prefix(block_name); + fp << "\t\t\tif(!(" << block_name << fpga_port_postfix; + fp << " === " << block_name << benchmark_port_postfix; + fp << ") && !(" << block_name << benchmark_port_postfix; + fp << " === 1'bx)) begin" << std::endl; + fp << "\t\t\t\t" << block_name << check_flag_port_postfix << " <= 1'b1;" + << std::endl; + fp << "\t\t\tend else begin" << std::endl; + fp << "\t\t\t\t" << block_name << check_flag_port_postfix << "<= 1'b0;" + << std::endl; + fp << "\t\t\tend" << std::endl; } - } + } fp << "\t\tend" << std::endl; fp << "\tend" << std::endl; @@ -595,17 +663,22 @@ void print_verilog_testbench_check(std::fstream& fp, continue; } - /* The block may be renamed as it contains special characters which violate Verilog syntax */ + /* The block may be renamed as it contains special characters which violate + * Verilog syntax */ std::string block_name = atom_ctx.nlist.block_name(atom_blk); if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); - } + } block_name = remove_atom_block_name_prefix(block_name); - fp << "\talways@(posedge " << block_name << check_flag_port_postfix << ") begin" << std::endl; - fp << "\t\tif(" << block_name << check_flag_port_postfix << ") begin" << std::endl; - fp << "\t\t\t" << error_counter_name << " = " << error_counter_name << " + 1;" << std::endl; - fp << "\t\t\t$display(\"Mismatch on " << block_name << fpga_port_postfix << " at time = " << std::string("%t") << "\", $realtime);" << std::endl; + fp << "\talways@(posedge " << block_name << check_flag_port_postfix + << ") begin" << std::endl; + fp << "\t\tif(" << block_name << check_flag_port_postfix << ") begin" + << std::endl; + fp << "\t\t\t" << error_counter_name << " = " << error_counter_name + << " + 1;" << std::endl; + fp << "\t\t\t$display(\"Mismatch on " << block_name << fpga_port_postfix + << " at time = " << std::string("%t") << "\", $realtime);" << std::endl; fp << "\t\tend" << std::endl; fp << "\tend" << std::endl; @@ -624,41 +697,53 @@ void print_verilog_testbench_check(std::fstream& fp, * In such case, this clock will not be wired to the benchmark module * but be only used as a synchronizer in verification *******************************************************************/ -void print_verilog_testbench_clock_stimuli(std::fstream& fp, - const PinConstraints& pin_constraints, - const SimulationSetting& simulation_parameters, - const std::vector& clock_ports) { +void print_verilog_testbench_clock_stimuli( + std::fstream& fp, const PinConstraints& pin_constraints, + const SimulationSetting& simulation_parameters, + const std::vector& clock_ports) { /* Validate the file stream */ valid_file_stream(fp); for (const BasicPort& clock_port : clock_ports) { - print_verilog_comment(fp, std::string("----- Clock '") + clock_port.get_name() + std::string("' Initialization -------")); + print_verilog_comment(fp, std::string("----- Clock '") + + clock_port.get_name() + + std::string("' Initialization -------")); /* Find the corresponding clock frequency from the simulation parameters */ - float clk_freq_to_use = (0.5 / simulation_parameters.default_operating_clock_frequency()) / VERILOG_SIM_TIMESCALE; - /* Check pin constraints to see if this clock is constrained to a specific pin - * If constrained, + float clk_freq_to_use = + (0.5 / simulation_parameters.default_operating_clock_frequency()) / + VERILOG_SIM_TIMESCALE; + /* Check pin constraints to see if this clock is constrained to a specific + * pin If constrained, * - connect this clock to default values if it is set to be OPEN - * - connect this clock to a specific clock source from simulation settings!!! + * - connect this clock to a specific clock source from simulation + * settings!!! */ VTR_ASSERT(1 == clock_port.get_width()); - for (const PinConstraintId& pin_constraint : pin_constraints.pin_constraints()) { + for (const PinConstraintId& pin_constraint : + pin_constraints.pin_constraints()) { if (clock_port.get_name() != pin_constraints.net(pin_constraint)) { continue; } /* Skip all the unrelated pin constraints */ VTR_ASSERT(clock_port.get_name() == pin_constraints.net(pin_constraint)); - /* Try to find which clock source is considered in simulation settings for this pin */ - for (const SimulationClockId& sim_clock_id : simulation_parameters.operating_clocks()) { - if (pin_constraints.pin(pin_constraint) == simulation_parameters.clock_port(sim_clock_id)) { - clk_freq_to_use = (0.5 / simulation_parameters.clock_frequency(sim_clock_id)) / VERILOG_SIM_TIMESCALE; + /* Try to find which clock source is considered in simulation settings for + * this pin */ + for (const SimulationClockId& sim_clock_id : + simulation_parameters.operating_clocks()) { + if (pin_constraints.pin(pin_constraint) == + simulation_parameters.clock_port(sim_clock_id)) { + clk_freq_to_use = + (0.5 / simulation_parameters.clock_frequency(sim_clock_id)) / + VERILOG_SIM_TIMESCALE; } } } fp << "\tinitial begin" << std::endl; /* Create clock stimuli */ - fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << " <= 1'b0;" << std::endl; + fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) + << " <= 1'b0;" << std::endl; fp << "\t\twhile(1) begin" << std::endl; fp << "\t\t\t#" << std::setprecision(10) << clk_freq_to_use << std::endl; fp << "\t\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, clock_port); @@ -678,17 +763,15 @@ void print_verilog_testbench_clock_stimuli(std::fstream& fp, * Generate random stimulus for the input ports (non-clock signals) * For clock signals, please use print_verilog_testbench_clock_stimuli *******************************************************************/ -void print_verilog_testbench_random_stimuli(std::fstream& fp, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const ModuleManager& module_manager, - const FabricGlobalPortInfo& global_ports, - const PinConstraints& pin_constraints, - const std::vector& clock_port_names, - const std::string& input_port_postfix, - const std::string& check_flag_port_postfix, - const std::vector& clock_ports, - const bool& no_self_checking) { +void print_verilog_testbench_random_stimuli( + std::fstream& fp, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const ModuleManager& module_manager, const FabricGlobalPortInfo& global_ports, + const PinConstraints& pin_constraints, + const std::vector& clock_port_names, + const std::string& input_port_postfix, + const std::string& check_flag_port_postfix, + const std::vector& clock_ports, const bool& no_self_checking) { /* Validate the file stream */ valid_file_stream(fp); @@ -698,35 +781,41 @@ void print_verilog_testbench_random_stimuli(std::fstream& fp, for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) { /* Bypass non-I/O atom blocks ! */ - if ( (AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) - && (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)) ) { + if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) && + (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk))) { continue; } - /* The block may be renamed as it contains special characters which violate Verilog syntax */ + /* The block may be renamed as it contains special characters which violate + * Verilog syntax */ std::string block_name = atom_ctx.nlist.block_name(atom_blk); if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); - } + } if (AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)) { block_name = remove_atom_block_name_prefix(block_name); } /* Bypass clock ports because their stimulus cannot be random */ - if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), block_name)) { + if (clock_port_names.end() != std::find(clock_port_names.begin(), + clock_port_names.end(), + block_name)) { continue; } - /* Bypass any constained net that are mapped to a global port of the FPGA fabric - * because their stimulus cannot be random + /* Bypass any constained net that are mapped to a global port of the FPGA + * fabric because their stimulus cannot be random */ - if (true == port_is_fabric_global_reset_port(global_ports, module_manager, pin_constraints.net_pin(block_name))) { + if (true == + port_is_fabric_global_reset_port(global_ports, module_manager, + pin_constraints.net_pin(block_name))) { continue; } /* TODO: find the clock inputs will be initialized later */ if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) { - fp << "\t\t" << block_name + input_port_postfix << " <= 1'b0;" << std::endl; + fp << "\t\t" << block_name + input_port_postfix << " <= 1'b0;" + << std::endl; } } @@ -734,23 +823,26 @@ void print_verilog_testbench_random_stimuli(std::fstream& fp, if (!no_self_checking) { /* Add an empty line as splitter */ fp << std::endl; - + for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) { /* Bypass non-I/O atom blocks ! */ if (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)) { continue; } - /* The block may be renamed as it contains special characters which violate Verilog syntax */ + /* The block may be renamed as it contains special characters which + * violate Verilog syntax */ std::string block_name = atom_ctx.nlist.block_name(atom_blk); if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); - } + } block_name = remove_atom_block_name_prefix(block_name); /* Each logical block assumes a single-width port */ - BasicPort output_port(std::string(block_name + check_flag_port_postfix), 1); - fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, output_port) << " <= 1'b0;" << std::endl; + BasicPort output_port(std::string(block_name + check_flag_port_postfix), + 1); + fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, output_port) + << " <= 1'b0;" << std::endl; } } @@ -762,44 +854,52 @@ void print_verilog_testbench_random_stimuli(std::fstream& fp, print_verilog_comment(fp, std::string("----- Input Stimulus -------")); /* TODO: This is limitation when multiple clock signals exist - * Ideally, all the input signals are generated by different clock edges, + * Ideally, all the input signals are generated by different clock edges, * depending which clock domain the signals belong to * Currently, as we lack the information, we only use the first clock signal */ VTR_ASSERT(1 <= clock_ports.size()); - fp << "\talways@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, clock_ports[0]) << ") begin" << std::endl; + fp << "\talways@(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, clock_ports[0]) << ") begin" + << std::endl; for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) { /* Bypass non-I/O atom blocks ! */ - if ( (AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) - && (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)) ) { + if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) && + (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk))) { continue; } - /* The block may be renamed as it contains special characters which violate Verilog syntax */ + /* The block may be renamed as it contains special characters which violate + * Verilog syntax */ std::string block_name = atom_ctx.nlist.block_name(atom_blk); if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); - } + } if (AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)) { block_name = remove_atom_block_name_prefix(block_name); } /* Bypass clock ports because their stimulus cannot be random */ - if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), block_name)) { + if (clock_port_names.end() != std::find(clock_port_names.begin(), + clock_port_names.end(), + block_name)) { continue; } - /* Bypass any constained net that are mapped to a global port of the FPGA fabric - * because their stimulus cannot be random + /* Bypass any constained net that are mapped to a global port of the FPGA + * fabric because their stimulus cannot be random */ - if (true == port_is_fabric_global_reset_port(global_ports, module_manager, pin_constraints.net_pin(block_name))) { + if (true == + port_is_fabric_global_reset_port(global_ports, module_manager, + pin_constraints.net_pin(block_name))) { continue; } /* TODO: find the clock inputs will be initialized later */ if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) { - fp << "\t\t" << block_name + input_port_postfix << " <= $random;" << std::endl; + fp << "\t\t" << block_name + input_port_postfix << " <= $random;" + << std::endl; } } @@ -811,25 +911,23 @@ void print_verilog_testbench_random_stimuli(std::fstream& fp, /******************************************************************** * Print Verilog declaration of shared ports appear in testbenches - * which are - * 1. the shared input ports (registers) to drive both + * which are + * 1. the shared input ports (registers) to drive both * FPGA fabric and benchmark instance * 2. the output ports (wires) for both FPGA fabric and benchmark instance * 3. the checking flag ports to evaluate if outputs matches under the * same input vectors *******************************************************************/ -void print_verilog_testbench_shared_ports(std::fstream& fp, - const ModuleManager& module_manager, - const FabricGlobalPortInfo& global_ports, - const PinConstraints& pin_constraints, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const std::vector& clock_port_names, - const std::string& shared_input_port_postfix, - const std::string& benchmark_output_port_postfix, - const std::string& fpga_output_port_postfix, - const std::string& check_flag_port_postfix, - const bool& no_self_checking) { +void print_verilog_testbench_shared_ports( + std::fstream& fp, const ModuleManager& module_manager, + const FabricGlobalPortInfo& global_ports, + const PinConstraints& pin_constraints, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const std::vector& clock_port_names, + const std::string& shared_input_port_postfix, + const std::string& benchmark_output_port_postfix, + const std::string& fpga_output_port_postfix, + const std::string& check_flag_port_postfix, const bool& no_self_checking) { /* Validate the file stream */ valid_file_stream(fp); @@ -841,24 +939,31 @@ void print_verilog_testbench_shared_ports(std::fstream& fp, continue; } - /* The block may be renamed as it contains special characters which violate Verilog syntax */ + /* The block may be renamed as it contains special characters which violate + * Verilog syntax */ std::string block_name = atom_ctx.nlist.block_name(atom_blk); if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); - } + } /* TODO: Skip clocks because they are handled in another function */ - if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), block_name)) { + if (clock_port_names.end() != std::find(clock_port_names.begin(), + clock_port_names.end(), + block_name)) { continue; } - + /* Each logical block assumes a single-width port */ - BasicPort input_port(block_name + shared_input_port_postfix, 1); + BasicPort input_port(block_name + shared_input_port_postfix, 1); /* For global ports, use wires; otherwise, use registers*/ - if (false == port_is_fabric_global_reset_port(global_ports, module_manager, pin_constraints.net_pin(block_name))) { - fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, input_port) << ";" << std::endl; + if (false == + port_is_fabric_global_reset_port(global_ports, module_manager, + pin_constraints.net_pin(block_name))) { + fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, input_port) << ";" + << std::endl; } else { - fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, input_port) << ";" << std::endl; + fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, input_port) << ";" + << std::endl; } } @@ -874,16 +979,19 @@ void print_verilog_testbench_shared_ports(std::fstream& fp, continue; } - /* The block may be renamed as it contains special characters which violate Verilog syntax */ + /* The block may be renamed as it contains special characters which violate + * Verilog syntax */ std::string block_name = atom_ctx.nlist.block_name(atom_blk); if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); - } + } block_name = remove_atom_block_name_prefix(block_name); /* Each logical block assumes a single-width port */ - BasicPort output_port(std::string(block_name + fpga_output_port_postfix), 1); - fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, output_port) << ";" << std::endl; + BasicPort output_port(std::string(block_name + fpga_output_port_postfix), + 1); + fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, output_port) << ";" + << std::endl; } /* Add an empty line as splitter */ @@ -901,39 +1009,45 @@ void print_verilog_testbench_shared_ports(std::fstream& fp, continue; } - /* The block may be renamed as it contains special characters which violate Verilog syntax */ + /* The block may be renamed as it contains special characters which violate + * Verilog syntax */ std::string block_name = atom_ctx.nlist.block_name(atom_blk); if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); - } + } block_name = remove_atom_block_name_prefix(block_name); /* Each logical block assumes a single-width port */ - BasicPort output_port(std::string(block_name + benchmark_output_port_postfix), 1); - fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, output_port) << ";" << std::endl; + BasicPort output_port( + std::string(block_name + benchmark_output_port_postfix), 1); + fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, output_port) << ";" + << std::endl; } /* Add an empty line as splitter */ fp << std::endl; /* Instantiate register for output comparison */ - print_verilog_comment(fp, std::string("----- Output vectors checking flags -------")); + print_verilog_comment( + fp, std::string("----- Output vectors checking flags -------")); for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) { /* We care only those logic blocks which are output I/Os */ if (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)) { continue; } - /* The block may be renamed as it contains special characters which violate Verilog syntax */ + /* The block may be renamed as it contains special characters which violate + * Verilog syntax */ std::string block_name = atom_ctx.nlist.block_name(atom_blk); if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); - } + } block_name = remove_atom_block_name_prefix(block_name); /* Each logical block assumes a single-width port */ - BasicPort output_port(std::string(block_name + check_flag_port_postfix), 1); - fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, output_port) << ";" << std::endl; + BasicPort output_port(std::string(block_name + check_flag_port_postfix), 1); + fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, output_port) << ";" + << std::endl; } /* Add an empty line as splitter */ @@ -948,16 +1062,12 @@ void print_verilog_testbench_shared_ports(std::fstream& fp, * The hierarchy walkthrough collects the full paths for the primitive modules * in the graph of modules *******************************************************************/ -static -void rec_print_verilog_testbench_primitive_module_signal_initialization(std::fstream& fp, - const std::string& hie_path, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const std::vector& circuit_input_ports, - const ModuleManager& module_manager, - const ModuleId& parent_module, - const ModuleId& primitive_module, - const bool& deposit_random_values) { +static void rec_print_verilog_testbench_primitive_module_signal_initialization( + std::fstream& fp, const std::string& hie_path, + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const std::vector& circuit_input_ports, + const ModuleManager& module_manager, const ModuleId& parent_module, + const ModuleId& primitive_module, const bool& deposit_random_values) { /* Validate the file stream */ valid_file_stream(fp); @@ -967,47 +1077,52 @@ void rec_print_verilog_testbench_primitive_module_signal_initialization(std::fst } /* Go through child modules */ - for (const ModuleId& child_module : module_manager.child_modules(parent_module)) { - /* If the child module is not the primitive module, + for (const ModuleId& child_module : + module_manager.child_modules(parent_module)) { + /* If the child module is not the primitive module, * we recursively visit the child module */ - for (const size_t& child_instance : module_manager.child_module_instances(parent_module, child_module)) { - std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); + for (const size_t& child_instance : + module_manager.child_module_instances(parent_module, child_module)) { + std::string instance_name = module_manager.instance_name( + parent_module, child_module, child_instance); /* Use default instanec name if not assigned */ if (true == instance_name.empty()) { - instance_name = generate_instance_name(module_manager.module_name(child_module), child_instance); + instance_name = generate_instance_name( + module_manager.module_name(child_module), child_instance); } - + std::string child_hie_path = hie_path + "." + instance_name; if (child_module != primitive_module) { - rec_print_verilog_testbench_primitive_module_signal_initialization(fp, - child_hie_path, - circuit_lib, circuit_model, circuit_input_ports, - module_manager, child_module, - primitive_module, - deposit_random_values); + rec_print_verilog_testbench_primitive_module_signal_initialization( + fp, child_hie_path, circuit_lib, circuit_model, circuit_input_ports, + module_manager, child_module, primitive_module, + deposit_random_values); } else { - /* If the child module is the primitive module, + /* If the child module is the primitive module, * we output the signal initialization codes for the input ports */ VTR_ASSERT_SAFE(child_module == primitive_module); - print_verilog_comment(fp, std::string("------ BEGIN driver initialization -----")); + print_verilog_comment( + fp, std::string("------ BEGIN driver initialization -----")); fp << "\tinitial begin" << std::endl; for (const auto& input_port : circuit_input_ports) { /* Only for formal verification: deposite a zero signal values */ /* Initialize each input port */ - BasicPort input_port_info(circuit_lib.port_lib_name(input_port), circuit_lib.port_size(input_port)); + BasicPort input_port_info(circuit_lib.port_lib_name(input_port), + circuit_lib.port_size(input_port)); input_port_info.set_origin_port_width(input_port_info.get_width()); fp << "\t\t$deposit("; fp << child_hie_path << "."; - fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info, false); - - if (!deposit_random_values) { + fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info, + false); - fp << ", " << circuit_lib.port_size(input_port) << "'b" << std::string(circuit_lib.port_size(input_port), '0'); + if (!deposit_random_values) { + fp << ", " << circuit_lib.port_size(input_port) << "'b" + << std::string(circuit_lib.port_size(input_port), '0'); fp << ");" << std::endl; } else { VTR_ASSERT_SAFE(deposit_random_values); @@ -1016,7 +1131,8 @@ void rec_print_verilog_testbench_primitive_module_signal_initialization(std::fst } fp << "\tend" << std::endl; - print_verilog_comment(fp, std::string("------ END driver initialization -----")); + print_verilog_comment( + fp, std::string("------ END driver initialization -----")); } } } @@ -1024,16 +1140,15 @@ void rec_print_verilog_testbench_primitive_module_signal_initialization(std::fst /******************************************************************** * Print signal initialization for Verilog testbenches - * which aim to deposit initial values for the input ports of primitive circuit models: + * which aim to deposit initial values for the input ports of primitive circuit + *models: * - Passgate * - Logic gates (ONLY for MUX2) *******************************************************************/ -void print_verilog_testbench_signal_initialization(std::fstream& fp, - const std::string& top_instance_name, - const CircuitLibrary& circuit_lib, - const ModuleManager& module_manager, - const ModuleId& top_module, - const bool& deposit_random_values) { +void print_verilog_testbench_signal_initialization( + std::fstream& fp, const std::string& top_instance_name, + const CircuitLibrary& circuit_lib, const ModuleManager& module_manager, + const ModuleId& top_module, const bool& deposit_random_values) { /* Validate the file stream */ valid_file_stream(fp); @@ -1041,28 +1156,33 @@ void print_verilog_testbench_signal_initialization(std::fstream& fp, std::vector signal_init_circuit_models; /* Collect the input ports that require signal initialization */ - std::map> signal_init_circuit_ports; + std::map> + signal_init_circuit_ports; - for (const CircuitModelId& model : circuit_lib.models_by_type(CIRCUIT_MODEL_PASSGATE)) { + for (const CircuitModelId& model : + circuit_lib.models_by_type(CIRCUIT_MODEL_PASSGATE)) { signal_init_circuit_models.push_back(model); /* Only 1 input requires signal initialization, * which is the first port, i.e., the datapath inputs */ - std::vector input_ports = circuit_lib.model_input_ports(model); + std::vector input_ports = + circuit_lib.model_input_ports(model); VTR_ASSERT(0 < input_ports.size()); - signal_init_circuit_ports[model].push_back(input_ports[0]); + signal_init_circuit_ports[model].push_back(input_ports[0]); } - for (const CircuitModelId& model : circuit_lib.models_by_type(CIRCUIT_MODEL_GATE)) { + for (const CircuitModelId& model : + circuit_lib.models_by_type(CIRCUIT_MODEL_GATE)) { if (CIRCUIT_MODEL_GATE_MUX2 == circuit_lib.gate_type(model)) { signal_init_circuit_models.push_back(model); /* Only 2 input requires signal initialization, * which is the first two port, i.e., the datapath inputs */ - std::vector input_ports = circuit_lib.model_input_ports(model); + std::vector input_ports = + circuit_lib.model_input_ports(model); VTR_ASSERT(1 < input_ports.size()); - signal_init_circuit_ports[model].push_back(input_ports[0]); - signal_init_circuit_ports[model].push_back(input_ports[1]); + signal_init_circuit_ports[model].push_back(input_ports[0]); + signal_init_circuit_ports[model].push_back(input_ports[1]); } } @@ -1073,18 +1193,19 @@ void print_verilog_testbench_signal_initialization(std::fstream& fp, /* Add signal initialization Verilog codes */ fp << std::endl; - for (const CircuitModelId& signal_init_circuit_model : signal_init_circuit_models) { - /* Find the module id corresponding to the circuit model from module graph */ - ModuleId primitive_module = module_manager.find_module(circuit_lib.model_name(signal_init_circuit_model)); + for (const CircuitModelId& signal_init_circuit_model : + signal_init_circuit_models) { + /* Find the module id corresponding to the circuit model from module graph + */ + ModuleId primitive_module = module_manager.find_module( + circuit_lib.model_name(signal_init_circuit_model)); VTR_ASSERT(true == module_manager.valid_module_id(primitive_module)); /* Find all the instances created by the circuit model across the fabric*/ - rec_print_verilog_testbench_primitive_module_signal_initialization(fp, - top_instance_name, - circuit_lib, signal_init_circuit_model, signal_init_circuit_ports.at(signal_init_circuit_model), - module_manager, top_module, - primitive_module, - deposit_random_values); + rec_print_verilog_testbench_primitive_module_signal_initialization( + fp, top_instance_name, circuit_lib, signal_init_circuit_model, + signal_init_circuit_ports.at(signal_init_circuit_model), module_manager, + top_module, primitive_module, deposit_random_values); } } diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.h b/openfpga/src/fpga_verilog/verilog_testbench_utils.h index 7803be4d0..2aedd18e3 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.h +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.h @@ -7,17 +7,16 @@ #include #include #include -#include "module_manager.h" + +#include "bus_group.h" #include "circuit_library.h" -#include "vpr_context.h" -#include "io_location_map.h" -#include "vpr_netlist_annotation.h" #include "fabric_global_port_info.h" +#include "io_location_map.h" +#include "module_manager.h" #include "pin_constraints.h" #include "simulation_setting.h" -#include "fabric_global_port_info.h" -#include "pin_constraints.h" -#include "bus_group.h" +#include "vpr_context.h" +#include "vpr_netlist_annotation.h" /******************************************************************** * Function declaration @@ -33,93 +32,79 @@ void print_verilog_testbench_fpga_instance(std::fstream& fp, const std::string& net_postfix, const bool& explicit_port_mapping); -void print_verilog_testbench_benchmark_instance(std::fstream& fp, - const std::string& module_name, - const std::string& instance_name, - const std::string& module_input_port_postfix, - const std::string& module_output_port_postfix, - const std::string& input_port_postfix, - const std::string& output_port_postfix, - const std::vector& clock_port_names, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const bool& use_explicit_port_map); +void print_verilog_testbench_benchmark_instance( + std::fstream& fp, const std::string& module_name, + const std::string& instance_name, + const std::string& module_input_port_postfix, + const std::string& module_output_port_postfix, + const std::string& input_port_postfix, const std::string& output_port_postfix, + const std::vector& clock_port_names, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const PinConstraints& pin_constraints, const BusGroup& bus_group, + const bool& use_explicit_port_map); -void print_verilog_testbench_connect_fpga_ios(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const IoLocationMap& io_location_map, - const VprNetlistAnnotation& netlist_annotation, - const BusGroup& bus_group, - const std::string& net_name_postfix, - const std::string& io_input_port_name_postfix, - const std::string& io_output_port_name_postfix, - const std::vector& clock_port_names, - const size_t& unused_io_value); +void print_verilog_testbench_connect_fpga_ios( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, const AtomContext& atom_ctx, + const PlacementContext& place_ctx, const IoLocationMap& io_location_map, + const VprNetlistAnnotation& netlist_annotation, const BusGroup& bus_group, + const std::string& net_name_postfix, + const std::string& io_input_port_name_postfix, + const std::string& io_output_port_name_postfix, + const std::vector& clock_port_names, + const size_t& unused_io_value); -void print_verilog_timeout_and_vcd(std::fstream& fp, - const std::string& module_name, - const std::string& vcd_fname, - const std::string& simulation_start_counter_name, - const std::string& error_counter_name, - const float& simulation_time, - const bool& no_self_checking); +void print_verilog_timeout_and_vcd( + std::fstream& fp, const std::string& module_name, + const std::string& vcd_fname, + const std::string& simulation_start_counter_name, + const std::string& error_counter_name, const float& simulation_time, + const bool& no_self_checking); -std::vector generate_verilog_testbench_clock_port(const std::vector& clock_port_names, - const std::string& default_clock_name); +std::vector generate_verilog_testbench_clock_port( + const std::vector& clock_port_names, + const std::string& default_clock_name); -void print_verilog_testbench_check(std::fstream& fp, - const std::string& simulation_start_counter_name, - const std::string& benchmark_port_postfix, - const std::string& fpga_port_postfix, - const std::string& check_flag_port_postfix, - const std::string& config_done_name, - const std::string& error_counter_name, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const std::vector& clock_port_names, - const std::string& default_clock_name); +void print_verilog_testbench_check( + std::fstream& fp, const std::string& simulation_start_counter_name, + const std::string& benchmark_port_postfix, + const std::string& fpga_port_postfix, + const std::string& check_flag_port_postfix, + const std::string& config_done_name, const std::string& error_counter_name, + const AtomContext& atom_ctx, const VprNetlistAnnotation& netlist_annotation, + const std::vector& clock_port_names, + const std::string& default_clock_name); -void print_verilog_testbench_clock_stimuli(std::fstream& fp, - const PinConstraints& pin_constraints, - const SimulationSetting& simulation_parameters, - const std::vector& clock_ports); +void print_verilog_testbench_clock_stimuli( + std::fstream& fp, const PinConstraints& pin_constraints, + const SimulationSetting& simulation_parameters, + const std::vector& clock_ports); -void print_verilog_testbench_random_stimuli(std::fstream& fp, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const ModuleManager& module_manager, - const FabricGlobalPortInfo& global_ports, - const PinConstraints& pin_constraints, - const std::vector& clock_port_names, - const std::string& input_port_postfix, - const std::string& check_flag_port_postfix, - const std::vector& clock_ports, - const bool& no_self_checking); +void print_verilog_testbench_random_stimuli( + std::fstream& fp, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const ModuleManager& module_manager, const FabricGlobalPortInfo& global_ports, + const PinConstraints& pin_constraints, + const std::vector& clock_port_names, + const std::string& input_port_postfix, + const std::string& check_flag_port_postfix, + const std::vector& clock_ports, const bool& no_self_checking); -void print_verilog_testbench_shared_ports(std::fstream& fp, - const ModuleManager& module_manager, - const FabricGlobalPortInfo& global_ports, - const PinConstraints& pin_constraints, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const std::vector& clock_port_names, - const std::string& shared_input_port_postfix, - const std::string& benchmark_output_port_postfix, - const std::string& fpga_output_port_postfix, - const std::string& check_flag_port_postfix, - const bool& no_self_checking); +void print_verilog_testbench_shared_ports( + std::fstream& fp, const ModuleManager& module_manager, + const FabricGlobalPortInfo& global_ports, + const PinConstraints& pin_constraints, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const std::vector& clock_port_names, + const std::string& shared_input_port_postfix, + const std::string& benchmark_output_port_postfix, + const std::string& fpga_output_port_postfix, + const std::string& check_flag_port_postfix, const bool& no_self_checking); -void print_verilog_testbench_signal_initialization(std::fstream& fp, - const std::string& top_instance_name, - const CircuitLibrary& circuit_lib, - const ModuleManager& module_manager, - const ModuleId& top_module, - const bool& deposit_random_values); +void print_verilog_testbench_signal_initialization( + std::fstream& fp, const std::string& top_instance_name, + const CircuitLibrary& circuit_lib, const ModuleManager& module_manager, + const ModuleId& top_module, const bool& deposit_random_values); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_top_module.cpp b/openfpga/src/fpga_verilog/verilog_top_module.cpp index 0d4084074..0fb6b0d0c 100644 --- a/openfpga/src/fpga_verilog/verilog_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_module.cpp @@ -2,9 +2,9 @@ * This file includes functions that are used to print the top-level * module for the FPGA fabric in Verilog format *******************************************************************/ +#include #include #include -#include /* Headers from vtrutil library */ #include "vtr_assert.h" @@ -12,22 +12,20 @@ /* Headers from openfpgautil library */ #include "openfpga_digest.h" - #include "openfpga_naming.h" - #include "verilog_constants.h" -#include "verilog_writer_utils.h" #include "verilog_module_writer.h" #include "verilog_top_module.h" +#include "verilog_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** * Print the top-level module for the FPGA fabric in Verilog format - * This function will + * This function will * 1. name the top-level module - * 2. include dependent netlists + * 2. include dependent netlists * - User defined netlists * - Auto-generated netlists * 3. Add the submodules to the top-level graph @@ -38,14 +36,16 @@ void print_verilog_top_module(NetlistManager& netlist_manager, const ModuleManager& module_manager, const std::string& verilog_dir, const FabricVerilogOption& options) { - /* Create a module as the top-level fabric, and add it to the module manager */ + /* Create a module as the top-level fabric, and add it to the module manager + */ std::string top_module_name = generate_fpga_top_module_name(); ModuleId top_module = module_manager.find_module(top_module_name); VTR_ASSERT(true == module_manager.valid_module_id(top_module)); /* Start printing out Verilog netlists */ /* Create the file name for Verilog netlist */ - std::string verilog_fname(generate_fpga_top_netlist_name(std::string(VERILOG_NETLIST_FILE_POSTFIX))); + std::string verilog_fname( + generate_fpga_top_netlist_name(std::string(VERILOG_NETLIST_FILE_POSTFIX))); std::string verilog_fpath(verilog_dir + verilog_fname); VTR_LOG("Writing Verilog netlist for top-level module of FPGA fabric '%s'...", @@ -57,14 +57,11 @@ void print_verilog_top_module(NetlistManager& netlist_manager, check_file_stream(verilog_fpath.c_str(), fp); - print_verilog_file_header(fp, - std::string("Top-level Verilog module for FPGA"), - options.time_stamp()); + print_verilog_file_header( + fp, std::string("Top-level Verilog module for FPGA"), options.time_stamp()); /* Write the module content in Verilog format */ - write_verilog_module_to_file(fp, - module_manager, - top_module, + write_verilog_module_to_file(fp, module_manager, top_module, options.explicit_port_mapping(), options.default_net_type()); @@ -82,7 +79,8 @@ void print_verilog_top_module(NetlistManager& netlist_manager, nlist_id = netlist_manager.add_netlist(verilog_fpath); } VTR_ASSERT(nlist_id); - netlist_manager.set_netlist_type(nlist_id, NetlistManager::TOP_MODULE_NETLIST); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::TOP_MODULE_NETLIST); VTR_LOG("Done\n"); } diff --git a/openfpga/src/fpga_verilog/verilog_top_module.h b/openfpga/src/fpga_verilog/verilog_top_module.h index 33180729f..b4b0bab20 100644 --- a/openfpga/src/fpga_verilog/verilog_top_module.h +++ b/openfpga/src/fpga_verilog/verilog_top_module.h @@ -5,9 +5,10 @@ * Include header files that are required by function declaration *******************************************************************/ #include + +#include "fabric_verilog_options.h" #include "module_manager.h" #include "netlist_manager.h" -#include "fabric_verilog_options.h" /******************************************************************** * Function declaration diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 689b7f569..819bda9fb 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -2,40 +2,35 @@ * This file includes functions that are used to create * an auto-check top-level testbench for a FPGA fabric *******************************************************************/ +#include #include #include -#include /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgashell library */ #include "command_exit_codes.h" /* Headers from openfpgautil library */ -#include "openfpga_port.h" -#include "openfpga_digest.h" - #include "bitstream_manager_utils.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" -#include "simulation_utils.h" -#include "openfpga_atom_netlist_utils.h" - -#include "fast_configuration.h" #include "fabric_bitstream_utils.h" #include "fabric_global_port_info_utils.h" - +#include "fast_configuration.h" +#include "openfpga_atom_netlist_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" +#include "openfpga_reserved_words.h" +#include "simulation_utils.h" #include "verilog_constants.h" -#include "verilog_writer_utils.h" #include "verilog_testbench_utils.h" -#include "verilog_top_testbench_memory_bank.h" #include "verilog_top_testbench.h" - #include "verilog_top_testbench_constants.h" +#include "verilog_top_testbench_memory_bank.h" +#include "verilog_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -44,117 +39,133 @@ namespace openfpga { * Generate a simulation clock port name * This function is designed to produce a uniform clock naming for these ports *******************************************************************/ -static -std::string generate_top_testbench_clock_name(const std::string& prefix, - const std::string& port_name) { +static std::string generate_top_testbench_clock_name( + const std::string& prefix, const std::string& port_name) { return prefix + port_name; } - /******************************************************************** * Print local wires for flatten memory (standalone) configuration protocols *******************************************************************/ -static -void print_verilog_top_testbench_flatten_memory_port(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module) { +static void print_verilog_top_testbench_flatten_memory_port( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module) { /* Validate the file stream */ valid_file_stream(fp); /* Print the port for Bit-Line */ print_verilog_comment(fp, std::string("---- Bit Line ports -----")); - ModulePortId bl_port_id = module_manager.find_module_port(top_module, std::string(MEMORY_BL_PORT_NAME)); + ModulePortId bl_port_id = module_manager.find_module_port( + top_module, std::string(MEMORY_BL_PORT_NAME)); BasicPort bl_port = module_manager.module_port(top_module, bl_port_id); fp << generate_verilog_port(VERILOG_PORT_REG, bl_port) << ";" << std::endl; /* Print the port for Word-Line */ print_verilog_comment(fp, std::string("---- Word Line ports -----")); - ModulePortId wl_port_id = module_manager.find_module_port(top_module, std::string(MEMORY_WL_PORT_NAME)); + ModulePortId wl_port_id = module_manager.find_module_port( + top_module, std::string(MEMORY_WL_PORT_NAME)); BasicPort wl_port = module_manager.module_port(top_module, wl_port_id); fp << generate_verilog_port(VERILOG_PORT_REG, wl_port) << ";" << std::endl; } - /******************************************************************** * Print local wires for configuration chain protocols *******************************************************************/ -static -void print_verilog_top_testbench_config_chain_port(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module) { +static void print_verilog_top_testbench_config_chain_port( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module) { /* Validate the file stream */ valid_file_stream(fp); /* Print the head of configuraion-chains here */ print_verilog_comment(fp, std::string("---- Configuration-chain head -----")); - ModulePortId cc_head_port_id = module_manager.find_module_port(top_module, generate_configuration_chain_head_name()); - BasicPort config_chain_head_port = module_manager.module_port(top_module, cc_head_port_id); - fp << generate_verilog_port(VERILOG_PORT_REG, config_chain_head_port) << ";" << std::endl; + ModulePortId cc_head_port_id = module_manager.find_module_port( + top_module, generate_configuration_chain_head_name()); + BasicPort config_chain_head_port = + module_manager.module_port(top_module, cc_head_port_id); + fp << generate_verilog_port(VERILOG_PORT_REG, config_chain_head_port) << ";" + << std::endl; /* Print the tail of configuration-chains here */ print_verilog_comment(fp, std::string("---- Configuration-chain tail -----")); - ModulePortId cc_tail_port_id = module_manager.find_module_port(top_module, generate_configuration_chain_tail_name()); - BasicPort config_chain_tail_port = module_manager.module_port(top_module, cc_tail_port_id); - fp << generate_verilog_port(VERILOG_PORT_WIRE, config_chain_tail_port) << ";" << std::endl; + ModulePortId cc_tail_port_id = module_manager.find_module_port( + top_module, generate_configuration_chain_tail_name()); + BasicPort config_chain_tail_port = + module_manager.module_port(top_module, cc_tail_port_id); + fp << generate_verilog_port(VERILOG_PORT_WIRE, config_chain_tail_port) << ";" + << std::endl; } /******************************************************************** * Print local wires for memory bank configuration protocols *******************************************************************/ -static -void print_verilog_top_testbench_memory_bank_port(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module) { +static void print_verilog_top_testbench_memory_bank_port( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module) { /* Validate the file stream */ valid_file_stream(fp); /* Print the address port for the Bit-Line decoder here */ - print_verilog_comment(fp, std::string("---- Address port for Bit-Line decoder -----")); - ModulePortId bl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_BL_ADDRESS_PORT_NAME)); - BasicPort bl_addr_port = module_manager.module_port(top_module, bl_addr_port_id); + print_verilog_comment( + fp, std::string("---- Address port for Bit-Line decoder -----")); + ModulePortId bl_addr_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); + BasicPort bl_addr_port = + module_manager.module_port(top_module, bl_addr_port_id); - fp << generate_verilog_port(VERILOG_PORT_REG, bl_addr_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, bl_addr_port) << ";" + << std::endl; /* Print the address port for the Word-Line decoder here */ - print_verilog_comment(fp, std::string("---- Address port for Word-Line decoder -----")); - ModulePortId wl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_WL_ADDRESS_PORT_NAME)); - BasicPort wl_addr_port = module_manager.module_port(top_module, wl_addr_port_id); + print_verilog_comment( + fp, std::string("---- Address port for Word-Line decoder -----")); + ModulePortId wl_addr_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); + BasicPort wl_addr_port = + module_manager.module_port(top_module, wl_addr_port_id); - fp << generate_verilog_port(VERILOG_PORT_REG, wl_addr_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, wl_addr_port) << ";" + << std::endl; /* Print the data-input port for the frame-based decoder here */ - print_verilog_comment(fp, std::string("---- Data input port for memory decoders -----")); - ModulePortId din_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_DATA_IN_PORT_NAME)); + print_verilog_comment( + fp, std::string("---- Data input port for memory decoders -----")); + ModulePortId din_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_DATA_IN_PORT_NAME)); BasicPort din_port = module_manager.module_port(top_module, din_port_id); fp << generate_verilog_port(VERILOG_PORT_REG, din_port) << ";" << std::endl; /* Print the optional readback port for the decoder here */ - print_verilog_comment(fp, std::string("---- Readback port for memory decoders -----")); - ModulePortId readback_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_READBACK_PORT_NAME)); + print_verilog_comment( + fp, std::string("---- Readback port for memory decoders -----")); + ModulePortId readback_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_READBACK_PORT_NAME)); if (readback_port_id) { - BasicPort readback_port = module_manager.module_port(top_module, readback_port_id); - fp << generate_verilog_port(VERILOG_PORT_WIRE, readback_port) << ";" << std::endl; + BasicPort readback_port = + module_manager.module_port(top_module, readback_port_id); + fp << generate_verilog_port(VERILOG_PORT_WIRE, readback_port) << ";" + << std::endl; /* Disable readback in full testbenches */ - print_verilog_wire_constant_values(fp, readback_port, std::vector(readback_port.get_width(), 0)); + print_verilog_wire_constant_values( + fp, readback_port, std::vector(readback_port.get_width(), 0)); } /* Generate enable signal waveform here: - * which is a 90 degree phase shift than the programming clock + * which is a 90 degree phase shift than the programming clock */ - print_verilog_comment(fp, std::string("---- Wire enable port of memory decoders -----")); - ModulePortId en_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_ENABLE_PORT_NAME)); + print_verilog_comment( + fp, std::string("---- Wire enable port of memory decoders -----")); + ModulePortId en_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort en_port = module_manager.module_port(top_module, en_port_id); - BasicPort en_register_port(std::string(en_port.get_name() + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); + BasicPort en_register_port( + std::string(en_port.get_name() + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); fp << generate_verilog_port(VERILOG_PORT_WIRE, en_port) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_REG, en_register_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, en_register_port) << ";" + << std::endl; write_tab_to_file(fp, 1); fp << "assign "; @@ -166,45 +177,48 @@ void print_verilog_top_testbench_memory_bank_port(std::fstream& fp, fp << ";" << std::endl; } - /******************************************************************** * Print local wires for frame-based decoder protocols *******************************************************************/ -static -void print_verilog_top_testbench_frame_decoder_port(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module) { +static void print_verilog_top_testbench_frame_decoder_port( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module) { /* Validate the file stream */ valid_file_stream(fp); /* Print the address port for the frame-based decoder here */ - print_verilog_comment(fp, std::string("---- Address port for frame-based decoder -----")); - ModulePortId addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_ADDRESS_PORT_NAME)); + print_verilog_comment( + fp, std::string("---- Address port for frame-based decoder -----")); + ModulePortId addr_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_ADDRESS_PORT_NAME)); BasicPort addr_port = module_manager.module_port(top_module, addr_port_id); fp << generate_verilog_port(VERILOG_PORT_REG, addr_port) << ";" << std::endl; /* Print the data-input port for the frame-based decoder here */ - print_verilog_comment(fp, std::string("---- Data input port for frame-based decoder -----")); - ModulePortId din_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_DATA_IN_PORT_NAME)); + print_verilog_comment( + fp, std::string("---- Data input port for frame-based decoder -----")); + ModulePortId din_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_DATA_IN_PORT_NAME)); BasicPort din_port = module_manager.module_port(top_module, din_port_id); fp << generate_verilog_port(VERILOG_PORT_REG, din_port) << ";" << std::endl; /* Generate enable signal waveform here: - * which is a 90 degree phase shift than the programming clock + * which is a 90 degree phase shift than the programming clock */ - print_verilog_comment(fp, std::string("---- Wire enable port of frame-based decoders -----")); - ModulePortId en_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_ENABLE_PORT_NAME)); + print_verilog_comment( + fp, std::string("---- Wire enable port of frame-based decoders -----")); + ModulePortId en_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort en_port = module_manager.module_port(top_module, en_port_id); - BasicPort en_register_port(std::string(en_port.get_name() + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); + BasicPort en_register_port( + std::string(en_port.get_name() + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); fp << generate_verilog_port(VERILOG_PORT_WIRE, en_port) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_REG, en_register_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, en_register_port) << ";" + << std::endl; write_tab_to_file(fp, 1); fp << "assign "; @@ -219,50 +233,53 @@ void print_verilog_top_testbench_frame_decoder_port(std::fstream& fp, /******************************************************************** * Print local wires for different types of configuration protocols *******************************************************************/ -static -void print_verilog_top_testbench_config_protocol_port(std::fstream& fp, - const ConfigProtocol& config_protocol, - const ModuleManager& module_manager, - const ModuleId& top_module) { - switch(config_protocol.type()) { - case CONFIG_MEM_STANDALONE: - print_verilog_top_testbench_flatten_memory_port(fp, module_manager, top_module); - break; - case CONFIG_MEM_SCAN_CHAIN: - print_verilog_top_testbench_config_chain_port(fp, module_manager, top_module); - break; - case CONFIG_MEM_QL_MEMORY_BANK: - print_verilog_top_testbench_ql_memory_bank_port(fp, module_manager, top_module, config_protocol); - break; - case CONFIG_MEM_MEMORY_BANK: - print_verilog_top_testbench_memory_bank_port(fp, module_manager, top_module); - break; - case CONFIG_MEM_FRAME_BASED: - print_verilog_top_testbench_frame_decoder_port(fp, - module_manager, top_module); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization!\n"); - exit(1); +static void print_verilog_top_testbench_config_protocol_port( + std::fstream& fp, const ConfigProtocol& config_protocol, + const ModuleManager& module_manager, const ModuleId& top_module) { + switch (config_protocol.type()) { + case CONFIG_MEM_STANDALONE: + print_verilog_top_testbench_flatten_memory_port(fp, module_manager, + top_module); + break; + case CONFIG_MEM_SCAN_CHAIN: + print_verilog_top_testbench_config_chain_port(fp, module_manager, + top_module); + break; + case CONFIG_MEM_QL_MEMORY_BANK: + print_verilog_top_testbench_ql_memory_bank_port( + fp, module_manager, top_module, config_protocol); + break; + case CONFIG_MEM_MEMORY_BANK: + print_verilog_top_testbench_memory_bank_port(fp, module_manager, + top_module); + break; + case CONFIG_MEM_FRAME_BASED: + print_verilog_top_testbench_frame_decoder_port(fp, module_manager, + top_module); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization!\n"); + exit(1); } } /******************************************************************** * Wire the global clock ports of FPGA fabric to local wires *******************************************************************/ -static -void print_verilog_top_testbench_global_clock_ports_stimuli(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricGlobalPortInfo& fabric_global_port_info, - const SimulationSetting& simulation_parameters) { +static void print_verilog_top_testbench_global_clock_ports_stimuli( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info, + const SimulationSetting& simulation_parameters) { /* Validate the file stream */ valid_file_stream(fp); /* Connect global clock ports to operating or programming clock signal */ - for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { - if (false == fabric_global_port_info.global_port_is_clock(fabric_global_port)) { + for (const FabricGlobalPortId& fabric_global_port : + fabric_global_port_info.global_ports()) { + if (false == + fabric_global_port_info.global_port_is_clock(fabric_global_port)) { continue; } /* Reach here, it means we have a global clock to deal with: @@ -272,20 +289,25 @@ void print_verilog_top_testbench_global_clock_ports_stimuli(std::fstream& fp, * connect it to the local wire of operating clock */ /* Find the module port */ - ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port); - VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port)); - + ModulePortId module_global_port = + fabric_global_port_info.global_module_port(fabric_global_port); + VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, + module_global_port)); + /* Skip shift register clocks, they are handled in another way */ - if (true == fabric_global_port_info.global_port_is_shift_register(fabric_global_port)) { + if (true == fabric_global_port_info.global_port_is_shift_register( + fabric_global_port)) { continue; } BasicPort stimuli_clock_port; - if (true == fabric_global_port_info.global_port_is_prog(fabric_global_port)) { + 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); } else { - VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_prog(fabric_global_port)); + VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_prog( + fabric_global_port)); stimuli_clock_port.set_name(std::string(TOP_TB_OP_CLOCK_PORT_NAME)); stimuli_clock_port.set_width(1); } @@ -293,20 +315,28 @@ void print_verilog_top_testbench_global_clock_ports_stimuli(std::fstream& fp, * The wiring will be inverted if the default value of the global port is 1 * Otherwise, the wiring will not be inverted! */ - for (const size_t& pin : module_manager.module_port(top_module, module_global_port).pins()) { - BasicPort global_port_to_connect(module_manager.module_port(top_module, module_global_port).get_name(), pin, pin); + for (const size_t& pin : + module_manager.module_port(top_module, module_global_port).pins()) { + BasicPort global_port_to_connect( + module_manager.module_port(top_module, module_global_port).get_name(), + pin, pin); /* Should try to find a port defintion from simulation parameters - * If found, it means that we need to use special clock name! + * If found, it means that we need to use special clock name! */ - for (const SimulationClockId& sim_clock : simulation_parameters.operating_clocks()) { - if (global_port_to_connect == simulation_parameters.clock_port(sim_clock)) { - stimuli_clock_port.set_name(generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock))); + for (const SimulationClockId& sim_clock : + simulation_parameters.operating_clocks()) { + if (global_port_to_connect == + simulation_parameters.clock_port(sim_clock)) { + stimuli_clock_port.set_name(generate_top_testbench_clock_name( + std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), + simulation_parameters.clock_name(sim_clock))); } } - print_verilog_wire_connection(fp, global_port_to_connect, - stimuli_clock_port, - 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); + print_verilog_wire_connection( + fp, global_port_to_connect, stimuli_clock_port, + 1 == fabric_global_port_info.global_port_default_value( + fabric_global_port)); } } } @@ -314,124 +344,153 @@ void print_verilog_top_testbench_global_clock_ports_stimuli(std::fstream& fp, /******************************************************************** * Wire the global config done ports of FPGA fabric to local wires *******************************************************************/ -static -void print_verilog_top_testbench_global_config_done_ports_stimuli(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricGlobalPortInfo& fabric_global_port_info) { +static void print_verilog_top_testbench_global_config_done_ports_stimuli( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info) { /* Validate the file stream */ valid_file_stream(fp); /* Connect global configuration done ports to configuration done signal */ - for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { + for (const FabricGlobalPortId& fabric_global_port : + fabric_global_port_info.global_ports()) { /* Bypass clock signals, they have been processed */ - if (true == fabric_global_port_info.global_port_is_clock(fabric_global_port)) { + if (true == + fabric_global_port_info.global_port_is_clock(fabric_global_port)) { continue; } - if (false == fabric_global_port_info.global_port_is_config_enable(fabric_global_port)) { + if (false == fabric_global_port_info.global_port_is_config_enable( + fabric_global_port)) { continue; } /* Reach here, it means we have a configuration done port to deal with */ /* Find the module port */ - ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port); - VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port)); + ModulePortId module_global_port = + fabric_global_port_info.global_module_port(fabric_global_port); + VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, + module_global_port)); - BasicPort stimuli_config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); + BasicPort stimuli_config_done_port( + std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); /* Wire the port to the input stimuli: * The wiring will be inverted if the default value of the global port is 1 * Otherwise, the wiring will not be inverted! */ - print_verilog_wire_connection(fp, module_manager.module_port(top_module, module_global_port), - stimuli_config_done_port, - 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); + print_verilog_wire_connection( + fp, module_manager.module_port(top_module, module_global_port), + stimuli_config_done_port, + 1 == + fabric_global_port_info.global_port_default_value(fabric_global_port)); } } /******************************************************************** * Wire the global reset ports of FPGA fabric to local wires *******************************************************************/ -static -void print_verilog_top_testbench_global_reset_ports_stimuli(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const PinConstraints& pin_constraints, - const FabricGlobalPortInfo& fabric_global_port_info, - const bool& active_global_prog_reset) { +static void print_verilog_top_testbench_global_reset_ports_stimuli( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, const PinConstraints& pin_constraints, + const FabricGlobalPortInfo& fabric_global_port_info, + const bool& active_global_prog_reset) { /* Validate the file stream */ valid_file_stream(fp); /* Connect global reset ports to operating or programming reset signal */ - for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { + for (const FabricGlobalPortId& fabric_global_port : + fabric_global_port_info.global_ports()) { /* Bypass clock signals, they have been processed */ - if (true == fabric_global_port_info.global_port_is_clock(fabric_global_port)) { + if (true == + fabric_global_port_info.global_port_is_clock(fabric_global_port)) { continue; } /* Bypass config_done signals, they have been processed */ - if (true == fabric_global_port_info.global_port_is_config_enable(fabric_global_port)) { + if (true == fabric_global_port_info.global_port_is_config_enable( + fabric_global_port)) { continue; } - if (false == fabric_global_port_info.global_port_is_reset(fabric_global_port)) { + if (false == + fabric_global_port_info.global_port_is_reset(fabric_global_port)) { continue; } /* Reach here, it means we have a reset port to deal with */ /* Find the module port */ - ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port); - VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port)); + ModulePortId module_global_port = + fabric_global_port_info.global_module_port(fabric_global_port); + VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, + module_global_port)); /* For global programming reset port, we will active only when specified */ BasicPort stimuli_reset_port; bool activate = true; - if (true == fabric_global_port_info.global_port_is_prog(fabric_global_port)) { + if (true == + fabric_global_port_info.global_port_is_prog(fabric_global_port)) { stimuli_reset_port.set_name(std::string(TOP_TB_PROG_RESET_PORT_NAME)); stimuli_reset_port.set_width(1); activate = active_global_prog_reset; } else { - VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_prog(fabric_global_port)); + VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_prog( + fabric_global_port)); stimuli_reset_port.set_name(std::string(TOP_TB_RESET_PORT_NAME)); stimuli_reset_port.set_width(1); } - BasicPort module_global_port_info = module_manager.module_port(top_module, module_global_port); + BasicPort module_global_port_info = + module_manager.module_port(top_module, module_global_port); - for (size_t pin_id = 0; pin_id < module_global_port_info.pins().size(); ++pin_id) { + for (size_t pin_id = 0; pin_id < module_global_port_info.pins().size(); + ++pin_id) { BasicPort module_global_pin(module_global_port_info.get_name(), module_global_port_info.pins()[pin_id], module_global_port_info.pins()[pin_id]); /* Regular reset port can be mapped by a net from user design */ - if (false == fabric_global_port_info.global_port_is_prog(fabric_global_port)) { - /* If the global port name is in the pin constraints, we should wire it to the constrained pin */ - std::string constrained_net_name = pin_constraints.pin_net(module_global_pin); + if (false == + fabric_global_port_info.global_port_is_prog(fabric_global_port)) { + /* If the global port name is in the pin constraints, we should wire it + * to the constrained pin */ + std::string constrained_net_name = + pin_constraints.pin_net(module_global_pin); - /* - If constrained to a given net in the benchmark, we connect the global pin to the net */ - if ( (false == pin_constraints.unconstrained_net(constrained_net_name)) - && (false == pin_constraints.unmapped_net(constrained_net_name))) { - BasicPort benchmark_pin(constrained_net_name + std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX), 1); - /* Polarity of some input may have to be inverted, as defined in pin constraints - * For example, the reset signal of the benchmark is active low - * while the reset signal of the FPGA fabric is active high (inside FPGA, the reset signal will be inverted) - * However, to ensure correct stimuli to the benchmark, we have to invert the signal + /* - If constrained to a given net in the benchmark, we connect the + * global pin to the net */ + if ((false == + pin_constraints.unconstrained_net(constrained_net_name)) && + (false == pin_constraints.unmapped_net(constrained_net_name))) { + BasicPort benchmark_pin( + constrained_net_name + + std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX), + 1); + /* Polarity of some input may have to be inverted, as defined in pin + * constraints For example, the reset signal of the benchmark is + * active low while the reset signal of the FPGA fabric is active high + * (inside FPGA, the reset signal will be inverted) However, to ensure + * correct stimuli to the benchmark, we have to invert the signal */ - print_verilog_wire_connection(fp, module_global_pin, - benchmark_pin, - PinConstraints::LOGIC_HIGH == pin_constraints.net_default_value(constrained_net_name)); + print_verilog_wire_connection( + fp, module_global_pin, benchmark_pin, + PinConstraints::LOGIC_HIGH == + pin_constraints.net_default_value(constrained_net_name)); continue; /* Finish the net assignment for this reset pin */ } } - + /* Wire the port to the input stimuli: - * The wiring will be inverted if the default value of the global port is 1 - * Otherwise, the wiring will not be inverted! + * The wiring will be inverted if the default value of the global port is + * 1 Otherwise, the wiring will not be inverted! */ if (true == activate) { - print_verilog_wire_connection(fp, module_global_pin, - stimuli_reset_port, - 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); + print_verilog_wire_connection( + fp, module_global_pin, stimuli_reset_port, + 1 == fabric_global_port_info.global_port_default_value( + fabric_global_port)); } else { VTR_ASSERT_SAFE(false == activate); - print_verilog_wire_constant_values(fp, module_global_pin, - std::vector(1, fabric_global_port_info.global_port_default_value(fabric_global_port))); + print_verilog_wire_constant_values( + fp, module_global_pin, + std::vector(1, + fabric_global_port_info.global_port_default_value( + fabric_global_port))); } } } @@ -440,48 +499,56 @@ void print_verilog_top_testbench_global_reset_ports_stimuli(std::fstream& fp, /******************************************************************** * Wire the global set ports of FPGA fabric to local wires *******************************************************************/ -static -void print_verilog_top_testbench_global_set_ports_stimuli(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricGlobalPortInfo& fabric_global_port_info, - const bool& active_global_prog_set) { +static void print_verilog_top_testbench_global_set_ports_stimuli( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info, + const bool& active_global_prog_set) { /* Validate the file stream */ valid_file_stream(fp); /* Connect global set ports to operating or programming set signal */ - for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { + for (const FabricGlobalPortId& fabric_global_port : + fabric_global_port_info.global_ports()) { /* Bypass clock signals, they have been processed */ - if (true == fabric_global_port_info.global_port_is_clock(fabric_global_port)) { + if (true == + fabric_global_port_info.global_port_is_clock(fabric_global_port)) { continue; } /* Bypass config_done signals, they have been processed */ - if (true == fabric_global_port_info.global_port_is_config_enable(fabric_global_port)) { + if (true == fabric_global_port_info.global_port_is_config_enable( + fabric_global_port)) { continue; } /* Bypass reset signals, they have been processed */ - if (true == fabric_global_port_info.global_port_is_reset(fabric_global_port)) { + if (true == + fabric_global_port_info.global_port_is_reset(fabric_global_port)) { continue; } - if (false == fabric_global_port_info.global_port_is_set(fabric_global_port)) { + if (false == + fabric_global_port_info.global_port_is_set(fabric_global_port)) { continue; } /* Reach here, it means we have a set port to deal with */ /* Find the module port */ - ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port); - VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port)); + ModulePortId module_global_port = + fabric_global_port_info.global_module_port(fabric_global_port); + VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, + module_global_port)); /* For global programming set port, we will active only when specified */ BasicPort stimuli_set_port; bool activate = true; - if (true == fabric_global_port_info.global_port_is_prog(fabric_global_port)) { + if (true == + fabric_global_port_info.global_port_is_prog(fabric_global_port)) { stimuli_set_port.set_name(std::string(TOP_TB_PROG_SET_PORT_NAME)); stimuli_set_port.set_width(1); activate = active_global_prog_set; } else { - VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_prog(fabric_global_port)); + VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_prog( + fabric_global_port)); stimuli_set_port.set_name(std::string(TOP_TB_SET_PORT_NAME)); stimuli_set_port.set_width(1); } @@ -490,13 +557,18 @@ void print_verilog_top_testbench_global_set_ports_stimuli(std::fstream& fp, * Otherwise, the wiring will not be inverted! */ if (true == activate) { - print_verilog_wire_connection(fp, module_manager.module_port(top_module, module_global_port), - stimuli_set_port, - 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); + print_verilog_wire_connection( + fp, module_manager.module_port(top_module, module_global_port), + stimuli_set_port, + 1 == fabric_global_port_info.global_port_default_value( + fabric_global_port)); } else { VTR_ASSERT_SAFE(false == activate); - print_verilog_wire_constant_values(fp, module_manager.module_port(top_module, module_global_port), - std::vector(1, fabric_global_port_info.global_port_default_value(fabric_global_port))); + print_verilog_wire_constant_values( + fp, module_manager.module_port(top_module, module_global_port), + std::vector(1, + fabric_global_port_info.global_port_default_value( + fabric_global_port))); } } } @@ -504,32 +576,36 @@ void print_verilog_top_testbench_global_set_ports_stimuli(std::fstream& fp, /******************************************************************** * Wire the regular global ports of FPGA fabric to local wires *******************************************************************/ -static -void print_verilog_top_testbench_regular_global_ports_stimuli(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricGlobalPortInfo& fabric_global_port_info) { +static void print_verilog_top_testbench_regular_global_ports_stimuli( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info) { /* Validate the file stream */ valid_file_stream(fp); /* For the rest of global ports, wire them to constant signals */ - for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { + for (const FabricGlobalPortId& fabric_global_port : + fabric_global_port_info.global_ports()) { /* Bypass clock signals, they have been processed */ - if (true == fabric_global_port_info.global_port_is_clock(fabric_global_port)) { + if (true == + fabric_global_port_info.global_port_is_clock(fabric_global_port)) { continue; } /* Bypass config_done signals, they have been processed */ - if (true == fabric_global_port_info.global_port_is_config_enable(fabric_global_port)) { + if (true == fabric_global_port_info.global_port_is_config_enable( + fabric_global_port)) { continue; } /* Bypass reset signals, they have been processed */ - if (true == fabric_global_port_info.global_port_is_reset(fabric_global_port)) { + if (true == + fabric_global_port_info.global_port_is_reset(fabric_global_port)) { continue; } /* Bypass set signals, they have been processed */ - if (true == fabric_global_port_info.global_port_is_set(fabric_global_port)) { + if (true == + fabric_global_port_info.global_port_is_set(fabric_global_port)) { continue; } @@ -540,15 +616,21 @@ void print_verilog_top_testbench_regular_global_ports_stimuli(std::fstream& fp, /* Find the port name, gpio port has special names */ std::string port_name; - VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_io(fabric_global_port)); + VTR_ASSERT_SAFE( + false == fabric_global_port_info.global_port_is_io(fabric_global_port)); /* Reach here, it means we have a port to deal with */ /* Find the module port and wire it to constant values */ - ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port); - VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port)); + ModulePortId module_global_port = + fabric_global_port_info.global_module_port(fabric_global_port); + VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, + module_global_port)); - BasicPort module_port = module_manager.module_port(top_module, module_global_port); - std::vector default_values(module_port.get_width(), fabric_global_port_info.global_port_default_value(fabric_global_port)); + BasicPort module_port = + module_manager.module_port(top_module, module_global_port); + std::vector default_values( + module_port.get_width(), + fabric_global_port_info.global_port_default_value(fabric_global_port)); print_verilog_wire_constant_values(fp, module_port, default_values); } } @@ -556,76 +638,61 @@ void print_verilog_top_testbench_regular_global_ports_stimuli(std::fstream& fp, /******************************************************************** * Wire the global ports of FPGA fabric to local wires *******************************************************************/ -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 FabricGlobalPortInfo& fabric_global_port_info, - const SimulationSetting& simulation_parameters, - const bool& active_global_prog_reset, - const bool& active_global_prog_set) { +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 FabricGlobalPortInfo& fabric_global_port_info, + const SimulationSetting& simulation_parameters, + const bool& active_global_prog_reset, const bool& active_global_prog_set) { /* Validate the file stream */ valid_file_stream(fp); - print_verilog_comment(fp, std::string("----- Begin connecting global ports of FPGA fabric to stimuli -----")); + print_verilog_comment( + fp, + std::string( + "----- 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, - simulation_parameters); + print_verilog_top_testbench_global_clock_ports_stimuli( + fp, module_manager, top_module, fabric_global_port_info, + simulation_parameters); - print_verilog_top_testbench_global_shift_register_clock_ports_stimuli(fp, - module_manager, - top_module, - fabric_global_port_info); + print_verilog_top_testbench_global_shift_register_clock_ports_stimuli( + fp, module_manager, top_module, fabric_global_port_info); - print_verilog_top_testbench_global_config_done_ports_stimuli(fp, - module_manager, - top_module, - fabric_global_port_info); + print_verilog_top_testbench_global_config_done_ports_stimuli( + fp, module_manager, top_module, fabric_global_port_info); + print_verilog_top_testbench_global_reset_ports_stimuli( + fp, module_manager, top_module, pin_constraints, fabric_global_port_info, + active_global_prog_reset); - print_verilog_top_testbench_global_reset_ports_stimuli(fp, - module_manager, - top_module, - pin_constraints, - fabric_global_port_info, - active_global_prog_reset); + print_verilog_top_testbench_global_set_ports_stimuli( + fp, module_manager, top_module, fabric_global_port_info, + active_global_prog_set); - print_verilog_top_testbench_global_set_ports_stimuli(fp, - module_manager, - top_module, - fabric_global_port_info, - active_global_prog_set); + print_verilog_top_testbench_regular_global_ports_stimuli( + fp, module_manager, top_module, fabric_global_port_info); - - print_verilog_top_testbench_regular_global_ports_stimuli(fp, - module_manager, - top_module, - fabric_global_port_info); - - print_verilog_comment(fp, std::string("----- End connecting global ports of FPGA fabric to stimuli -----")); + print_verilog_comment( + fp, std::string( + "----- End connecting global ports of FPGA fabric to stimuli -----")); } /******************************************************************** * This function prints the clock ports for all the benchmark clock nets - * It will search the pin constraints to see if a clock is constrained to a specific pin - * If constrained, + * It will search the pin constraints to see if a clock is constrained to a + *specific pin If constrained, * - connect this clock to default values if it is set to be OPEN * - connect this clock to a specific clock source from simulation settings!!! * Otherwise, * - connect this clock to the default clock port *******************************************************************/ -static -void print_verilog_top_testbench_benchmark_clock_ports(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const std::vector& clock_port_names, - const PinConstraints& pin_constraints, - const SimulationSetting& simulation_parameters, - const BasicPort& default_clock_port) { +static void print_verilog_top_testbench_benchmark_clock_ports( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, const std::vector& clock_port_names, + const PinConstraints& pin_constraints, + const SimulationSetting& simulation_parameters, + const BasicPort& default_clock_port) { /* Create a clock port if the benchmark have one but not in the default name! * We will wire the clock directly to the operating clock directly */ @@ -633,9 +700,11 @@ void print_verilog_top_testbench_benchmark_clock_ports(std::fstream& fp, if (0 == clock_port_name.compare(default_clock_port.get_name())) { continue; } - /* Ensure the clock port name is not a duplication of global ports of the FPGA module */ + /* Ensure the clock port name is not a duplication of global ports of the + * FPGA module */ bool print_clock_port = true; - for (const BasicPort& module_port : module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GLOBAL_PORT)) { + for (const BasicPort& module_port : module_manager.module_ports_by_type( + top_module, ModuleManager::MODULE_GLOBAL_PORT)) { if (0 == clock_port_name.compare(module_port.get_name())) { print_clock_port = false; } @@ -645,32 +714,43 @@ void print_verilog_top_testbench_benchmark_clock_ports(std::fstream& fp, } BasicPort clock_source_to_connect = default_clock_port; - - /* Check pin constraints to see if this clock is constrained to a specific pin - * If constrained, + + /* Check pin constraints to see if this clock is constrained to a specific + * pin If constrained, * - connect this clock to default values if it is set to be OPEN - * - connect this clock to a specific clock source from simulation settings!!! + * - connect this clock to a specific clock source from simulation + * settings!!! */ - for (const PinConstraintId& pin_constraint : pin_constraints.pin_constraints()) { + for (const PinConstraintId& pin_constraint : + pin_constraints.pin_constraints()) { if (clock_port_name != pin_constraints.net(pin_constraint)) { continue; } /* Skip all the unrelated pin constraints */ VTR_ASSERT(clock_port_name == pin_constraints.net(pin_constraint)); - /* Try to find which clock source is considered in simulation settings for this pin */ - for (const SimulationClockId& sim_clock_id : simulation_parameters.operating_clocks()) { - if (pin_constraints.pin(pin_constraint) == simulation_parameters.clock_port(sim_clock_id)) { - std::string sim_clock_port_name = generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock_id)); + /* Try to find which clock source is considered in simulation settings for + * this pin */ + for (const SimulationClockId& sim_clock_id : + simulation_parameters.operating_clocks()) { + if (pin_constraints.pin(pin_constraint) == + simulation_parameters.clock_port(sim_clock_id)) { + std::string sim_clock_port_name = generate_top_testbench_clock_name( + std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), + simulation_parameters.clock_name(sim_clock_id)); clock_source_to_connect = BasicPort(sim_clock_port_name, 1); } } } /* Print the clock and wire it to the clock source */ - print_verilog_comment(fp, std::string("----- Create a clock for benchmark and wire it to " + clock_source_to_connect.get_name() + " -------")); + print_verilog_comment( + fp, std::string("----- Create a clock for benchmark and wire it to " + + clock_source_to_connect.get_name() + " -------")); BasicPort clock_port(clock_port_name, 1); - fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, clock_port) << ";" << std::endl; - print_verilog_wire_connection(fp, clock_port, clock_source_to_connect, false); + fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, clock_port) << ";" + << std::endl; + print_verilog_wire_connection(fp, clock_port, clock_source_to_connect, + false); } } @@ -691,27 +771,24 @@ void print_verilog_top_testbench_benchmark_clock_ports(std::fstream& fp, * address lines for decoders and a bit input port to feed * configuration bits *******************************************************************/ -static -void print_verilog_top_testbench_ports(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const std::vector& clock_port_names, - const FabricGlobalPortInfo& global_ports, - const PinConstraints& pin_constraints, - const SimulationSetting& simulation_parameters, - const ConfigProtocol& config_protocol, - const std::string& circuit_name, - const VerilogTestbenchOption& options) { +static void print_verilog_top_testbench_ports( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const std::vector& clock_port_names, + const FabricGlobalPortInfo& global_ports, + const PinConstraints& pin_constraints, + const SimulationSetting& simulation_parameters, + const ConfigProtocol& config_protocol, const std::string& circuit_name, + const VerilogTestbenchOption& options) { /* Validate the file stream */ valid_file_stream(fp); - print_verilog_default_net_type_declaration(fp, - options.default_net_type()); + print_verilog_default_net_type_declaration(fp, options.default_net_type()); /* Print module definition */ - fp << "module " << circuit_name << std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX); + fp << "module " << circuit_name + << std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX); fp << ";" << std::endl; /* Print regular local wires: @@ -719,29 +796,39 @@ void print_verilog_top_testbench_ports(std::fstream& fp, * 2. datapath I/O signals */ /* Global ports of top-level module */ - print_verilog_comment(fp, std::string("----- Local wires for global ports of FPGA fabric -----")); - for (const BasicPort& module_port : module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GLOBAL_PORT)) { - fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" << std::endl; + print_verilog_comment( + fp, std::string("----- Local wires for global ports of FPGA fabric -----")); + for (const BasicPort& module_port : module_manager.module_ports_by_type( + top_module, ModuleManager::MODULE_GLOBAL_PORT)) { + fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" + << std::endl; } /* Add an empty line as a splitter */ fp << std::endl; /* Datapath I/Os of top-level module */ - print_verilog_comment(fp, std::string("----- Local wires for I/Os of FPGA fabric -----")); - for (const BasicPort& module_port : module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GPIO_PORT)) { - fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" << std::endl; + print_verilog_comment( + fp, std::string("----- Local wires for I/Os of FPGA fabric -----")); + for (const BasicPort& module_port : module_manager.module_ports_by_type( + top_module, ModuleManager::MODULE_GPIO_PORT)) { + fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" + << std::endl; } /* Add an empty line as a splitter */ fp << std::endl; - for (const BasicPort& module_port : module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GPIN_PORT)) { - fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" << std::endl; + for (const BasicPort& module_port : module_manager.module_ports_by_type( + top_module, ModuleManager::MODULE_GPIN_PORT)) { + fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" + << std::endl; } /* Add an empty line as a splitter */ fp << std::endl; - for (const BasicPort& module_port : module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GPOUT_PORT)) { - fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" << std::endl; + for (const BasicPort& module_port : module_manager.module_ports_by_type( + top_module, ModuleManager::MODULE_GPOUT_PORT)) { + fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" + << std::endl; } /* Add an empty line as a splitter */ fp << std::endl; @@ -752,39 +839,60 @@ void print_verilog_top_testbench_ports(std::fstream& fp, */ /* Configuration done port */ BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); - fp << generate_verilog_port(VERILOG_PORT_REG, config_done_port) << ";" << std::endl; + 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); - fp << generate_verilog_port(VERILOG_PORT_WIRE, prog_clock_port) << ";" << std::endl; - BasicPort prog_clock_register_port(std::string(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); - fp << generate_verilog_port(VERILOG_PORT_REG, prog_clock_register_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_WIRE, prog_clock_port) << ";" + << std::endl; + BasicPort prog_clock_register_port( + std::string(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + + std::string(TOP_TB_CLOCK_REG_POSTFIX)), + 1); + fp << generate_verilog_port(VERILOG_PORT_REG, prog_clock_register_port) << ";" + << std::endl; /* Multiple operating clocks based on the simulation settings */ - for (const SimulationClockId& sim_clock : simulation_parameters.operating_clocks()) { - std::string sim_clock_port_name = generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock)); + for (const SimulationClockId& sim_clock : + simulation_parameters.operating_clocks()) { + std::string sim_clock_port_name = generate_top_testbench_clock_name( + std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), + simulation_parameters.clock_name(sim_clock)); BasicPort sim_clock_port(sim_clock_port_name, 1); - fp << generate_verilog_port(VERILOG_PORT_WIRE, sim_clock_port) << ";" << std::endl; - BasicPort sim_clock_register_port(std::string(sim_clock_port_name + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); - fp << generate_verilog_port(VERILOG_PORT_REG, sim_clock_register_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_WIRE, sim_clock_port) << ";" + << std::endl; + BasicPort sim_clock_register_port( + std::string(sim_clock_port_name + std::string(TOP_TB_CLOCK_REG_POSTFIX)), + 1); + fp << generate_verilog_port(VERILOG_PORT_REG, sim_clock_register_port) + << ";" << std::endl; } /* FIXME: Actually, for multi-clock implementations, input and output ports - * should be synchronized by different clocks. Currently, we lack the information - * about what inputs are driven by which clock. Therefore, we use a unified clock - * signal to do the job. However, this has to be fixed later!!! - * Create an operating clock_port to synchronize checkers stimulus generator + * should be synchronized by different clocks. Currently, we lack the + * information about what inputs are driven by which clock. Therefore, we use + * a unified clock signal to do the job. However, this has to be fixed + * later!!! Create an operating clock_port to synchronize checkers stimulus + * generator */ BasicPort op_clock_port(std::string(TOP_TB_OP_CLOCK_PORT_NAME), 1); - fp << generate_verilog_port(VERILOG_PORT_WIRE, op_clock_port) << ";" << std::endl; - BasicPort op_clock_register_port(std::string(std::string(TOP_TB_OP_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); - fp << generate_verilog_port(VERILOG_PORT_REG, op_clock_register_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_WIRE, op_clock_port) << ";" + << std::endl; + BasicPort op_clock_register_port( + std::string(std::string(TOP_TB_OP_CLOCK_PORT_NAME) + + std::string(TOP_TB_CLOCK_REG_POSTFIX)), + 1); + fp << generate_verilog_port(VERILOG_PORT_REG, op_clock_register_port) << ";" + << std::endl; /* Programming set and reset */ BasicPort prog_reset_port(std::string(TOP_TB_PROG_RESET_PORT_NAME), 1); - fp << generate_verilog_port(VERILOG_PORT_REG, prog_reset_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, prog_reset_port) << ";" + << std::endl; BasicPort prog_set_port(std::string(TOP_TB_PROG_SET_PORT_NAME), 1); - fp << generate_verilog_port(VERILOG_PORT_REG, prog_set_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, prog_set_port) << ";" + << std::endl; /* Global set and reset */ BasicPort reset_port(std::string(TOP_TB_RESET_PORT_NAME), 1); @@ -797,129 +905,160 @@ void print_verilog_top_testbench_ports(std::fstream& fp, module_manager, top_module); /* Print clock ports */ - print_verilog_top_testbench_benchmark_clock_ports(fp, - module_manager, top_module, - clock_port_names, - pin_constraints, - simulation_parameters, - op_clock_port); + print_verilog_top_testbench_benchmark_clock_ports( + fp, module_manager, top_module, clock_port_names, pin_constraints, + simulation_parameters, op_clock_port); std::vector global_port_names; - print_verilog_testbench_shared_ports(fp, - module_manager, global_ports, pin_constraints, - atom_ctx, netlist_annotation, - clock_port_names, - std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX), - std::string(TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX), - std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX), - std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX), - options.no_self_checking()); + print_verilog_testbench_shared_ports( + fp, module_manager, global_ports, pin_constraints, atom_ctx, + netlist_annotation, clock_port_names, + std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX), + std::string(TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX), + std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX), + std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX), + options.no_self_checking()); /* Instantiate an integer to count the number of error and * determine if the simulation succeed or failed */ if (!options.no_self_checking()) { - print_verilog_comment(fp, std::string("----- Error counter: Deposit an error for config_done signal is not raised at the beginning -----")); + print_verilog_comment( + fp, std::string("----- Error counter: Deposit an error for config_done " + "signal is not raised at the beginning -----")); fp << "\tinteger " << TOP_TESTBENCH_ERROR_COUNTER << "= 1;" << std::endl; } } /******************************************************************** * Estimate the number of configuration clock cycles - * by traversing the linked-list and count the number of SRAM=1 or BL=1&WL=1 in it. - * We plus 1 additional config clock cycle here because we need to reset everything during the first clock cycle - * If we consider fast configuration, the number of clock cycles will be - * the number of non-zero data points in the fabric bitstream - * Note that this will not applicable to configuration chain!!! + * by traversing the linked-list and count the number of SRAM=1 or BL=1&WL=1 in + *it. We plus 1 additional config clock cycle here because we need to reset + *everything during the first clock cycle If we consider fast configuration, the + *number of clock cycles will be the number of non-zero data points in the + *fabric bitstream Note that this will not applicable to configuration chain!!! *******************************************************************/ -static -size_t calculate_num_config_clock_cycles(const ConfigProtocol& config_protocol, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream) { +static size_t calculate_num_config_clock_cycles( + const ConfigProtocol& config_protocol, const bool& fast_configuration, + const bool& bit_value_to_skip, const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream) { /* Find the longest regional bitstream */ - size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream); + size_t regional_bitstream_max_size = + find_fabric_regional_bitstream_max_size(fabric_bitstream); size_t num_config_clock_cycles = 1 + regional_bitstream_max_size; /* Branch on the type of configuration protocol */ switch (config_protocol.type()) { - case CONFIG_MEM_STANDALONE: - /* We just need 1 clock cycle to load all the configuration bits - * since all the ports are exposed at the top-level - */ - num_config_clock_cycles = 2; - break; - case CONFIG_MEM_SCAN_CHAIN: - /* For fast configuration, the bitstream size counts from the first bit '1' */ - if (true == fast_configuration) { - /* For fast configuration, the number of bits to be skipped - * depends on each regional bitstream - * For example: - * Region 0: 000000001111101010 - * Region 1: 00000011010101 - * Region 2: 0010101111000110 - * The number of bits that can be skipped is limited by Region 2 + case CONFIG_MEM_STANDALONE: + /* We just need 1 clock cycle to load all the configuration bits + * since all the ports are exposed at the top-level */ - size_t num_bits_to_skip = find_configuration_chain_fabric_bitstream_size_to_be_skipped(fabric_bitstream, bitstream_manager, bit_value_to_skip); + num_config_clock_cycles = 2; + break; + case CONFIG_MEM_SCAN_CHAIN: + /* For fast configuration, the bitstream size counts from the first bit + * '1' */ + if (true == fast_configuration) { + /* For fast configuration, the number of bits to be skipped + * depends on each regional bitstream + * For example: + * Region 0: 000000001111101010 + * Region 1: 00000011010101 + * Region 2: 0010101111000110 + * The number of bits that can be skipped is limited by Region 2 + */ + size_t num_bits_to_skip = + find_configuration_chain_fabric_bitstream_size_to_be_skipped( + fabric_bitstream, bitstream_manager, bit_value_to_skip); - num_config_clock_cycles = 1 + regional_bitstream_max_size - num_bits_to_skip; + num_config_clock_cycles = + 1 + regional_bitstream_max_size - num_bits_to_skip; - VTR_LOG("Fast configuration reduces number of configuration clock cycles from %lu to %lu (compression_rate = %f%)\n", - 1 + regional_bitstream_max_size, - num_config_clock_cycles, - 100. * ((float)num_config_clock_cycles / (float)(1 + regional_bitstream_max_size) - 1.)); + VTR_LOG( + "Fast configuration reduces number of configuration clock cycles " + "from %lu to %lu (compression_rate = %f%)\n", + 1 + regional_bitstream_max_size, num_config_clock_cycles, + 100. * ((float)num_config_clock_cycles / + (float)(1 + regional_bitstream_max_size) - + 1.)); + } + break; + case CONFIG_MEM_QL_MEMORY_BANK: { + if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { + /* For fast configuration, we will skip all the zero data points */ + num_config_clock_cycles = + 1 + build_memory_bank_fabric_bitstream_by_address(fabric_bitstream) + .size(); + if (true == fast_configuration) { + size_t full_num_config_clock_cycles = num_config_clock_cycles; + num_config_clock_cycles = + 1 + find_memory_bank_fast_configuration_fabric_bitstream_size( + fabric_bitstream, bit_value_to_skip); + VTR_LOG( + "Fast configuration reduces number of configuration clock cycles " + "from %lu to %lu (compression_rate = %f%)\n", + full_num_config_clock_cycles, num_config_clock_cycles, + 100. * ((float)num_config_clock_cycles / + (float)full_num_config_clock_cycles - + 1.)); + } + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { + num_config_clock_cycles = + 1 + build_memory_bank_flatten_fabric_bitstream( + fabric_bitstream, fast_configuration, bit_value_to_skip) + .size(); + } else if (BLWL_PROTOCOL_SHIFT_REGISTER == + config_protocol.bl_protocol_type()) { + num_config_clock_cycles = + 1 + build_memory_bank_flatten_fabric_bitstream( + fabric_bitstream, fast_configuration, bit_value_to_skip) + .size(); + } + break; } - break; - case CONFIG_MEM_QL_MEMORY_BANK: { - if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { + case CONFIG_MEM_MEMORY_BANK: { /* For fast configuration, we will skip all the zero data points */ - num_config_clock_cycles = 1 + build_memory_bank_fabric_bitstream_by_address(fabric_bitstream).size(); + num_config_clock_cycles = + 1 + + build_memory_bank_fabric_bitstream_by_address(fabric_bitstream).size(); if (true == fast_configuration) { size_t full_num_config_clock_cycles = num_config_clock_cycles; - num_config_clock_cycles = 1 + find_memory_bank_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); - VTR_LOG("Fast configuration reduces number of configuration clock cycles from %lu to %lu (compression_rate = %f%)\n", - full_num_config_clock_cycles, - num_config_clock_cycles, - 100. * ((float)num_config_clock_cycles / (float)full_num_config_clock_cycles - 1.)); + num_config_clock_cycles = + 1 + find_memory_bank_fast_configuration_fabric_bitstream_size( + fabric_bitstream, bit_value_to_skip); + VTR_LOG( + "Fast configuration reduces number of configuration clock cycles " + "from %lu to %lu (compression_rate = %f%)\n", + full_num_config_clock_cycles, num_config_clock_cycles, + 100. * ((float)num_config_clock_cycles / + (float)full_num_config_clock_cycles - + 1.)); } - } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { - num_config_clock_cycles = 1 + build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip).size(); - } else if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { - num_config_clock_cycles = 1 + build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip).size(); + break; } - break; - } - case CONFIG_MEM_MEMORY_BANK: { - /* For fast configuration, we will skip all the zero data points */ - num_config_clock_cycles = 1 + build_memory_bank_fabric_bitstream_by_address(fabric_bitstream).size(); - if (true == fast_configuration) { - size_t full_num_config_clock_cycles = num_config_clock_cycles; - num_config_clock_cycles = 1 + find_memory_bank_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); - VTR_LOG("Fast configuration reduces number of configuration clock cycles from %lu to %lu (compression_rate = %f%)\n", - full_num_config_clock_cycles, - num_config_clock_cycles, - 100. * ((float)num_config_clock_cycles / (float)full_num_config_clock_cycles - 1.)); + case CONFIG_MEM_FRAME_BASED: { + num_config_clock_cycles = + 1 + + build_frame_based_fabric_bitstream_by_address(fabric_bitstream).size(); + if (true == fast_configuration) { + size_t full_num_config_clock_cycles = num_config_clock_cycles; + num_config_clock_cycles = + 1 + find_frame_based_fast_configuration_fabric_bitstream_size( + fabric_bitstream, bit_value_to_skip); + VTR_LOG( + "Fast configuration reduces number of configuration clock cycles " + "from %lu to %lu (compression_rate = %f%)\n", + full_num_config_clock_cycles, num_config_clock_cycles, + 100. * ((float)num_config_clock_cycles / + (float)full_num_config_clock_cycles - + 1.)); + } + break; } - break; - } - case CONFIG_MEM_FRAME_BASED: { - num_config_clock_cycles = 1 + build_frame_based_fabric_bitstream_by_address(fabric_bitstream).size(); - if (true == fast_configuration) { - size_t full_num_config_clock_cycles = num_config_clock_cycles; - num_config_clock_cycles = 1 + find_frame_based_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); - VTR_LOG("Fast configuration reduces number of configuration clock cycles from %lu to %lu (compression_rate = %f%)\n", - full_num_config_clock_cycles, - num_config_clock_cycles, - 100. * ((float)num_config_clock_cycles / (float)full_num_config_clock_cycles - 1.)); - } - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid SRAM organization type!\n"); - exit(1); + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid SRAM organization type!\n"); + exit(1); } VTR_LOG("Will use %ld configuration clock cycles to top testbench\n", @@ -931,34 +1070,29 @@ size_t calculate_num_config_clock_cycles(const ConfigProtocol& config_protocol, /******************************************************************** * Instanciate the input benchmark module *******************************************************************/ -static -void print_verilog_top_testbench_benchmark_instance(std::fstream& fp, - const std::string& reference_verilog_top_name, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const std::vector& clock_port_names, - const bool& explicit_port_mapping) { +static void print_verilog_top_testbench_benchmark_instance( + std::fstream& fp, const std::string& reference_verilog_top_name, + const AtomContext& atom_ctx, const VprNetlistAnnotation& netlist_annotation, + const PinConstraints& pin_constraints, const BusGroup& bus_group, + const std::vector& clock_port_names, + const bool& explicit_port_mapping) { /* Validate the file stream */ valid_file_stream(fp); /* Instanciate benchmark */ - print_verilog_comment(fp, std::string("----- Reference Benchmark Instanication -------")); + print_verilog_comment( + fp, std::string("----- Reference Benchmark Instanication -------")); - print_verilog_testbench_benchmark_instance(fp, reference_verilog_top_name, - std::string(TOP_TESTBENCH_REFERENCE_INSTANCE_NAME), - std::string(), - std::string(), - std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX), - std::string(TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX), - clock_port_names, - atom_ctx, netlist_annotation, - pin_constraints, - bus_group, - explicit_port_mapping); + print_verilog_testbench_benchmark_instance( + fp, reference_verilog_top_name, + std::string(TOP_TESTBENCH_REFERENCE_INSTANCE_NAME), std::string(), + std::string(), std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX), + std::string(TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX), clock_port_names, + atom_ctx, netlist_annotation, pin_constraints, bus_group, + explicit_port_mapping); - print_verilog_comment(fp, std::string("----- End reference Benchmark Instanication -------")); + print_verilog_comment( + fp, std::string("----- End reference Benchmark Instanication -------")); /* Add an empty line as splitter */ fp << std::endl; @@ -975,25 +1109,30 @@ void print_verilog_top_testbench_benchmark_instance(std::fstream& fp, * 6. reset signal * 7. set signal *******************************************************************/ -static -void print_verilog_top_testbench_generic_stimulus(std::fstream& fp, - const SimulationSetting& simulation_parameters, - const size_t& num_config_clock_cycles, - const float& prog_clock_period, - const float& op_clock_period, - const float& timescale) { +static void print_verilog_top_testbench_generic_stimulus( + std::fstream& fp, 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 */ valid_file_stream(fp); - print_verilog_comment(fp, std::string("----- Number of clock cycles in configuration phase: " + std::to_string(num_config_clock_cycles) + " -----")); + print_verilog_comment( + 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); BasicPort op_clock_port(std::string(TOP_TB_OP_CLOCK_PORT_NAME), 1); - BasicPort op_clock_register_port(std::string(std::string(TOP_TB_OP_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); + BasicPort op_clock_register_port( + std::string(std::string(TOP_TB_OP_CLOCK_PORT_NAME) + + std::string(TOP_TB_CLOCK_REG_POSTFIX)), + 1); BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); - BasicPort prog_clock_register_port(std::string(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); + BasicPort prog_clock_register_port( + std::string(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + + std::string(TOP_TB_CLOCK_REG_POSTFIX)), + 1); BasicPort prog_reset_port(std::string(TOP_TB_PROG_RESET_PORT_NAME), 1); BasicPort prog_set_port(std::string(TOP_TB_PROG_SET_PORT_NAME), 1); @@ -1002,54 +1141,80 @@ void print_verilog_top_testbench_generic_stimulus(std::fstream& fp, BasicPort set_port(std::string(TOP_TB_SET_PORT_NAME), 1); /* Generate stimuli waveform for configuration done signals */ - print_verilog_comment(fp, "----- Begin configuration done signal generation -----"); - print_verilog_pulse_stimuli(fp, config_done_port, - 0, /* Initial value */ - num_config_clock_cycles * prog_clock_period / timescale, 0); - print_verilog_comment(fp, "----- End configuration done signal generation -----"); + print_verilog_comment( + fp, "----- Begin configuration done signal generation -----"); + print_verilog_pulse_stimuli( + fp, config_done_port, 0, /* Initial value */ + num_config_clock_cycles * prog_clock_period / timescale, 0); + print_verilog_comment(fp, + "----- End configuration done signal generation -----"); fp << std::endl; /* Generate stimuli waveform for programming clock signals */ - print_verilog_comment(fp, "----- Begin raw programming clock signal generation -----"); - print_verilog_clock_stimuli(fp, prog_clock_register_port, - 0, /* Initial value */ - 0.5 * prog_clock_period / timescale, - std::string()); - print_verilog_comment(fp, "----- End raw programming clock signal generation -----"); + print_verilog_comment( + fp, "----- Begin raw programming clock signal generation -----"); + print_verilog_clock_stimuli( + fp, prog_clock_register_port, 0, /* Initial value */ + 0.5 * prog_clock_period / timescale, std::string()); + print_verilog_comment( + fp, "----- End raw programming clock signal generation -----"); fp << std::endl; /* Programming clock should be only enabled during programming phase. - * When configuration is done (config_done is enabled), programming clock should be always zero. + * When configuration is done (config_done is enabled), programming clock + * should be always zero. */ - print_verilog_comment(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) << ")"; + print_verilog_comment( + 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; fp << std::endl; - /* Generate stimuli waveform for multiple user-defined operating clock signals */ - for (const SimulationClockId& sim_clock : simulation_parameters.operating_clocks()) { - print_verilog_comment(fp, "----- Begin raw operating clock signal '" + simulation_parameters.clock_name(sim_clock) + "' generation -----"); - std::string sim_clock_port_name = generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock)); + /* Generate stimuli waveform for multiple user-defined operating clock signals + */ + for (const SimulationClockId& sim_clock : + simulation_parameters.operating_clocks()) { + print_verilog_comment(fp, "----- Begin raw operating clock signal '" + + simulation_parameters.clock_name(sim_clock) + + "' generation -----"); + std::string sim_clock_port_name = generate_top_testbench_clock_name( + std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), + simulation_parameters.clock_name(sim_clock)); BasicPort sim_clock_port(sim_clock_port_name, 1); - BasicPort sim_clock_register_port(std::string(sim_clock_port_name + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); + BasicPort sim_clock_register_port( + std::string(sim_clock_port_name + std::string(TOP_TB_CLOCK_REG_POSTFIX)), + 1); - float sim_clock_period = 1. / simulation_parameters.clock_frequency(sim_clock); + float sim_clock_period = + 1. / simulation_parameters.clock_frequency(sim_clock); print_verilog_clock_stimuli(fp, sim_clock_register_port, 0, /* Initial value */ 0.5 * sim_clock_period / timescale, std::string("~" + reset_port.get_name())); - print_verilog_comment(fp, "----- End raw operating clock signal generation -----"); + print_verilog_comment( + 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 should be always zero. + * Before configuration is done (config_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 -----")); - fp << "\tassign " << generate_verilog_port(VERILOG_PORT_CONKT, sim_clock_port); - fp << " = " << generate_verilog_port(VERILOG_PORT_CONKT, sim_clock_register_port); + print_verilog_comment( + fp, std::string("----- Actual operating clock is triggered only when " + + config_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 << ";" << std::endl; @@ -1057,19 +1222,24 @@ void print_verilog_top_testbench_generic_stimulus(std::fstream& fp, } /* Generate stimuli waveform for operating clock signals */ - print_verilog_comment(fp, "----- Begin raw operating clock signal generation -----"); - print_verilog_clock_stimuli(fp, op_clock_register_port, - 0, /* Initial value */ + print_verilog_comment( + fp, "----- Begin raw operating clock signal generation -----"); + print_verilog_clock_stimuli(fp, op_clock_register_port, 0, /* Initial value */ 0.5 * op_clock_period / timescale, std::string("~" + reset_port.get_name())); - print_verilog_comment(fp, "----- End raw operating clock signal generation -----"); + print_verilog_comment( + 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 should be always zero. + * Before configuration is done (config_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 -----")); + print_verilog_comment( + fp, std::string("----- Actual operating clock is triggered only when " + + config_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, op_clock_register_port); fp << " & " << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port); fp << ";" << std::endl; @@ -1078,24 +1248,27 @@ void print_verilog_top_testbench_generic_stimulus(std::fstream& fp, /* Reset signal for configuration circuit: * only enable during the first clock cycle in programming phase */ - print_verilog_comment(fp, "----- Begin programming reset signal generation -----"); - print_verilog_pulse_stimuli(fp, prog_reset_port, - 1, /* Initial value */ + print_verilog_comment( + fp, "----- Begin programming reset signal generation -----"); + print_verilog_pulse_stimuli(fp, prog_reset_port, 1, /* Initial value */ prog_clock_period / timescale, 0); - print_verilog_comment(fp, "----- End programming reset signal generation -----"); + print_verilog_comment(fp, + "----- End programming reset signal generation -----"); fp << std::endl; /* Programming set signal for configuration circuit : always disabled */ - print_verilog_comment(fp, "----- Begin programming set signal generation -----"); - print_verilog_pulse_stimuli(fp, prog_set_port, - 1, /* Initial value */ + print_verilog_comment(fp, + "----- Begin programming set signal generation -----"); + print_verilog_pulse_stimuli(fp, prog_set_port, 1, /* Initial value */ prog_clock_period / timescale, 0); - print_verilog_comment(fp, "----- End programming set signal generation -----"); + print_verilog_comment(fp, + "----- End programming set signal generation -----"); fp << std::endl; - /* Operating reset signals: only enabled during the first clock cycle in operation phase */ + /* Operating reset signals: only enabled during the first clock cycle in + * operation phase */ std::vector reset_pulse_widths; reset_pulse_widths.push_back(op_clock_period / timescale); reset_pulse_widths.push_back(2 * op_clock_period / timescale); @@ -1104,21 +1277,23 @@ void print_verilog_top_testbench_generic_stimulus(std::fstream& fp, reset_flip_values.push_back(1); reset_flip_values.push_back(0); - print_verilog_comment(fp, "----- Begin operating reset signal generation -----"); - print_verilog_comment(fp, "----- 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()); - print_verilog_comment(fp, "----- End operating reset signal generation -----"); + print_verilog_comment(fp, + "----- Begin operating reset signal generation -----"); + print_verilog_comment(fp, + "----- 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()); + print_verilog_comment(fp, + "----- End operating reset signal generation -----"); /* Operating set signal for configuration circuit : always disabled */ - print_verilog_comment(fp, "----- Begin operating set signal generation: always disabled -----"); - print_verilog_pulse_stimuli(fp, set_port, - 0, /* Initial value */ + print_verilog_comment( + fp, "----- Begin operating set signal generation: always disabled -----"); + print_verilog_pulse_stimuli(fp, set_port, 0, /* Initial value */ op_clock_period / timescale, 0); - print_verilog_comment(fp, "----- End operating set signal generation: always disabled -----"); + print_verilog_comment( + fp, "----- End operating set signal generation: always disabled -----"); fp << std::endl; } @@ -1126,74 +1301,68 @@ void print_verilog_top_testbench_generic_stimulus(std::fstream& fp, /******************************************************************** * Print input stimuli for configuration protocol * include: - * - memory bank - * 1. the enable signal - * - frame-based - * 1. the enable signal + * - memory bank + * 1. the enable signal + * - frame-based + * 1. the enable signal *******************************************************************/ -static -int print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& fp, - const ConfigProtocol& config_protocol, - const SimulationSetting& sim_settings, - const ModuleManager& module_manager, - const ModuleId& top_module, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const FabricBitstream& fabric_bitstream, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const float& prog_clock_period, - const float& timescale) { +static int print_verilog_top_testbench_configuration_protocol_stimulus( + std::fstream& fp, const ConfigProtocol& config_protocol, + const SimulationSetting& sim_settings, const ModuleManager& module_manager, + const ModuleId& top_module, const bool& fast_configuration, + const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const float& prog_clock_period, const float& timescale) { /* Validate the file stream */ valid_file_stream(fp); /* Branch on the type of configuration protocol */ switch (config_protocol.type()) { - case CONFIG_MEM_STANDALONE: - break; - case CONFIG_MEM_SCAN_CHAIN: - break; - case CONFIG_MEM_QL_MEMORY_BANK: - return print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(fp, - config_protocol, sim_settings, - module_manager, top_module, - fast_configuration, bit_value_to_skip, - fabric_bitstream, blwl_sr_banks, - prog_clock_period, timescale); - break; - case CONFIG_MEM_MEMORY_BANK: - case CONFIG_MEM_FRAME_BASED: { - ModulePortId en_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_ENABLE_PORT_NAME)); - BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); - if (en_port_id) { - en_port = module_manager.module_port(top_module, en_port_id); + case CONFIG_MEM_STANDALONE: + break; + case CONFIG_MEM_SCAN_CHAIN: + break; + case CONFIG_MEM_QL_MEMORY_BANK: + return print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus( + fp, config_protocol, sim_settings, module_manager, top_module, + fast_configuration, bit_value_to_skip, fabric_bitstream, blwl_sr_banks, + prog_clock_period, timescale); + break; + case CONFIG_MEM_MEMORY_BANK: + case CONFIG_MEM_FRAME_BASED: { + ModulePortId en_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_ENABLE_PORT_NAME)); + BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); + if (en_port_id) { + en_port = module_manager.module_port(top_module, en_port_id); + } + BasicPort en_register_port( + std::string(en_port.get_name() + std::string(TOP_TB_CLOCK_REG_POSTFIX)), + 1); + print_verilog_comment( + fp, std::string("---- Generate enable signal waveform -----")); + print_verilog_shifted_clock_stimuli( + fp, en_register_port, 0.25 * prog_clock_period / timescale, + 0.5 * prog_clock_period / timescale, 0); + break; } - BasicPort en_register_port(std::string(en_port.get_name() + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); - print_verilog_comment(fp, std::string("---- Generate enable signal waveform -----")); - print_verilog_shifted_clock_stimuli(fp, en_register_port, - 0.25 * prog_clock_period / timescale, - 0.5 * prog_clock_period / timescale, 0); - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid SRAM organization type!\n"); - exit(1); + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid SRAM organization type!\n"); + exit(1); } return CMD_EXEC_SUCCESS; } /******************************************************************** - * Print stimulus for a FPGA fabric with a flatten memory (standalone) configuration protocol - * We will load the bitstream in the second clock cycle, right after the first reset cycle + * Print stimulus for a FPGA fabric with a flatten memory (standalone) + *configuration protocol We will load the bitstream in the second clock cycle, + *right after the first reset cycle *******************************************************************/ -static -void print_verilog_full_testbench_vanilla_bitstream(std::fstream& fp, - const std::string& bitstream_file, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricBitstream& fabric_bitstream) { +static void print_verilog_full_testbench_vanilla_bitstream( + std::fstream& fp, const std::string& bitstream_file, + const ModuleManager& module_manager, const ModuleId& top_module, + const FabricBitstream& fabric_bitstream) { /* Validate the file stream */ valid_file_stream(fp); @@ -1201,17 +1370,21 @@ void print_verilog_full_testbench_vanilla_bitstream(std::fstream& fp, BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); /* Find Bit-Line and Word-Line port */ - ModulePortId bl_port_id = module_manager.find_module_port(top_module, std::string(MEMORY_BL_PORT_NAME)); + ModulePortId bl_port_id = module_manager.find_module_port( + top_module, std::string(MEMORY_BL_PORT_NAME)); BasicPort bl_port = module_manager.module_port(top_module, bl_port_id); - ModulePortId wl_port_id = module_manager.find_module_port(top_module, std::string(MEMORY_WL_PORT_NAME)); + ModulePortId wl_port_id = module_manager.find_module_port( + top_module, std::string(MEMORY_WL_PORT_NAME)); BasicPort wl_port = module_manager.module_port(top_module, wl_port_id); /* Define a constant for the bitstream length */ - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), fabric_bitstream.num_bits()); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), + fabric_bitstream.num_bits()); /* Declare local variables for bitstream loading in Verilog */ - print_verilog_comment(fp, "----- Virtual memory to store the bitstream from external file -----"); + print_verilog_comment( + fp, "----- Virtual memory to store the bitstream from external file -----"); fp << "reg [0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1] "; fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:0];"; fp << std::endl; @@ -1219,13 +1392,14 @@ void print_verilog_full_testbench_vanilla_bitstream(std::fstream& fp, /* 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. - * We do not care the value of scan_chain head during the first programming cycle - * It is reset anyway + * We do not care the value of scan_chain head during the first programming + * cycle It is reset anyway */ std::vector initial_bl_values(bl_port.get_width(), 0); std::vector initial_wl_values(wl_port.get_width(), 0); - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); + print_verilog_comment( + fp, "----- Begin bitstream loading during configuration phase -----"); fp << "initial" << std::endl; fp << "\tbegin" << std::endl; print_verilog_comment(fp, "----- Configuration chain default input -----"); @@ -1236,12 +1410,16 @@ void print_verilog_full_testbench_vanilla_bitstream(std::fstream& fp, fp << generate_verilog_port_constant_values(wl_port, initial_wl_values); fp << ";" << std::endl; - print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); + print_verilog_comment( + fp, "----- Preload bitstream file to a virtual memory -----"); fp << "\t"; - fp << "$readmemb(\"" << bitstream_file << "\", " << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; + fp << "$readmemb(\"" << bitstream_file << "\", " + << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; fp << std::endl; - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ") begin" << std::endl; + fp << "\t\t@(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ") begin" + << std::endl; /* Enable all the WLs */ std::vector enabled_wl_values(wl_port.get_width(), 1); @@ -1258,99 +1436,118 @@ void print_verilog_full_testbench_vanilla_bitstream(std::fstream& fp, fp << "\t\tend" << std::endl; /* Disable all the WLs */ - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; + fp << "\t\t@(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" + << std::endl; fp << "\t\t\t"; fp << generate_verilog_port_constant_values(wl_port, initial_wl_values); fp << ";" << std::endl; /* Raise the flag of configuration done when bitstream loading is complete */ - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; + fp << "\t\t@(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" + << std::endl; BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); fp << "\t\t\t"; fp << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port); fp << " <= "; - std::vector config_done_enable_values(config_done_port.get_width(), 1); + std::vector config_done_enable_values(config_done_port.get_width(), + 1); fp << generate_verilog_constant_values(config_done_enable_values); fp << ";" << std::endl; fp << "\tend" << std::endl; - print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); + print_verilog_comment( + fp, "----- End bitstream loading during configuration phase -----"); } /******************************************************************** * Print stimulus for a FPGA fabric with a configuration chain protocol * where configuration bits are programming in serial (one by one) * Task list: - * 1. For clock signal, we should create voltage waveforms for two types of clock signals: - * a. operation clock - * b. programming clock + * 1. For clock signal, we should create voltage waveforms for two types of + *clock signals: a. operation clock b. programming clock * 2. For Set/Reset, we reset the chip after programming phase ends * and before operation phase starts * 3. For input/output clb nets (mapped to I/O grids), * we should create voltage waveforms only after programming phase *******************************************************************/ -static -void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp, - const std::string& bitstream_file, - 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) { +static void print_verilog_full_testbench_configuration_chain_bitstream( + std::fstream& fp, const std::string& bitstream_file, + 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) { /* Validate the file stream */ valid_file_stream(fp); - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); + print_verilog_comment( + fp, "----- Begin bitstream loading during configuration phase -----"); /* Find the longest bitstream */ - size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream); + size_t regional_bitstream_max_size = + find_fabric_regional_bitstream_max_size(fabric_bitstream); /* For fast configuration, the bitstream size counts from the first bit '1' */ size_t num_bits_to_skip = 0; if (true == fast_configuration) { - num_bits_to_skip = find_configuration_chain_fabric_bitstream_size_to_be_skipped(fabric_bitstream, bitstream_manager, bit_value_to_skip); + num_bits_to_skip = + find_configuration_chain_fabric_bitstream_size_to_be_skipped( + fabric_bitstream, bitstream_manager, bit_value_to_skip); } VTR_ASSERT(num_bits_to_skip < regional_bitstream_max_size); /* 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()); + 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()); /* 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. - * We do not care the value of scan_chain head during the first programming cycle - * It is reset anyway + * We do not care the value of scan_chain head during the first programming + * cycle It is reset anyway */ - ModulePortId cc_head_port_id = module_manager.find_module_port(top_module, generate_configuration_chain_head_name()); - BasicPort config_chain_head_port = module_manager.module_port(top_module, cc_head_port_id); + ModulePortId cc_head_port_id = module_manager.find_module_port( + top_module, generate_configuration_chain_head_name()); + BasicPort config_chain_head_port = + module_manager.module_port(top_module, cc_head_port_id); std::vector initial_values(config_chain_head_port.get_width(), 0); /* Declare local variables for bitstream loading in Verilog */ - print_verilog_comment(fp, "----- Virtual memory to store the bitstream from external file -----"); + print_verilog_comment( + fp, "----- Virtual memory to store the bitstream from external file -----"); fp << "reg [0:`" << TOP_TB_BITSTREAM_WIDTH_VARIABLE << " - 1] "; - fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1];"; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" + << 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; + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " + << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; BasicPort bit_skip_reg(TOP_TB_BITSTREAM_SKIP_FLAG_REG_NAME, 1); - print_verilog_comment(fp, "----- Registers used for fast configuration logic -----"); - fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_REG, bit_skip_reg) << ";" << std::endl; + print_verilog_comment( + fp, "----- Registers used for fast configuration logic -----"); + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " + << TOP_TB_BITSTREAM_ITERATOR_REG_NAME << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, bit_skip_reg) << ";" + << std::endl; - print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); + print_verilog_comment( + fp, "----- Preload bitstream file to a virtual memory -----"); fp << "initial begin" << std::endl; fp << "\t"; - fp << "$readmemb(\"" << bitstream_file << "\", " << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; + fp << "$readmemb(\"" << bitstream_file << "\", " + << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; fp << std::endl; print_verilog_comment(fp, "----- Configuration chain default input -----"); fp << "\t"; - fp << generate_verilog_port_constant_values(config_chain_head_port, initial_values, true); + fp << generate_verilog_port_constant_values(config_chain_head_port, + initial_values, true); fp << ";"; fp << std::endl; @@ -1359,33 +1556,40 @@ void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp fp << ";"; fp << std::endl; - std::vector bit_skip_values(bit_skip_reg.get_width(), fast_configuration ? 1 : 0); + std::vector bit_skip_values(bit_skip_reg.get_width(), + fast_configuration ? 1 : 0); fp << "\t"; - fp << generate_verilog_port_constant_values(bit_skip_reg, bit_skip_values, true); + fp << generate_verilog_port_constant_values(bit_skip_reg, bit_skip_values, + true); 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 << 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 << 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 << 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 << generate_verilog_constant_values( + std::vector(bit_skip_reg.get_width(), 1)); fp << " == "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, bit_skip_reg) << ")"; + fp << generate_verilog_port(VERILOG_PORT_CONKT, bit_skip_reg) << ")"; fp << " begin"; fp << std::endl; @@ -1404,7 +1608,8 @@ void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp 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 << generate_verilog_port_constant_values( + bit_skip_reg, std::vector(bit_skip_reg.get_width(), 0), true); fp << ";" << std::endl; fp << "\t\t"; @@ -1418,10 +1623,15 @@ void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp fp << "end"; fp << std::endl; - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1); - print_verilog_comment(fp, "----- 'else if' condition is required by Modelsim to synthesis the Verilog correctly -----"); + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + + std::string(TOP_TB_CLOCK_REG_POSTFIX), + 1); + 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 << " @(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; fp << " begin"; fp << std::endl; @@ -1436,7 +1646,8 @@ void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp 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 << generate_verilog_port_constant_values(config_done_port, + config_done_final_values, true); fp << ";" << std::endl; fp << "\t"; @@ -1450,9 +1661,10 @@ void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp fp << std::endl; fp << "\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, config_chain_head_port); + 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"; @@ -1468,31 +1680,33 @@ void print_verilog_full_testbench_configuration_chain_bitstream(std::fstream& fp fp << "end"; fp << std::endl; - print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); + print_verilog_comment( + fp, "----- End bitstream loading during configuration phase -----"); } /******************************************************************** * Print stimulus for a FPGA fabric with a memory bank configuration protocol * where configuration bits are programming in serial (one by one) *******************************************************************/ -static -void print_verilog_full_testbench_memory_bank_bitstream(std::fstream& fp, - const std::string& bitstream_file, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricBitstream& fabric_bitstream) { +static void print_verilog_full_testbench_memory_bank_bitstream( + std::fstream& fp, const std::string& bitstream_file, + const bool& fast_configuration, const bool& bit_value_to_skip, + const ModuleManager& module_manager, const ModuleId& top_module, + const FabricBitstream& fabric_bitstream) { /* Validate the file stream */ valid_file_stream(fp); /* Reorganize the fabric bitstream by the same address across regions */ - MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); + MemoryBankFabricBitstream fabric_bits_by_addr = + build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); /* For fast configuration, identify the final bitstream size to be used */ size_t num_bits_to_skip = 0; if (true == fast_configuration) { - num_bits_to_skip = fabric_bits_by_addr.size() - find_memory_bank_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); + num_bits_to_skip = + fabric_bits_by_addr.size() - + find_memory_bank_fast_configuration_fabric_bitstream_size( + fabric_bitstream, bit_value_to_skip); } VTR_ASSERT(num_bits_to_skip < fabric_bits_by_addr.size()); @@ -1500,48 +1714,60 @@ void print_verilog_full_testbench_memory_bank_bitstream(std::fstream& fp, * Note: the first cycle is reserved for programming reset * We should give dummy values */ - ModulePortId bl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_BL_ADDRESS_PORT_NAME)); - BasicPort bl_addr_port = module_manager.module_port(top_module, bl_addr_port_id); + ModulePortId bl_addr_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); + BasicPort bl_addr_port = + module_manager.module_port(top_module, bl_addr_port_id); std::vector initial_bl_addr_values(bl_addr_port.get_width(), 0); - ModulePortId wl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_WL_ADDRESS_PORT_NAME)); - BasicPort wl_addr_port = module_manager.module_port(top_module, wl_addr_port_id); + ModulePortId wl_addr_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); + BasicPort wl_addr_port = + module_manager.module_port(top_module, wl_addr_port_id); std::vector initial_wl_addr_values(wl_addr_port.get_width(), 0); - ModulePortId din_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_DATA_IN_PORT_NAME)); + ModulePortId din_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_DATA_IN_PORT_NAME)); BasicPort din_port = module_manager.module_port(top_module, din_port_id); std::vector initial_din_values(din_port.get_width(), 0); /* Define a constant for the bitstream length */ - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), fabric_bits_by_addr.size() - num_bits_to_skip); - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), bl_addr_port.get_width() + wl_addr_port.get_width() + din_port.get_width()); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), + fabric_bits_by_addr.size() - num_bits_to_skip); + print_verilog_define_flag( + fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), + bl_addr_port.get_width() + wl_addr_port.get_width() + din_port.get_width()); /* Declare local variables for bitstream loading in Verilog */ - print_verilog_comment(fp, "----- Virtual memory to store the bitstream from external file -----"); + print_verilog_comment( + fp, "----- Virtual memory to store the bitstream from external file -----"); fp << "reg [0:`" << TOP_TB_BITSTREAM_WIDTH_VARIABLE << " - 1] "; - fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1];"; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" + << 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; + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " + << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; - print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); + print_verilog_comment( + fp, "----- Preload bitstream file to a virtual memory -----"); fp << "initial begin" << std::endl; fp << "\t"; - fp << "$readmemb(\"" << bitstream_file << "\", " << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; + fp << "$readmemb(\"" << bitstream_file << "\", " + << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; fp << std::endl; print_verilog_comment(fp, "----- Bit-Line Address port default input -----"); fp << "\t"; - fp << generate_verilog_port_constant_values(bl_addr_port, initial_bl_addr_values); + fp << generate_verilog_port_constant_values(bl_addr_port, + initial_bl_addr_values); fp << ";"; fp << std::endl; print_verilog_comment(fp, "----- Word-Line Address port default input -----"); fp << "\t"; - fp << generate_verilog_port_constant_values(wl_addr_port, initial_wl_addr_values); + fp << generate_verilog_port_constant_values(wl_addr_port, + initial_wl_addr_values); fp << ";"; fp << std::endl; @@ -1559,10 +1785,14 @@ void print_verilog_full_testbench_memory_bank_bitstream(std::fstream& fp, fp << "end"; fp << std::endl; - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1); + print_verilog_comment( + fp, "----- Begin bitstream loading during configuration phase -----"); + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + + std::string(TOP_TB_CLOCK_REG_POSTFIX), + 1); fp << "always"; - fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " @(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; fp << " begin"; fp << std::endl; @@ -1577,7 +1807,8 @@ void print_verilog_full_testbench_memory_bank_bitstream(std::fstream& fp, 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 << generate_verilog_port_constant_values(config_done_port, + config_done_final_values, true); fp << ";" << std::endl; fp << "\t"; @@ -1586,14 +1817,15 @@ void print_verilog_full_testbench_memory_bank_bitstream(std::fstream& fp, fp << "\t\t"; fp << "{"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, bl_addr_port); + fp << generate_verilog_port(VERILOG_PORT_CONKT, bl_addr_port); fp << ", "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, wl_addr_port); + fp << generate_verilog_port(VERILOG_PORT_CONKT, wl_addr_port); fp << ", "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port); + fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port); fp << "}"; 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"; @@ -1609,31 +1841,33 @@ void print_verilog_full_testbench_memory_bank_bitstream(std::fstream& fp, fp << "end"; fp << std::endl; - print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); + print_verilog_comment( + fp, "----- End bitstream loading during configuration phase -----"); } /******************************************************************** * Print stimulus for a FPGA fabric with a frame-based configuration protocol * where configuration bits are programming in serial (one by one) *******************************************************************/ -static -void print_verilog_full_testbench_frame_decoder_bitstream(std::fstream& fp, - const std::string& bitstream_file, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricBitstream& fabric_bitstream) { +static void print_verilog_full_testbench_frame_decoder_bitstream( + std::fstream& fp, const std::string& bitstream_file, + const bool& fast_configuration, const bool& bit_value_to_skip, + const ModuleManager& module_manager, const ModuleId& top_module, + const FabricBitstream& fabric_bitstream) { /* Validate the file stream */ valid_file_stream(fp); /* Reorganize the fabric bitstream by the same address across regions */ - FrameFabricBitstream fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream); + FrameFabricBitstream fabric_bits_by_addr = + build_frame_based_fabric_bitstream_by_address(fabric_bitstream); /* For fast configuration, identify the final bitstream size to be used */ size_t num_bits_to_skip = 0; if (true == fast_configuration) { - num_bits_to_skip = fabric_bits_by_addr.size() - find_frame_based_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); + num_bits_to_skip = + fabric_bits_by_addr.size() - + find_frame_based_fast_configuration_fabric_bitstream_size( + fabric_bitstream, bit_value_to_skip); } VTR_ASSERT(num_bits_to_skip < fabric_bits_by_addr.size()); @@ -1641,32 +1875,39 @@ void print_verilog_full_testbench_frame_decoder_bitstream(std::fstream& fp, * Note: the first cycle is reserved for programming reset * We should give dummy values */ - ModulePortId addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_ADDRESS_PORT_NAME)); + ModulePortId addr_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_ADDRESS_PORT_NAME)); BasicPort addr_port = module_manager.module_port(top_module, addr_port_id); std::vector initial_addr_values(addr_port.get_width(), 0); - ModulePortId din_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_DATA_IN_PORT_NAME)); + ModulePortId din_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_DATA_IN_PORT_NAME)); BasicPort din_port = module_manager.module_port(top_module, din_port_id); std::vector initial_din_values(din_port.get_width(), 0); /* Define a constant for the bitstream length */ - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), fabric_bits_by_addr.size() - num_bits_to_skip); - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), addr_port.get_width() + din_port.get_width()); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), + fabric_bits_by_addr.size() - num_bits_to_skip); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), + addr_port.get_width() + din_port.get_width()); /* Declare local variables for bitstream loading in Verilog */ - print_verilog_comment(fp, "----- Virtual memory to store the bitstream from external file -----"); + print_verilog_comment( + fp, "----- Virtual memory to store the bitstream from external file -----"); fp << "reg [0:`" << TOP_TB_BITSTREAM_WIDTH_VARIABLE << " - 1] "; - fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1];"; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" + << 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; + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " + << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; - print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); + print_verilog_comment( + fp, "----- Preload bitstream file to a virtual memory -----"); fp << "initial begin" << std::endl; fp << "\t"; - fp << "$readmemb(\"" << bitstream_file << "\", " << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; + fp << "$readmemb(\"" << bitstream_file << "\", " + << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; fp << std::endl; print_verilog_comment(fp, "----- Address port default input -----"); @@ -1689,10 +1930,14 @@ void print_verilog_full_testbench_frame_decoder_bitstream(std::fstream& fp, fp << "end"; fp << std::endl; - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1); + print_verilog_comment( + fp, "----- Begin bitstream loading during configuration phase -----"); + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + + std::string(TOP_TB_CLOCK_REG_POSTFIX), + 1); fp << "always"; - fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " @(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; fp << " begin"; fp << std::endl; @@ -1707,7 +1952,8 @@ void print_verilog_full_testbench_frame_decoder_bitstream(std::fstream& fp, 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 << generate_verilog_port_constant_values(config_done_port, + config_done_final_values, true); fp << ";" << std::endl; fp << "\t"; @@ -1716,12 +1962,13 @@ void print_verilog_full_testbench_frame_decoder_bitstream(std::fstream& fp, fp << "\t\t"; fp << "{"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); + fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); fp << ", "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port); + fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port); fp << "}"; 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"; @@ -1737,89 +1984,69 @@ void print_verilog_full_testbench_frame_decoder_bitstream(std::fstream& fp, fp << "end"; fp << std::endl; - print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); + print_verilog_comment( + fp, "----- End bitstream loading during configuration phase -----"); } /******************************************************************** * Generate the stimuli for the full testbench - * The simulation consists of two phases: configuration phase and operation phase - * Configuration bits are loaded serially. - * This is actually what we do for a physical FPGA + * The simulation consists of two phases: configuration phase and operation + *phase Configuration bits are loaded serially. This is actually what we do for + *a physical FPGA *******************************************************************/ -static -void print_verilog_full_testbench_bitstream(std::fstream& fp, - const std::string& bitstream_file, - const ConfigProtocol& config_protocol, - 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 MemoryBankShiftRegisterBanks& blwl_sr_banks) { - +static void print_verilog_full_testbench_bitstream( + std::fstream& fp, const std::string& bitstream_file, + const ConfigProtocol& config_protocol, 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 MemoryBankShiftRegisterBanks& blwl_sr_banks) { /* Branch on the type of configuration protocol */ switch (config_protocol.type()) { - case CONFIG_MEM_STANDALONE: - print_verilog_full_testbench_vanilla_bitstream(fp, - bitstream_file, - module_manager, - top_module, - fabric_bitstream); + case CONFIG_MEM_STANDALONE: + print_verilog_full_testbench_vanilla_bitstream( + fp, bitstream_file, module_manager, top_module, fabric_bitstream); - break; - 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); - break; - case CONFIG_MEM_MEMORY_BANK: - print_verilog_full_testbench_memory_bank_bitstream(fp, bitstream_file, - fast_configuration, - bit_value_to_skip, - module_manager, top_module, - fabric_bitstream); - break; - case CONFIG_MEM_QL_MEMORY_BANK: - print_verilog_full_testbench_ql_memory_bank_bitstream(fp, bitstream_file, - config_protocol, - fast_configuration, - bit_value_to_skip, - module_manager, top_module, - fabric_bitstream, blwl_sr_banks); - break; - case CONFIG_MEM_FRAME_BASED: - print_verilog_full_testbench_frame_decoder_bitstream(fp, bitstream_file, - fast_configuration, - bit_value_to_skip, - module_manager, top_module, - fabric_bitstream); + break; + 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); + break; + case CONFIG_MEM_MEMORY_BANK: + print_verilog_full_testbench_memory_bank_bitstream( + fp, bitstream_file, fast_configuration, bit_value_to_skip, + module_manager, top_module, fabric_bitstream); + break; + case CONFIG_MEM_QL_MEMORY_BANK: + print_verilog_full_testbench_ql_memory_bank_bitstream( + fp, bitstream_file, config_protocol, fast_configuration, + bit_value_to_skip, module_manager, top_module, fabric_bitstream, + blwl_sr_banks); + break; + case CONFIG_MEM_FRAME_BASED: + print_verilog_full_testbench_frame_decoder_bitstream( + fp, bitstream_file, fast_configuration, bit_value_to_skip, + module_manager, top_module, fabric_bitstream); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid configuration protocol type!\n"); - exit(1); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid configuration protocol type!\n"); + exit(1); } } - /******************************************************************** * Connect proper stimuli to the reset port * This function is designed to drive the reset port of a benchmark module *******************************************************************/ -static -void print_verilog_top_testbench_reset_stimuli(std::fstream& fp, - const AtomContext& atom_ctx, - const VprNetlistAnnotation& netlist_annotation, - const ModuleManager& module_manager, - const FabricGlobalPortInfo& global_ports, - const PinConstraints& pin_constraints, - const std::string& port_name_postfix, - const std::vector& clock_port_names) { +static void print_verilog_top_testbench_reset_stimuli( + std::fstream& fp, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const ModuleManager& module_manager, const FabricGlobalPortInfo& global_ports, + const PinConstraints& pin_constraints, const std::string& port_name_postfix, + const std::vector& clock_port_names) { valid_file_stream(fp); print_verilog_comment(fp, "----- Begin reset signal generation -----"); @@ -1830,31 +2057,38 @@ void print_verilog_top_testbench_reset_stimuli(std::fstream& fp, continue; } - /* The block may be renamed as it contains special characters which violate Verilog syntax */ + /* The block may be renamed as it contains special characters which violate + * Verilog syntax */ std::string block_name = atom_ctx.nlist.block_name(atom_blk); if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); - } + } /* Bypass clock ports because their stimulus cannot be random */ - if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), block_name)) { + if (clock_port_names.end() != std::find(clock_port_names.begin(), + clock_port_names.end(), + block_name)) { continue; } - /* Bypass any constained net that are mapped to a global port of the FPGA fabric - * because their stimulus cannot be random + /* Bypass any constained net that are mapped to a global port of the FPGA + * fabric because their stimulus cannot be random */ - if (false == port_is_fabric_global_reset_port(global_ports, module_manager, pin_constraints.net_pin(block_name))) { + if (false == + port_is_fabric_global_reset_port(global_ports, module_manager, + pin_constraints.net_pin(block_name))) { continue; } - size_t initial_value = global_ports.global_port_default_value(find_fabric_global_port(global_ports, module_manager, pin_constraints.net_pin(block_name))); + size_t initial_value = + global_ports.global_port_default_value(find_fabric_global_port( + global_ports, module_manager, pin_constraints.net_pin(block_name))); - /* Connect stimuli to greset with an optional inversion, depending on the default value */ + /* Connect stimuli to greset with an optional inversion, depending on the + * default value */ BasicPort reset_port(block_name + port_name_postfix, 1); - print_verilog_wire_connection(fp, reset_port, - BasicPort(TOP_TB_RESET_PORT_NAME, 1), - 1 == initial_value); + print_verilog_wire_connection( + fp, reset_port, BasicPort(TOP_TB_RESET_PORT_NAME, 1), 1 == initial_value); } } @@ -1864,23 +2098,26 @@ void print_verilog_top_testbench_reset_stimuli(std::fstream& fp, * - Check that the configuration done signal is raised, indicating * that the configuration phase is finished *******************************************************************/ -static -void print_verilog_top_testbench_check(std::fstream& fp, - const std::string& config_done_port_name, - const std::string& error_counter_name) { - +static void print_verilog_top_testbench_check( + std::fstream& fp, const std::string& config_done_port_name, + const std::string& error_counter_name) { /* Validate the file stream */ valid_file_stream(fp); - print_verilog_comment(fp, std::string("----- Configuration done must be raised in the end -------")); + print_verilog_comment( + fp, + std::string("----- Configuration done must be raised in the end -------")); BasicPort config_done_port(config_done_port_name, 1); write_tab_to_file(fp, 1); - fp << "always@(posedge " << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port) << ") begin" << std::endl; + fp << "always@(posedge " + << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port) << ") begin" + << std::endl; write_tab_to_file(fp, 2); - fp << error_counter_name << " = " << error_counter_name << " - 1;" << std::endl; + fp << error_counter_name << " = " << error_counter_name << " - 1;" + << std::endl; write_tab_to_file(fp, 1); fp << "end" << std::endl; @@ -1901,37 +2138,34 @@ void print_verilog_top_testbench_check(std::fstream& fp, * | | | | | * | +----------+ | | * | | Output | - * random_input_vectors -----+ | Vector |---->Functional correct? - * | | Comparator | - * | +-----------+ | | - * | | Input | | | + * random_input_vectors -----+ | Vector + *|---->Functional correct? | | Comparator | | + *+-----------+ | | | | Input | | | * +----->| Benchmark |----->| | * +-----------+ +------------+ * *******************************************************************/ -int print_verilog_full_testbench(const ModuleManager& module_manager, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const FabricGlobalPortInfo& global_ports, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const std::string& bitstream_file, - const IoLocationMap& io_location_map, - const VprNetlistAnnotation& netlist_annotation, - const std::string& circuit_name, - const std::string& verilog_fname, - const SimulationSetting& simulation_parameters, - const VerilogTestbenchOption& options) { - +int print_verilog_full_testbench( + const ModuleManager& module_manager, + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const FabricGlobalPortInfo& global_ports, const AtomContext& atom_ctx, + const PlacementContext& place_ctx, const PinConstraints& pin_constraints, + const BusGroup& bus_group, const std::string& bitstream_file, + const IoLocationMap& io_location_map, + const VprNetlistAnnotation& netlist_annotation, + const std::string& circuit_name, const std::string& verilog_fname, + const SimulationSetting& simulation_parameters, + const VerilogTestbenchOption& options) { bool fast_configuration = options.fast_configuration(); bool explicit_port_mapping = options.explicit_port_mapping(); - std::string timer_message = std::string("Write autocheck testbench for FPGA top-level Verilog netlist for '") + circuit_name + std::string("'"); + std::string timer_message = + std::string( + "Write autocheck testbench for FPGA top-level Verilog netlist for '") + + circuit_name + std::string("'"); /* Start time count */ vtr::ScopedStartFinishTimer timer(timer_message); @@ -1944,85 +2178,85 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, check_file_stream(verilog_fname.c_str(), fp); /* Generate a brief description on the Verilog file*/ - std::string title = std::string("FPGA Verilog full testbench for top-level netlist of design: ") + circuit_name; + std::string title = + std::string( + "FPGA Verilog full testbench for top-level netlist of design: ") + + circuit_name; print_verilog_file_header(fp, title, options.time_stamp()); /* Find the top_module */ - ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name()); + ModuleId top_module = + module_manager.find_module(generate_fpga_top_module_name()); VTR_ASSERT(true == module_manager.valid_module_id(top_module)); /* Preparation: find all the clock ports */ - std::vector clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); + std::vector clock_port_names = + find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); /* Preparation: find all the reset/set ports for programming usage */ - std::vector global_prog_reset_ports = find_fabric_global_programming_reset_ports(global_ports); - std::vector global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports); + std::vector global_prog_reset_ports = + find_fabric_global_programming_reset_ports(global_ports); + std::vector global_prog_set_ports = + find_fabric_global_programming_set_ports(global_ports); /* Identify if we can apply fast configuration */ - bool apply_fast_configuration = fast_configuration && is_fast_configuration_applicable(global_ports); + bool apply_fast_configuration = + fast_configuration && is_fast_configuration_applicable(global_ports); bool bit_value_to_skip = false; if (true == apply_fast_configuration) { - bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration(config_protocol.type(), - global_ports, - bitstream_manager, - fabric_bitstream); + bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration( + config_protocol.type(), global_ports, bitstream_manager, + fabric_bitstream); } /* Start of testbench */ - print_verilog_top_testbench_ports(fp, module_manager, top_module, - atom_ctx, netlist_annotation, - clock_port_names, - global_ports, - pin_constraints, - simulation_parameters, config_protocol, - circuit_name, - options); + print_verilog_top_testbench_ports( + fp, module_manager, top_module, atom_ctx, netlist_annotation, + clock_port_names, global_ports, pin_constraints, simulation_parameters, + config_protocol, circuit_name, options); /* Find the clock period */ - float prog_clock_period = (1./simulation_parameters.programming_clock_frequency()); - float default_op_clock_period = (1./simulation_parameters.default_operating_clock_frequency()); + float prog_clock_period = + (1. / simulation_parameters.programming_clock_frequency()); + float default_op_clock_period = + (1. / simulation_parameters.default_operating_clock_frequency()); float max_op_clock_period = 0.; - for (const SimulationClockId& clock_id : simulation_parameters.operating_clocks()) { - max_op_clock_period = std::max(max_op_clock_period, (float)(1./simulation_parameters.clock_frequency(clock_id))); + for (const SimulationClockId& clock_id : + simulation_parameters.operating_clocks()) { + max_op_clock_period = + std::max(max_op_clock_period, + (float)(1. / simulation_parameters.clock_frequency(clock_id))); } /* Estimate the number of configuration clock cycles */ - size_t num_config_clock_cycles = calculate_num_config_clock_cycles(config_protocol, - apply_fast_configuration, - bit_value_to_skip, - bitstream_manager, - fabric_bitstream); + size_t num_config_clock_cycles = calculate_num_config_clock_cycles( + config_protocol, apply_fast_configuration, bit_value_to_skip, + bitstream_manager, fabric_bitstream); /* Generate stimuli for general control signals */ - print_verilog_top_testbench_generic_stimulus(fp, - simulation_parameters, - num_config_clock_cycles, - prog_clock_period, - default_op_clock_period, - VERILOG_SIM_TIMESCALE); + print_verilog_top_testbench_generic_stimulus( + fp, 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; - status = print_verilog_top_testbench_configuration_protocol_stimulus(fp, - config_protocol, simulation_parameters, - module_manager, top_module, - fast_configuration, bit_value_to_skip, - fabric_bitstream, blwl_sr_banks, - prog_clock_period, - VERILOG_SIM_TIMESCALE); + status = print_verilog_top_testbench_configuration_protocol_stimulus( + fp, config_protocol, simulation_parameters, module_manager, top_module, + fast_configuration, bit_value_to_skip, fabric_bitstream, blwl_sr_banks, + prog_clock_period, VERILOG_SIM_TIMESCALE); if (status == CMD_EXEC_FATAL_ERROR) { return status; } - + /* Identify the stimulus for global reset/set for programming purpose: - * - If only reset port is seen we turn on Reset - * - If only set port is seen we turn on Reset + * - If only reset port is seen we turn on Reset + * - If only set port is seen we turn on Reset * - If both reset and set port is defined, * we pick the one which is consistent with the bit value to be skipped */ - bool active_global_prog_reset = false; - bool active_global_prog_set = false; + bool active_global_prog_reset = false; + bool active_global_prog_set = false; if (!global_prog_reset_ports.empty()) { active_global_prog_reset = true; @@ -2033,8 +2267,7 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, } /* Ensure that at most only one of the two switches is activated */ - if ( (true == active_global_prog_reset) - && (true == active_global_prog_set) ) { + if ((true == active_global_prog_reset) && (true == active_global_prog_set)) { /* If we will skip logic '0', we will activate programming reset */ active_global_prog_reset = !bit_value_to_skip; /* If we will skip logic '1', we will activate programming set */ @@ -2042,127 +2275,102 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, } /* 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, - simulation_parameters, - active_global_prog_reset, - active_global_prog_set); + print_verilog_top_testbench_global_ports_stimuli( + fp, module_manager, top_module, pin_constraints, global_ports, + simulation_parameters, active_global_prog_reset, active_global_prog_set); /* Instanciate FPGA top-level module */ - print_verilog_testbench_fpga_instance(fp, module_manager, top_module, - std::string(TOP_TESTBENCH_FPGA_INSTANCE_NAME), - std::string(), - explicit_port_mapping); + print_verilog_testbench_fpga_instance( + fp, module_manager, top_module, + std::string(TOP_TESTBENCH_FPGA_INSTANCE_NAME), std::string(), + explicit_port_mapping); /* Connect I/Os to benchmark I/Os or constant driver */ - print_verilog_testbench_connect_fpga_ios(fp, module_manager, top_module, - atom_ctx, place_ctx, io_location_map, - netlist_annotation, - BusGroup(), - std::string(), - std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX), - std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX), - clock_port_names, - (size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE); + print_verilog_testbench_connect_fpga_ios( + fp, module_manager, top_module, atom_ctx, place_ctx, io_location_map, + netlist_annotation, BusGroup(), std::string(), + std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX), + std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX), clock_port_names, + (size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE); /* Instanciate input benchmark */ if (!options.no_self_checking()) { - print_verilog_top_testbench_benchmark_instance(fp, - circuit_name, - atom_ctx, - netlist_annotation, - pin_constraints, - bus_group, - clock_port_names, - explicit_port_mapping); + print_verilog_top_testbench_benchmark_instance( + fp, circuit_name, atom_ctx, netlist_annotation, pin_constraints, + bus_group, clock_port_names, explicit_port_mapping); } /* load bitstream to FPGA fabric in a configuration phase */ - print_verilog_full_testbench_bitstream(fp, - bitstream_file, - config_protocol, - apply_fast_configuration, - bit_value_to_skip, - module_manager, top_module, - bitstream_manager, fabric_bitstream, blwl_sr_banks); + print_verilog_full_testbench_bitstream( + fp, bitstream_file, config_protocol, apply_fast_configuration, + bit_value_to_skip, module_manager, top_module, bitstream_manager, + fabric_bitstream, blwl_sr_banks); - /* Add signal initialization: - * Bypass writing codes to files due to the autogenerated codes are very large. + /* Add signal initialization: + * Bypass writing codes to files due to the autogenerated codes are very + * large. */ if (true == options.include_signal_init()) { - print_verilog_testbench_signal_initialization(fp, - std::string(TOP_TESTBENCH_FPGA_INSTANCE_NAME), - circuit_lib, - module_manager, - top_module, - true); + print_verilog_testbench_signal_initialization( + fp, std::string(TOP_TESTBENCH_FPGA_INSTANCE_NAME), circuit_lib, + module_manager, top_module, true); } - /* Add stimuli for reset, set, clock and iopad signals */ - print_verilog_top_testbench_reset_stimuli(fp, - atom_ctx, - netlist_annotation, - module_manager, - global_ports, - pin_constraints, - std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX), - clock_port_names); - print_verilog_testbench_random_stimuli(fp, atom_ctx, - netlist_annotation, - module_manager, - global_ports, - pin_constraints, - clock_port_names, - std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX), - std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX), - std::vector(1, BasicPort(std::string(TOP_TB_OP_CLOCK_PORT_NAME), 1)), - options.no_self_checking()); + print_verilog_top_testbench_reset_stimuli( + fp, atom_ctx, netlist_annotation, module_manager, global_ports, + pin_constraints, std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX), + clock_port_names); + print_verilog_testbench_random_stimuli( + fp, atom_ctx, netlist_annotation, module_manager, global_ports, + pin_constraints, clock_port_names, + std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX), + std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX), + std::vector( + 1, BasicPort(std::string(TOP_TB_OP_CLOCK_PORT_NAME), 1)), + options.no_self_checking()); if (!options.no_self_checking()) { /* Add output autocheck */ - print_verilog_testbench_check(fp, - std::string(TOP_TESTBENCH_SIM_START_PORT_NAME), - 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_TESTBENCH_ERROR_COUNTER), - atom_ctx, - netlist_annotation, - clock_port_names, - std::string(TOP_TB_OP_CLOCK_PORT_NAME)); + print_verilog_testbench_check( + fp, std::string(TOP_TESTBENCH_SIM_START_PORT_NAME), + 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_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, + print_verilog_top_testbench_check(fp, std::string(TOP_TB_CONFIG_DONE_PORT_NAME), std::string(TOP_TESTBENCH_ERROR_COUNTER)); } /* Find simulation time */ - float simulation_time = find_simulation_time_period(VERILOG_SIM_TIMESCALE, - num_config_clock_cycles, - 1./simulation_parameters.programming_clock_frequency(), - simulation_parameters.num_clock_cycles(), - 1./simulation_parameters.default_operating_clock_frequency()); + float simulation_time = find_simulation_time_period( + VERILOG_SIM_TIMESCALE, num_config_clock_cycles, + 1. / simulation_parameters.programming_clock_frequency(), + simulation_parameters.num_clock_cycles(), + 1. / simulation_parameters.default_operating_clock_frequency()); - - /* Add Icarus requirement: - * Always ceil the simulation time so that we test a sufficient length of period!!! + /* Add Icarus requirement: + * Always ceil the simulation time so that we test a sufficient length of + * period!!! */ - print_verilog_timeout_and_vcd(fp, - std::string(circuit_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX)), - std::string(circuit_name + std::string("_formal.vcd")), - std::string(TOP_TESTBENCH_SIM_START_PORT_NAME), - std::string(TOP_TESTBENCH_ERROR_COUNTER), - std::ceil(simulation_time), - options.no_self_checking()); - + print_verilog_timeout_and_vcd( + fp, + std::string(circuit_name + + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX)), + std::string(circuit_name + std::string("_formal.vcd")), + std::string(TOP_TESTBENCH_SIM_START_PORT_NAME), + std::string(TOP_TESTBENCH_ERROR_COUNTER), std::ceil(simulation_time), + options.no_self_checking()); /* Testbench ends*/ - print_verilog_module_end(fp, std::string(circuit_name) + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX)); + print_verilog_module_end( + fp, std::string(circuit_name) + + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX)); /* Close the file stream */ fp.close(); @@ -2170,5 +2378,4 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, return status; } - } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.h b/openfpga/src/fpga_verilog/verilog_top_testbench.h index 51f71fee7..dfe24a6c9 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.h @@ -6,20 +6,21 @@ *******************************************************************/ #include #include -#include "module_manager.h" + #include "bitstream_manager.h" -#include "fabric_bitstream.h" +#include "bus_group.h" #include "circuit_library.h" #include "config_protocol.h" -#include "vpr_context.h" -#include "pin_constraints.h" -#include "io_location_map.h" +#include "fabric_bitstream.h" #include "fabric_global_port_info.h" -#include "vpr_netlist_annotation.h" -#include "simulation_setting.h" +#include "io_location_map.h" #include "memory_bank_shift_register_banks.h" +#include "module_manager.h" +#include "pin_constraints.h" +#include "simulation_setting.h" #include "verilog_testbench_options.h" -#include "bus_group.h" +#include "vpr_context.h" +#include "vpr_netlist_annotation.h" /******************************************************************** * Function declaration @@ -28,24 +29,20 @@ /* begin namespace openfpga */ namespace openfpga { -int print_verilog_full_testbench(const ModuleManager& module_manager, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const FabricGlobalPortInfo& global_ports, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const PinConstraints& pin_constraints, - const BusGroup& bus_group, - const std::string& bitstream_file, - const IoLocationMap& io_location_map, - const VprNetlistAnnotation& netlist_annotation, - const std::string& circuit_name, - const std::string& verilog_fname, - const SimulationSetting& simulation_parameters, - const VerilogTestbenchOption& options); +int print_verilog_full_testbench( + const ModuleManager& module_manager, + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const FabricGlobalPortInfo& global_ports, const AtomContext& atom_ctx, + const PlacementContext& place_ctx, const PinConstraints& pin_constraints, + const BusGroup& bus_group, const std::string& bitstream_file, + const IoLocationMap& io_location_map, + const VprNetlistAnnotation& netlist_annotation, + const std::string& circuit_name, const std::string& verilog_fname, + const SimulationSetting& simulation_parameters, + const VerilogTestbenchOption& options); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_constants.h b/openfpga/src/fpga_verilog/verilog_top_testbench_constants.h index 61aab06ac..1d1640d0c 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_constants.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_constants.h @@ -35,8 +35,8 @@ constexpr const char* TOP_TB_BITSTREAM_INDEX_REG_NAME = "bit_index"; constexpr const char* TOP_TB_BITSTREAM_ITERATOR_REG_NAME = "ibit"; constexpr const char* TOP_TB_BITSTREAM_SKIP_FLAG_REG_NAME = "skip_bits"; -constexpr const char* AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX = "_autocheck_top_tb"; - +constexpr const char* AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX = + "_autocheck_top_tb"; } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 0d68e7a16..8b70ef3fb 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -2,203 +2,250 @@ * This file includes functions that are used to create * an auto-check top-level testbench for a FPGA fabric *******************************************************************/ +#include #include #include -#include /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgashell library */ #include "command_exit_codes.h" /* Headers from openfpgautil library */ -#include "openfpga_scale.h" -#include "openfpga_port.h" -#include "openfpga_digest.h" - #include "bitstream_manager_utils.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" -#include "simulation_utils.h" -#include "openfpga_atom_netlist_utils.h" - -#include "fast_configuration.h" #include "fabric_bitstream_utils.h" #include "fabric_global_port_info_utils.h" - +#include "fast_configuration.h" +#include "openfpga_atom_netlist_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" +#include "openfpga_reserved_words.h" +#include "openfpga_scale.h" +#include "simulation_utils.h" #include "verilog_constants.h" -#include "verilog_writer_utils.h" #include "verilog_testbench_utils.h" -#include "verilog_top_testbench_memory_bank.h" - #include "verilog_top_testbench_constants.h" +#include "verilog_top_testbench_memory_bank.h" +#include "verilog_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { constexpr const char* TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME = "bl_sr_clock"; constexpr const char* TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME = "wl_sr_clock"; -constexpr const char* TOP_TB_VIRTUAL_BL_SHIFT_REGISTER_CLOCK_PORT_NAME = "virtual_bl_sr_clock"; -constexpr const char* TOP_TB_VIRTUAL_WL_SHIFT_REGISTER_CLOCK_PORT_NAME = "virtual_wl_sr_clock"; +constexpr const char* TOP_TB_VIRTUAL_BL_SHIFT_REGISTER_CLOCK_PORT_NAME = + "virtual_bl_sr_clock"; +constexpr const char* TOP_TB_VIRTUAL_WL_SHIFT_REGISTER_CLOCK_PORT_NAME = + "virtual_wl_sr_clock"; constexpr const char* TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME = "start_bl_sr"; constexpr const char* TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME = "start_wl_sr"; constexpr const char* TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME = "bl_sr_count"; constexpr const char* TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME = "wl_sr_count"; -constexpr const char* TOP_TB_BITSTREAM_BL_HEAD_WIDTH_VARIABLE = "BITSTREAM_BL_HEAD_WIDTH"; -constexpr const char* TOP_TB_BITSTREAM_WL_HEAD_WIDTH_VARIABLE = "BITSTREAM_WL_HEAD_WIDTH"; -constexpr const char* TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE = "BITSTREAM_BL_WORD_SIZE"; -constexpr const char* TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE = "BITSTREAM_WL_WORD_SIZE"; +constexpr const char* TOP_TB_BITSTREAM_BL_HEAD_WIDTH_VARIABLE = + "BITSTREAM_BL_HEAD_WIDTH"; +constexpr const char* TOP_TB_BITSTREAM_WL_HEAD_WIDTH_VARIABLE = + "BITSTREAM_WL_HEAD_WIDTH"; +constexpr const char* TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE = + "BITSTREAM_BL_WORD_SIZE"; +constexpr const char* TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE = + "BITSTREAM_WL_WORD_SIZE"; -void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigProtocol& config_protocol) { +void print_verilog_top_testbench_ql_memory_bank_port( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, const ConfigProtocol& config_protocol) { /* Validate the file stream */ valid_file_stream(fp); /* Print the address port for the Bit-Line decoder here */ if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { - print_verilog_comment(fp, std::string("---- Address port for Bit-Line decoder -----")); - ModulePortId bl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_BL_ADDRESS_PORT_NAME)); - BasicPort bl_addr_port = module_manager.module_port(top_module, bl_addr_port_id); + print_verilog_comment( + fp, std::string("---- Address port for Bit-Line decoder -----")); + ModulePortId bl_addr_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); + BasicPort bl_addr_port = + module_manager.module_port(top_module, bl_addr_port_id); - fp << generate_verilog_port(VERILOG_PORT_REG, bl_addr_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, bl_addr_port) << ";" + << std::endl; } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { print_verilog_comment(fp, std::string("---- Bit-Line ports -----")); for (const ConfigRegionId& region : module_manager.regions(top_module)) { - ModulePortId bl_port_id = module_manager.find_module_port(top_module, - generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), region)); + ModulePortId bl_port_id = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(MEMORY_BL_PORT_NAME), region)); BasicPort bl_port = module_manager.module_port(top_module, bl_port_id); - fp << generate_verilog_port(VERILOG_PORT_REG, bl_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, bl_port) << ";" + << std::endl; } } else { - VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); + VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == + config_protocol.bl_protocol_type()); print_verilog_comment(fp, std::string("---- Bit-Line ports -----")); for (const ConfigRegionId& region : module_manager.regions(top_module)) { - ModulePortId sr_head_port_id = module_manager.find_module_port(top_module, - generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), region)); - BasicPort sr_head_port = module_manager.module_port(top_module, sr_head_port_id); - fp << generate_verilog_port(VERILOG_PORT_REG, sr_head_port) << ";" << std::endl; + ModulePortId sr_head_port_id = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), region)); + BasicPort sr_head_port = + module_manager.module_port(top_module, sr_head_port_id); + fp << generate_verilog_port(VERILOG_PORT_REG, sr_head_port) << ";" + << std::endl; - ModulePortId sr_tail_port_id = module_manager.find_module_port(top_module, - generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME), region)); - BasicPort sr_tail_port = module_manager.module_port(top_module, sr_tail_port_id); - fp << generate_verilog_port(VERILOG_PORT_WIRE, sr_tail_port) << ";" << std::endl; + ModulePortId sr_tail_port_id = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME), region)); + BasicPort sr_tail_port = + module_manager.module_port(top_module, sr_tail_port_id); + fp << generate_verilog_port(VERILOG_PORT_WIRE, sr_tail_port) << ";" + << std::endl; } /* BL Shift register clock and registers */ - BasicPort virtual_sr_clock_port(std::string(TOP_TB_VIRTUAL_BL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); - fp << generate_verilog_port(VERILOG_PORT_REG, virtual_sr_clock_port) << ";" << std::endl; - BasicPort sr_clock_port(std::string(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); - fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_port) << ";" << std::endl; - + BasicPort virtual_sr_clock_port( + std::string(TOP_TB_VIRTUAL_BL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); + fp << generate_verilog_port(VERILOG_PORT_REG, virtual_sr_clock_port) << ";" + << std::endl; + BasicPort sr_clock_port( + std::string(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); + fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_port) << ";" + << std::endl; /* Register to enable/disable bl/wl shift register clocks */ BasicPort start_bl_sr_port(TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME, 1); - fp << generate_verilog_port(VERILOG_PORT_REG, start_bl_sr_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, start_bl_sr_port) << ";" + << std::endl; /* Register to count bl/wl shift register clocks */ - fp << "integer " << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME << ";" << std::endl; + fp << "integer " << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME << ";" + << std::endl; } /* Print the address port for the Word-Line decoder here */ if (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) { - print_verilog_comment(fp, std::string("---- Address port for Word-Line decoder -----")); - ModulePortId wl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_WL_ADDRESS_PORT_NAME)); - BasicPort wl_addr_port = module_manager.module_port(top_module, wl_addr_port_id); + print_verilog_comment( + fp, std::string("---- Address port for Word-Line decoder -----")); + ModulePortId wl_addr_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); + BasicPort wl_addr_port = + module_manager.module_port(top_module, wl_addr_port_id); - fp << generate_verilog_port(VERILOG_PORT_REG, wl_addr_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, wl_addr_port) << ";" + << std::endl; } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { print_verilog_comment(fp, std::string("---- Word-Line ports -----")); for (const ConfigRegionId& region : module_manager.regions(top_module)) { - ModulePortId wl_port_id = module_manager.find_module_port(top_module, - generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), region)); + ModulePortId wl_port_id = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(MEMORY_WL_PORT_NAME), region)); BasicPort wl_port = module_manager.module_port(top_module, wl_port_id); - fp << generate_verilog_port(VERILOG_PORT_REG, wl_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, wl_port) << ";" + << std::endl; } } else { - VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()); + VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == + config_protocol.wl_protocol_type()); print_verilog_comment(fp, std::string("---- Word-Line ports -----")); for (const ConfigRegionId& region : module_manager.regions(top_module)) { - ModulePortId sr_head_port_id = module_manager.find_module_port(top_module, - generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), region)); - BasicPort sr_head_port = module_manager.module_port(top_module, sr_head_port_id); - fp << generate_verilog_port(VERILOG_PORT_REG, sr_head_port) << ";" << std::endl; + ModulePortId sr_head_port_id = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), region)); + BasicPort sr_head_port = + module_manager.module_port(top_module, sr_head_port_id); + fp << generate_verilog_port(VERILOG_PORT_REG, sr_head_port) << ";" + << std::endl; - ModulePortId sr_tail_port_id = module_manager.find_module_port(top_module, - generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME), region)); - BasicPort sr_tail_port = module_manager.module_port(top_module, sr_tail_port_id); - fp << generate_verilog_port(VERILOG_PORT_WIRE, sr_tail_port) << ";" << std::endl; + ModulePortId sr_tail_port_id = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME), region)); + BasicPort sr_tail_port = + module_manager.module_port(top_module, sr_tail_port_id); + fp << generate_verilog_port(VERILOG_PORT_WIRE, sr_tail_port) << ";" + << std::endl; } /* WL Shift register clock and registers */ - BasicPort virtual_sr_clock_port(std::string(TOP_TB_VIRTUAL_WL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); - fp << generate_verilog_port(VERILOG_PORT_REG, virtual_sr_clock_port) << ";" << std::endl; - BasicPort sr_clock_port(std::string(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); - fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_port) << ";" << std::endl; + BasicPort virtual_sr_clock_port( + std::string(TOP_TB_VIRTUAL_WL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); + fp << generate_verilog_port(VERILOG_PORT_REG, virtual_sr_clock_port) << ";" + << std::endl; + BasicPort sr_clock_port( + std::string(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); + fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_port) << ";" + << std::endl; /* Register to enable/disable bl/wl shift register clocks */ BasicPort start_wl_sr_port(TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME, 1); - fp << generate_verilog_port(VERILOG_PORT_REG, start_wl_sr_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, start_wl_sr_port) << ";" + << std::endl; /* Register to count bl/wl shift register clocks */ - fp << "integer " << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME << ";" << std::endl; + fp << "integer " << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME << ";" + << std::endl; } /* Print the data-input port: only available when BL has a decoder */ if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { - print_verilog_comment(fp, std::string("---- Data input port for memory decoders -----")); - ModulePortId din_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_DATA_IN_PORT_NAME)); + print_verilog_comment( + fp, std::string("---- Data input port for memory decoders -----")); + ModulePortId din_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_DATA_IN_PORT_NAME)); BasicPort din_port = module_manager.module_port(top_module, din_port_id); fp << generate_verilog_port(VERILOG_PORT_REG, din_port) << ";" << std::endl; } /* Print the optional readback port for the decoder here */ if (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) { - print_verilog_comment(fp, std::string("---- Readback port for memory decoders -----")); - ModulePortId readback_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_READBACK_PORT_NAME)); + print_verilog_comment( + fp, std::string("---- Readback port for memory decoders -----")); + ModulePortId readback_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_READBACK_PORT_NAME)); if (readback_port_id) { - BasicPort readback_port = module_manager.module_port(top_module, readback_port_id); - fp << generate_verilog_port(VERILOG_PORT_WIRE, readback_port) << ";" << std::endl; + BasicPort readback_port = + module_manager.module_port(top_module, readback_port_id); + fp << generate_verilog_port(VERILOG_PORT_WIRE, readback_port) << ";" + << std::endl; /* Disable readback in full testbenches */ - print_verilog_wire_constant_values(fp, readback_port, std::vector(readback_port.get_width(), 0)); + print_verilog_wire_constant_values( + fp, readback_port, std::vector(readback_port.get_width(), 0)); } } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { print_verilog_comment(fp, std::string("---- Word line read ports -----")); for (const ConfigRegionId& region : module_manager.regions(top_module)) { - ModulePortId wlr_port_id = module_manager.find_module_port(top_module, - generate_regional_blwl_port_name(std::string(MEMORY_WLR_PORT_NAME), region)); + ModulePortId wlr_port_id = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(MEMORY_WLR_PORT_NAME), region)); if (wlr_port_id) { - BasicPort wlr_port = module_manager.module_port(top_module, wlr_port_id); - fp << generate_verilog_port(VERILOG_PORT_WIRE, wlr_port) << ";" << std::endl; + BasicPort wlr_port = + module_manager.module_port(top_module, wlr_port_id); + fp << generate_verilog_port(VERILOG_PORT_WIRE, wlr_port) << ";" + << std::endl; /* Disable readback in full testbenches */ - print_verilog_wire_constant_values(fp, wlr_port, std::vector(wlr_port.get_width(), 0)); + print_verilog_wire_constant_values( + fp, wlr_port, std::vector(wlr_port.get_width(), 0)); } } } /* Generate enable signal waveform here: - * which is a 90 degree phase shift than the programming clock + * which is a 90 degree phase shift than the programming clock */ - print_verilog_comment(fp, std::string("---- Wire enable port of memory decoders -----")); - ModulePortId en_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_ENABLE_PORT_NAME)); + print_verilog_comment( + fp, std::string("---- Wire enable port of memory decoders -----")); + ModulePortId en_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); if (en_port_id) { en_port = module_manager.module_port(top_module, en_port_id); } - BasicPort en_register_port(std::string(en_port.get_name() + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); + BasicPort en_register_port( + std::string(en_port.get_name() + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); fp << generate_verilog_port(VERILOG_PORT_WIRE, en_port) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_REG, en_register_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, en_register_port) << ";" + << std::endl; write_tab_to_file(fp, 1); fp << "assign "; @@ -210,70 +257,84 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, fp << ";" << std::endl; } - -void print_verilog_top_testbench_global_shift_register_clock_ports_stimuli(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricGlobalPortInfo& fabric_global_port_info) { +void print_verilog_top_testbench_global_shift_register_clock_ports_stimuli( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info) { /* Validate the file stream */ valid_file_stream(fp); /* Connect global clock ports to shift-register programming clock signal */ - for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { + for (const FabricGlobalPortId& fabric_global_port : + fabric_global_port_info.global_ports()) { /* Only care shift register clocks */ - if (false == fabric_global_port_info.global_port_is_clock(fabric_global_port) - || false == fabric_global_port_info.global_port_is_shift_register(fabric_global_port) - || false == fabric_global_port_info.global_port_is_prog(fabric_global_port)) { + if (false == + fabric_global_port_info.global_port_is_clock(fabric_global_port) || + false == fabric_global_port_info.global_port_is_shift_register( + fabric_global_port) || + false == + fabric_global_port_info.global_port_is_prog(fabric_global_port)) { continue; } /* Find the module port */ - ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port); - VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port)); - + ModulePortId module_global_port = + fabric_global_port_info.global_module_port(fabric_global_port); + VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, + module_global_port)); + BasicPort stimuli_clock_port; if (true == fabric_global_port_info.global_port_is_bl(fabric_global_port)) { - stimuli_clock_port.set_name(std::string(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME)); + stimuli_clock_port.set_name( + std::string(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME)); stimuli_clock_port.set_width(1); } else { - VTR_ASSERT(true == fabric_global_port_info.global_port_is_wl(fabric_global_port)); - stimuli_clock_port.set_name(std::string(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME)); + VTR_ASSERT(true == + fabric_global_port_info.global_port_is_wl(fabric_global_port)); + stimuli_clock_port.set_name( + std::string(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME)); stimuli_clock_port.set_width(1); } - for (const size_t& pin : module_manager.module_port(top_module, module_global_port).pins()) { - BasicPort global_port_to_connect(module_manager.module_port(top_module, module_global_port).get_name(), pin, pin); - print_verilog_wire_connection(fp, global_port_to_connect, - stimuli_clock_port, - 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); - } + for (const size_t& pin : + module_manager.module_port(top_module, module_global_port).pins()) { + BasicPort global_port_to_connect( + module_manager.module_port(top_module, module_global_port).get_name(), + pin, pin); + print_verilog_wire_connection( + fp, global_port_to_connect, stimuli_clock_port, + 1 == fabric_global_port_info.global_port_default_value( + fabric_global_port)); + } } } /** - * @brief Generate the Verilog codes for a shift register virtual clock that controls BL/WL protocols - * The virtual clock is the reference clock, which include 1 additional clock cycle for reset - * when compared to the actual clock + * @brief Generate the Verilog codes for a shift register virtual clock that + * controls BL/WL protocols The virtual clock is the reference clock, which + * include 1 additional clock cycle for reset when compared to the actual clock */ -static -void print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator(std::fstream& fp, - const BasicPort& start_sr_port, - const BasicPort& sr_clock_port, - const float& sr_clock_period) { +static void +print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator( + std::fstream& fp, const BasicPort& start_sr_port, + const BasicPort& sr_clock_port, const float& sr_clock_period) { /* Validate the file stream */ valid_file_stream(fp); fp << "always"; - fp << " @(posedge " << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) << ")"; + fp << " @(posedge " + << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) << ")"; fp << " begin"; fp << std::endl; fp << "\t"; - fp << generate_verilog_port_constant_values(sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); + fp << generate_verilog_port_constant_values( + sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); fp << ";" << std::endl; fp << "\t"; - fp << "while (" << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) << ") begin"; + fp << "while (" << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) + << ") begin"; fp << std::endl; fp << "\t\t"; @@ -285,27 +346,28 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_ge fp << std::endl; fp << "\t"; - fp << generate_verilog_port_constant_values(sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); + fp << generate_verilog_port_constant_values( + sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); fp << ";" << std::endl; fp << "end"; fp << std::endl; } - /** - * @brief Generate the Verilog codes for a shift register clocks that controls BL/WL protocols + * @brief Generate the Verilog codes for a shift register clocks that controls + * BL/WL protocols */ -static -void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(std::fstream& fp, - const BasicPort& start_sr_port, - const BasicPort& sr_clock_port, - const float& sr_clock_period) { +static void +print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator( + std::fstream& fp, const BasicPort& start_sr_port, + const BasicPort& sr_clock_port, const float& sr_clock_period) { /* Validate the file stream */ valid_file_stream(fp); fp << "always"; - fp << " @(posedge " << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) << ")"; + fp << " @(posedge " + << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) << ")"; fp << " begin"; fp << std::endl; @@ -315,11 +377,13 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator( fp << std::endl; fp << "\t"; - fp << generate_verilog_port_constant_values(sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); + fp << generate_verilog_port_constant_values( + sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); fp << ";" << std::endl; fp << "\t"; - fp << "while (" << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) << ") begin"; + fp << "while (" << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) + << ") begin"; fp << std::endl; fp << "\t\t"; @@ -331,7 +395,8 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator( fp << std::endl; fp << "\t"; - fp << generate_verilog_port_constant_values(sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); + fp << generate_verilog_port_constant_values( + sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); fp << ";" << std::endl; fp << "end"; @@ -339,29 +404,38 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator( } /** - * @brief Update the clock period of shift register chain by considering the constraints from simulation settings - * - If the frequency is lower than the pre-computed bound, we should error out! Shift register chain cannot load the data completely - * - If the frequency is higher than the pre-computed bound, we use the contrained frequency - * @param sr_clock_port is the clock port which expect constraints - * @param sr_clock_period is the pre-constrained clock period. It is also the final clock period which will be return (if updated) + * @brief Update the clock period of shift register chain by considering the + * constraints from simulation settings + * - If the frequency is lower than the pre-computed bound, we should error out! + * Shift register chain cannot load the data completely + * - If the frequency is higher than the pre-computed bound, we use the + * contrained frequency + * @param sr_clock_port is the clock port which expect constraints + * @param sr_clock_period is the pre-constrained clock period. It is also the + * final clock period which will be return (if updated) */ -static -int constrain_blwl_shift_register_clock_period_from_simulation_settings(const SimulationSetting& sim_settings, - const BasicPort& sr_clock_port, - const float& timescale, - float& sr_clock_period) { - for (const SimulationClockId& sim_clk : sim_settings.programming_shift_register_clocks()) { +static int constrain_blwl_shift_register_clock_period_from_simulation_settings( + const SimulationSetting& sim_settings, const BasicPort& sr_clock_port, + const float& timescale, float& sr_clock_period) { + for (const SimulationClockId& sim_clk : + sim_settings.programming_shift_register_clocks()) { /* Bypass all the clocks which does not match */ - if (sim_settings.clock_name(sim_clk) == sr_clock_port.get_name() && sim_settings.constrained_clock(sim_clk)) { - if (1. / (2. * sr_clock_period * timescale) > sim_settings.clock_frequency(sim_clk)) { - VTR_LOG_ERROR("Constrained clock frequency (=%g %s) for BL shift registers is lower than the minimum requirement (=%g %s)! Shift register chain cannot load data completely!\n", - sim_settings.clock_frequency(sim_clk) / 1e6, - time_unit_to_string(1e6, "Hz").c_str(), - 1. / (2. * sr_clock_period * timescale) / 1e6, - time_unit_to_string(1e6, "Hz").c_str()); + if (sim_settings.clock_name(sim_clk) == sr_clock_port.get_name() && + sim_settings.constrained_clock(sim_clk)) { + if (1. / (2. * sr_clock_period * timescale) > + sim_settings.clock_frequency(sim_clk)) { + VTR_LOG_ERROR( + "Constrained clock frequency (=%g %s) for BL shift registers is " + "lower than the minimum requirement (=%g %s)! Shift register chain " + "cannot load data completely!\n", + sim_settings.clock_frequency(sim_clk) / 1e6, + time_unit_to_string(1e6, "Hz").c_str(), + 1. / (2. * sr_clock_period * timescale) / 1e6, + time_unit_to_string(1e6, "Hz").c_str()); return CMD_EXEC_FATAL_ERROR; } else { - sr_clock_period = 0.5 * (1. / sim_settings.clock_frequency(sim_clk)) / timescale; + sr_clock_period = + 0.5 * (1. / sim_settings.clock_frequency(sim_clk)) / timescale; VTR_LOG("Will use constrained clock frequency (=%g %s) for %s.\n", sim_settings.clock_frequency(sim_clk) / 1e6, time_unit_to_string(1e6, "Hz").c_str(), @@ -373,54 +447,63 @@ int constrain_blwl_shift_register_clock_period_from_simulation_settings(const Si return CMD_EXEC_SUCCESS; } -int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp, - const ConfigProtocol& config_protocol, - const SimulationSetting& sim_settings, - const ModuleManager& module_manager, - const ModuleId& top_module, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const FabricBitstream& fabric_bitstream, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const float& prog_clock_period, - const float& timescale) { - ModulePortId en_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_ENABLE_PORT_NAME)); +int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus( + std::fstream& fp, const ConfigProtocol& config_protocol, + const SimulationSetting& sim_settings, const ModuleManager& module_manager, + const ModuleId& top_module, const bool& fast_configuration, + const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const float& prog_clock_period, const float& timescale) { + ModulePortId en_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); if (en_port_id) { en_port = module_manager.module_port(top_module, en_port_id); } - BasicPort en_register_port(std::string(en_port.get_name() + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); - print_verilog_comment(fp, std::string("---- Generate enable signal waveform -----")); + BasicPort en_register_port( + std::string(en_port.get_name() + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); + print_verilog_comment( + fp, std::string("---- Generate enable signal waveform -----")); print_verilog_shifted_clock_stimuli(fp, en_register_port, 0.25 * prog_clock_period / timescale, 0.5 * prog_clock_period / timescale, 0); /* Stimulus only for shift-register-based BL/WL protocols */ - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1); - BasicPort virtual_bl_sr_clock_port(TOP_TB_VIRTUAL_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); - BasicPort virtual_wl_sr_clock_port(TOP_TB_VIRTUAL_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + + std::string(TOP_TB_CLOCK_REG_POSTFIX), + 1); + BasicPort virtual_bl_sr_clock_port( + TOP_TB_VIRTUAL_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); + BasicPort virtual_wl_sr_clock_port( + TOP_TB_VIRTUAL_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); BasicPort bl_sr_clock_port(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); BasicPort wl_sr_clock_port(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); BasicPort start_bl_sr_port(TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME, 1); BasicPort start_wl_sr_port(TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME, 1); /* Reorganize the fabric bitstream by the same address across regions */ - if ( (CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) - && (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) - && (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()) ) { - MemoryBankShiftRegisterFabricBitstream fabric_bits_by_addr = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, - blwl_sr_banks, - fast_configuration, - bit_value_to_skip); + if ((CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) && + (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) && + (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type())) { + MemoryBankShiftRegisterFabricBitstream fabric_bits_by_addr = + build_memory_bank_shift_register_fabric_bitstream( + fabric_bitstream, blwl_sr_banks, fast_configuration, bit_value_to_skip); - /* Compute the auto-tuned clock period first, this is the lower bound of the shift register clock periods: - * - the BL/WL shift register clock only works in the second half of the programming clock period - * - consider two additional clocks to avoid racing between programming clock and shift register clocks at edge - * TODO: To figure out what is the min. slack required here. See something strange in HDL simulation + /* Compute the auto-tuned clock period first, this is the lower bound of the + * shift register clock periods: + * - the BL/WL shift register clock only works in the second half of the + * programming clock period + * - consider two additional clocks to avoid racing between programming + * clock and shift register clocks at edge + * TODO: To figure out what is the min. slack required here. See something + * strange in HDL simulation */ - float bl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.bl_word_size() + 2) / timescale; - float wl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.wl_word_size() + 2) / timescale; + float bl_sr_clock_period = 0.25 * prog_clock_period / + (fabric_bits_by_addr.bl_word_size() + 2) / + timescale; + float wl_sr_clock_period = 0.25 * prog_clock_period / + (fabric_bits_by_addr.wl_word_size() + 2) / + timescale; VTR_LOG("Precomputed clock frequency (=%g %s) for %s.\n", 1. / (2. * bl_sr_clock_period * timescale) / 1e6, @@ -432,55 +515,59 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(s time_unit_to_string(1e6, "Hz").c_str(), wl_sr_clock_port.get_name().c_str()); - if (CMD_EXEC_FATAL_ERROR == constrain_blwl_shift_register_clock_period_from_simulation_settings(sim_settings, - bl_sr_clock_port, - timescale, - bl_sr_clock_period)) { + if (CMD_EXEC_FATAL_ERROR == + constrain_blwl_shift_register_clock_period_from_simulation_settings( + sim_settings, bl_sr_clock_port, timescale, bl_sr_clock_period)) { return CMD_EXEC_FATAL_ERROR; } - if (CMD_EXEC_FATAL_ERROR == constrain_blwl_shift_register_clock_period_from_simulation_settings(sim_settings, - wl_sr_clock_port, - timescale, - wl_sr_clock_period)) { + if (CMD_EXEC_FATAL_ERROR == + constrain_blwl_shift_register_clock_period_from_simulation_settings( + sim_settings, wl_sr_clock_port, timescale, wl_sr_clock_period)) { return CMD_EXEC_FATAL_ERROR; } if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { - print_verilog_comment(fp, "----- BL Shift register virtual clock generator -----"); - print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator(fp, start_bl_sr_port, virtual_bl_sr_clock_port, bl_sr_clock_period); + print_verilog_comment( + fp, "----- BL Shift register virtual clock generator -----"); + print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator( + fp, start_bl_sr_port, virtual_bl_sr_clock_port, bl_sr_clock_period); - print_verilog_comment(fp, "----- BL Shift register clock generator -----"); - print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, start_bl_sr_port, bl_sr_clock_port, bl_sr_clock_period); + print_verilog_comment(fp, + "----- BL Shift register clock generator -----"); + print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator( + fp, start_bl_sr_port, bl_sr_clock_port, bl_sr_clock_period); } if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()) { - print_verilog_comment(fp, "----- WL Shift register virtual clock generator -----"); - print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator(fp, start_wl_sr_port, virtual_wl_sr_clock_port, wl_sr_clock_period); - print_verilog_comment(fp, "----- WL Shift register clock generator -----"); - print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, start_wl_sr_port, wl_sr_clock_port, wl_sr_clock_period); + print_verilog_comment( + fp, "----- WL Shift register virtual clock generator -----"); + print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator( + fp, start_wl_sr_port, virtual_wl_sr_clock_port, wl_sr_clock_period); + print_verilog_comment(fp, + "----- WL Shift register clock generator -----"); + print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator( + fp, start_wl_sr_port, wl_sr_clock_port, wl_sr_clock_period); } } return CMD_EXEC_SUCCESS; } -/* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */ -static -void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream& fp, - const std::string& bitstream_file, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricBitstream& fabric_bitstream) { +/* Verilog codes to load bitstream from a bit file for memory bank using flatten + * BL/WLs */ +static void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream( + std::fstream& fp, const std::string& bitstream_file, + const bool& fast_configuration, const bool& bit_value_to_skip, + const ModuleManager& module_manager, const ModuleId& top_module, + const FabricBitstream& fabric_bitstream) { /* Validate the file stream */ valid_file_stream(fp); /* Reorganize the fabric bitstream by the same address across regions */ - MemoryBankFlattenFabricBitstream fabric_bits_by_addr = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, - fast_configuration, - bit_value_to_skip); + MemoryBankFlattenFabricBitstream fabric_bits_by_addr = + build_memory_bank_flatten_fabric_bitstream( + fabric_bitstream, fast_configuration, bit_value_to_skip); /* Feed address and data input pair one by one * Note: the first cycle is reserved for programming reset @@ -488,15 +575,17 @@ void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream& */ std::vector bl_ports; for (const ConfigRegionId& region : module_manager.regions(top_module)) { - ModulePortId cur_bl_port_id = module_manager.find_module_port(top_module, - generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), region)); + ModulePortId cur_bl_port_id = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(MEMORY_BL_PORT_NAME), region)); bl_ports.push_back(module_manager.module_port(top_module, cur_bl_port_id)); } std::vector wl_ports; for (const ConfigRegionId& region : module_manager.regions(top_module)) { - ModulePortId cur_wl_port_id = module_manager.find_module_port(top_module, - generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), region)); + ModulePortId cur_wl_port_id = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(MEMORY_WL_PORT_NAME), region)); wl_ports.push_back(module_manager.module_port(top_module, cur_wl_port_id)); } @@ -514,21 +603,28 @@ void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream& std::vector initial_wl_values(wl_port_width, 0); /* Define a constant for the bitstream length */ - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), fabric_bits_by_addr.size()); - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), bl_port_width + wl_port_width); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), + fabric_bits_by_addr.size()); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), + bl_port_width + wl_port_width); /* Declare local variables for bitstream loading in Verilog */ - print_verilog_comment(fp, "----- Virtual memory to store the bitstream from external file -----"); + print_verilog_comment( + fp, "----- Virtual memory to store the bitstream from external file -----"); fp << "reg [0:`" << TOP_TB_BITSTREAM_WIDTH_VARIABLE << " - 1] "; - fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1];"; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" + << 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; + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " + << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; - print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); + print_verilog_comment( + fp, "----- Preload bitstream file to a virtual memory -----"); fp << "initial begin" << std::endl; fp << "\t"; - fp << "$readmemb(\"" << bitstream_file << "\", " << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; + fp << "$readmemb(\"" << bitstream_file << "\", " + << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; fp << std::endl; print_verilog_comment(fp, "----- Bit-Line Address port default input -----"); @@ -551,10 +647,14 @@ void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream& fp << "end"; fp << std::endl; - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1); + print_verilog_comment( + fp, "----- Begin bitstream loading during configuration phase -----"); + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + + std::string(TOP_TB_CLOCK_REG_POSTFIX), + 1); fp << "always"; - fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " @(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; fp << " begin"; fp << std::endl; @@ -569,7 +669,8 @@ void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream& 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 << generate_verilog_port_constant_values(config_done_port, + config_done_final_values, true); fp << ";" << std::endl; fp << "\t"; @@ -579,9 +680,10 @@ void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream& std::vector blwl_ports = bl_ports; blwl_ports.insert(blwl_ports.end(), wl_ports.begin(), wl_ports.end()); fp << "\t\t"; - fp << generate_verilog_ports(blwl_ports); + fp << generate_verilog_ports(blwl_ports); 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"; @@ -597,27 +699,26 @@ void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream& fp << "end"; fp << std::endl; - print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); + print_verilog_comment( + fp, "----- End bitstream loading during configuration phase -----"); } -/* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */ -static -void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::fstream& fp, - const std::string& bitstream_file, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricBitstream& fabric_bitstream, - const MemoryBankShiftRegisterBanks& blwl_sr_banks) { +/* Verilog codes to load bitstream from a bit file for memory bank using flatten + * BL/WLs */ +static void +print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream( + std::fstream& fp, const std::string& bitstream_file, + const bool& fast_configuration, const bool& bit_value_to_skip, + const ModuleManager& module_manager, const ModuleId& top_module, + const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks) { /* Validate the file stream */ valid_file_stream(fp); /* Reorganize the fabric bitstream by the same address across regions */ - MemoryBankShiftRegisterFabricBitstream fabric_bits_by_addr = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, - blwl_sr_banks, - fast_configuration, - bit_value_to_skip); + MemoryBankShiftRegisterFabricBitstream fabric_bits_by_addr = + build_memory_bank_shift_register_fabric_bitstream( + fabric_bitstream, blwl_sr_banks, fast_configuration, bit_value_to_skip); /* Feed address and data input pair one by one * Note: the first cycle is reserved for programming reset @@ -625,16 +726,20 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f */ std::vector bl_head_ports; for (const ConfigRegionId& region : module_manager.regions(top_module)) { - ModulePortId cur_bl_head_port_id = module_manager.find_module_port(top_module, - generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), region)); - bl_head_ports.push_back(module_manager.module_port(top_module, cur_bl_head_port_id)); + ModulePortId cur_bl_head_port_id = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), region)); + bl_head_ports.push_back( + module_manager.module_port(top_module, cur_bl_head_port_id)); } std::vector wl_head_ports; for (const ConfigRegionId& region : module_manager.regions(top_module)) { - ModulePortId cur_wl_head_port_id = module_manager.find_module_port(top_module, - generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), region)); - wl_head_ports.push_back(module_manager.module_port(top_module, cur_wl_head_port_id)); + ModulePortId cur_wl_head_port_id = module_manager.find_module_port( + top_module, generate_regional_blwl_port_name( + std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), region)); + wl_head_ports.push_back( + module_manager.module_port(top_module, cur_wl_head_port_id)); } /* Calculate the total size of BL/WL ports */ @@ -642,50 +747,67 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f for (const BasicPort& bl_head_port : bl_head_ports) { bl_head_port_width += bl_head_port.get_width(); } - VTR_ASSERT(bl_head_port_width == fabric_bits_by_addr.bl_width()); + VTR_ASSERT(bl_head_port_width == fabric_bits_by_addr.bl_width()); size_t wl_head_port_width = 0; for (const BasicPort& wl_head_port : wl_head_ports) { wl_head_port_width += wl_head_port.get_width(); } - VTR_ASSERT(wl_head_port_width == fabric_bits_by_addr.wl_width()); + VTR_ASSERT(wl_head_port_width == fabric_bits_by_addr.wl_width()); std::vector initial_bl_head_values(bl_head_port_width, 0); std::vector initial_wl_head_values(wl_head_port_width, 0); /* Define a constant for the bitstream length */ - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), fabric_bits_by_addr.num_words()); - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), std::max(bl_head_port_width, wl_head_port_width)); - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_BL_HEAD_WIDTH_VARIABLE), bl_head_port_width); - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WL_HEAD_WIDTH_VARIABLE), wl_head_port_width); - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE), fabric_bits_by_addr.bl_word_size()); - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE), fabric_bits_by_addr.wl_word_size()); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), + fabric_bits_by_addr.num_words()); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), + std::max(bl_head_port_width, wl_head_port_width)); + print_verilog_define_flag( + fp, std::string(TOP_TB_BITSTREAM_BL_HEAD_WIDTH_VARIABLE), + bl_head_port_width); + print_verilog_define_flag( + fp, std::string(TOP_TB_BITSTREAM_WL_HEAD_WIDTH_VARIABLE), + wl_head_port_width); + print_verilog_define_flag(fp, + std::string(TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE), + fabric_bits_by_addr.bl_word_size()); + print_verilog_define_flag(fp, + std::string(TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE), + fabric_bits_by_addr.wl_word_size()); /* Declare local variables for bitstream loading in Verilog */ - print_verilog_comment(fp, "----- Virtual memory to store the bitstream from external file -----"); + print_verilog_comment( + fp, "----- Virtual memory to store the bitstream from external file -----"); fp << "reg [0:`" << TOP_TB_BITSTREAM_WIDTH_VARIABLE << " - 1] "; fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`"; - fp << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "*(`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE; - fp << " + `"<< TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << ") - 1];"; + fp << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "*(`" + << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE; + fp << " + `" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << ") - 1];"; fp << std::endl; - fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " + << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; - print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); + print_verilog_comment( + fp, "----- Preload bitstream file to a virtual memory -----"); fp << "initial begin" << std::endl; fp << "\t"; - fp << "$readmemb(\"" << bitstream_file << "\", " << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; + fp << "$readmemb(\"" << bitstream_file << "\", " + << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; fp << std::endl; print_verilog_comment(fp, "----- Bit-Line head port default input -----"); fp << "\t"; - fp << generate_verilog_ports_constant_values(bl_head_ports, initial_bl_head_values); + fp << generate_verilog_ports_constant_values(bl_head_ports, + initial_bl_head_values); fp << ";"; fp << std::endl; print_verilog_comment(fp, "----- Word-Line head port default input -----"); fp << "\t"; - fp << generate_verilog_ports_constant_values(wl_head_ports, initial_wl_head_values); + fp << generate_verilog_ports_constant_values(wl_head_ports, + initial_wl_head_values); fp << ";"; fp << std::endl; @@ -698,12 +820,16 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f BasicPort start_wl_sr_port(TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME, 1); fp << "\t"; - fp << generate_verilog_port_constant_values(start_bl_sr_port, std::vector(start_bl_sr_port.get_width(), 0), true); + fp << generate_verilog_port_constant_values( + start_bl_sr_port, std::vector(start_bl_sr_port.get_width(), 0), + true); fp << ";"; fp << std::endl; fp << "\t"; - fp << generate_verilog_port_constant_values(start_wl_sr_port, std::vector(start_wl_sr_port.get_width(), 0), true); + fp << generate_verilog_port_constant_values( + start_wl_sr_port, std::vector(start_wl_sr_port.get_width(), 0), + true); fp << ";"; fp << std::endl; @@ -711,40 +837,55 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f BasicPort wl_sr_clock_port(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); fp << "\t"; - fp << generate_verilog_port_constant_values(bl_sr_clock_port, std::vector(bl_sr_clock_port.get_width(), 0), true); + fp << generate_verilog_port_constant_values( + bl_sr_clock_port, std::vector(bl_sr_clock_port.get_width(), 0), + true); fp << ";"; fp << std::endl; fp << "\t"; - fp << generate_verilog_port_constant_values(wl_sr_clock_port, std::vector(wl_sr_clock_port.get_width(), 0), true); + fp << generate_verilog_port_constant_values( + wl_sr_clock_port, std::vector(wl_sr_clock_port.get_width(), 0), + true); fp << ";"; fp << std::endl; - BasicPort virtual_bl_sr_clock_port(TOP_TB_VIRTUAL_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); - BasicPort virtual_wl_sr_clock_port(TOP_TB_VIRTUAL_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); + BasicPort virtual_bl_sr_clock_port( + TOP_TB_VIRTUAL_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); + BasicPort virtual_wl_sr_clock_port( + TOP_TB_VIRTUAL_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); fp << "\t"; - fp << generate_verilog_port_constant_values(virtual_bl_sr_clock_port, std::vector(virtual_bl_sr_clock_port.get_width(), 0), true); + fp << generate_verilog_port_constant_values( + virtual_bl_sr_clock_port, + std::vector(virtual_bl_sr_clock_port.get_width(), 0), true); fp << ";"; fp << std::endl; fp << "\t"; - fp << generate_verilog_port_constant_values(virtual_wl_sr_clock_port, std::vector(virtual_wl_sr_clock_port.get_width(), 0), true); + fp << generate_verilog_port_constant_values( + virtual_wl_sr_clock_port, + std::vector(virtual_wl_sr_clock_port.get_width(), 0), true); fp << ";"; 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), 1); + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + + std::string(TOP_TB_CLOCK_REG_POSTFIX), + 1); - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); + print_verilog_comment( + fp, "----- Begin bitstream loading during configuration phase -----"); fp << "always"; - fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " @(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; fp << " begin"; fp << std::endl; - /* Finished all the configuration words, raise the configuration done signal */ + /* Finished all the configuration words, raise the configuration done signal + */ fp << "\t"; fp << "if ("; fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; @@ -756,21 +897,27 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f 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 << generate_verilog_port_constant_values(config_done_port, + config_done_final_values, true); fp << ";" << std::endl; fp << "\t"; fp << "end else begin"; fp << std::endl; - /* When there are still configuration words to be load, start the BL and WL shift register clock */ + /* When there are still configuration words to be load, start the BL and WL + * shift register clock */ fp << "\t\t"; - fp << generate_verilog_port_constant_values(start_bl_sr_port, std::vector(start_bl_sr_port.get_width(), 1), true); + fp << generate_verilog_port_constant_values( + start_bl_sr_port, std::vector(start_bl_sr_port.get_width(), 1), + true); fp << ";"; fp << std::endl; fp << "\t\t"; - fp << generate_verilog_port_constant_values(start_wl_sr_port, std::vector(start_wl_sr_port.get_width(), 1), true); + fp << generate_verilog_port_constant_values( + start_wl_sr_port, std::vector(start_wl_sr_port.get_width(), 1), + true); fp << ";"; fp << std::endl; @@ -797,7 +944,9 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f /* Load data to BL shift register chains */ fp << "always"; - fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, virtual_bl_sr_clock_port) << ")"; + fp << " @(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, virtual_bl_sr_clock_port) + << ")"; fp << " begin"; fp << std::endl; @@ -810,13 +959,14 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << std::endl; fp << "\t\t"; - fp << generate_verilog_port_constant_values(start_bl_sr_port, std::vector(start_bl_sr_port.get_width(), 0), true); + fp << generate_verilog_port_constant_values( + start_bl_sr_port, std::vector(start_bl_sr_port.get_width(), 0), + true); fp << ";" << std::endl; fp << "\t"; fp << "end" << std::endl; - fp << "\t"; fp << "if ("; fp << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME; @@ -833,10 +983,13 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << "end else begin" << std::endl; fp << "\t\t"; - fp << generate_verilog_ports(bl_head_ports); + fp << generate_verilog_ports(bl_head_ports); fp << " <= "; fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[("; - fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << "-1)*(`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " + `" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << ") + " << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << "-1)*(`" + << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " + `" + << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << ") + " + << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME; fp << "];" << std::endl; fp << "\t\t"; @@ -853,7 +1006,9 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f /* Load data to WL shift register chains */ fp << "always"; - fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, virtual_wl_sr_clock_port) << ")"; + fp << " @(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, virtual_wl_sr_clock_port) + << ")"; fp << " begin"; fp << std::endl; @@ -866,7 +1021,9 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << std::endl; fp << "\t\t"; - fp << generate_verilog_port_constant_values(start_wl_sr_port, std::vector(start_wl_sr_port.get_width(), 0), true); + fp << generate_verilog_port_constant_values( + start_wl_sr_port, std::vector(start_wl_sr_port.get_width(), 0), + true); fp << ";" << std::endl; fp << "\t"; @@ -888,10 +1045,14 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << "end else begin" << std::endl; fp << "\t\t"; - fp << generate_verilog_ports(wl_head_ports); + fp << generate_verilog_ports(wl_head_ports); fp << " <= "; fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[("; - fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << "-1)*(`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " + `" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << ") + `" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " + " << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << "-1)*(`" + << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " + `" + << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << ") + `" + << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " + " + << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME; fp << "];" << std::endl; fp << "\t\t"; @@ -906,29 +1067,31 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << "end"; fp << std::endl; - print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); + print_verilog_comment( + fp, "----- End bitstream loading during configuration phase -----"); } - -/* Verilog codes to load bitstream from a bit file for memory bank using BL/WL decoders */ -static -void print_verilog_full_testbench_ql_memory_bank_decoder_bitstream(std::fstream& fp, - const std::string& bitstream_file, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricBitstream& fabric_bitstream) { +/* Verilog codes to load bitstream from a bit file for memory bank using BL/WL + * decoders */ +static void print_verilog_full_testbench_ql_memory_bank_decoder_bitstream( + std::fstream& fp, const std::string& bitstream_file, + const bool& fast_configuration, const bool& bit_value_to_skip, + const ModuleManager& module_manager, const ModuleId& top_module, + const FabricBitstream& fabric_bitstream) { /* Validate the file stream */ valid_file_stream(fp); /* Reorganize the fabric bitstream by the same address across regions */ - MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); + MemoryBankFabricBitstream fabric_bits_by_addr = + build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); /* For fast configuration, identify the final bitstream size to be used */ size_t num_bits_to_skip = 0; if (true == fast_configuration) { - num_bits_to_skip = fabric_bits_by_addr.size() - find_memory_bank_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); + num_bits_to_skip = + fabric_bits_by_addr.size() - + find_memory_bank_fast_configuration_fabric_bitstream_size( + fabric_bitstream, bit_value_to_skip); } VTR_ASSERT(num_bits_to_skip < fabric_bits_by_addr.size()); @@ -936,48 +1099,60 @@ void print_verilog_full_testbench_ql_memory_bank_decoder_bitstream(std::fstream& * Note: the first cycle is reserved for programming reset * We should give dummy values */ - ModulePortId bl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_BL_ADDRESS_PORT_NAME)); - BasicPort bl_addr_port = module_manager.module_port(top_module, bl_addr_port_id); + ModulePortId bl_addr_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); + BasicPort bl_addr_port = + module_manager.module_port(top_module, bl_addr_port_id); std::vector initial_bl_addr_values(bl_addr_port.get_width(), 0); - ModulePortId wl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_WL_ADDRESS_PORT_NAME)); - BasicPort wl_addr_port = module_manager.module_port(top_module, wl_addr_port_id); + ModulePortId wl_addr_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); + BasicPort wl_addr_port = + module_manager.module_port(top_module, wl_addr_port_id); std::vector initial_wl_addr_values(wl_addr_port.get_width(), 0); - ModulePortId din_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_DATA_IN_PORT_NAME)); + ModulePortId din_port_id = module_manager.find_module_port( + top_module, std::string(DECODER_DATA_IN_PORT_NAME)); BasicPort din_port = module_manager.module_port(top_module, din_port_id); std::vector initial_din_values(din_port.get_width(), 0); /* Define a constant for the bitstream length */ - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), fabric_bits_by_addr.size() - num_bits_to_skip); - print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), bl_addr_port.get_width() + wl_addr_port.get_width() + din_port.get_width()); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), + fabric_bits_by_addr.size() - num_bits_to_skip); + print_verilog_define_flag( + fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), + bl_addr_port.get_width() + wl_addr_port.get_width() + din_port.get_width()); /* Declare local variables for bitstream loading in Verilog */ - print_verilog_comment(fp, "----- Virtual memory to store the bitstream from external file -----"); + print_verilog_comment( + fp, "----- Virtual memory to store the bitstream from external file -----"); fp << "reg [0:`" << TOP_TB_BITSTREAM_WIDTH_VARIABLE << " - 1] "; - fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1];"; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" + << 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; + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " + << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; - print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); + print_verilog_comment( + fp, "----- Preload bitstream file to a virtual memory -----"); fp << "initial begin" << std::endl; fp << "\t"; - fp << "$readmemb(\"" << bitstream_file << "\", " << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; + fp << "$readmemb(\"" << bitstream_file << "\", " + << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; fp << std::endl; print_verilog_comment(fp, "----- Bit-Line Address port default input -----"); fp << "\t"; - fp << generate_verilog_port_constant_values(bl_addr_port, initial_bl_addr_values); + fp << generate_verilog_port_constant_values(bl_addr_port, + initial_bl_addr_values); fp << ";"; fp << std::endl; print_verilog_comment(fp, "----- Word-Line Address port default input -----"); fp << "\t"; - fp << generate_verilog_port_constant_values(wl_addr_port, initial_wl_addr_values); + fp << generate_verilog_port_constant_values(wl_addr_port, + initial_wl_addr_values); fp << ";"; fp << std::endl; @@ -995,10 +1170,14 @@ void print_verilog_full_testbench_ql_memory_bank_decoder_bitstream(std::fstream& fp << "end"; fp << std::endl; - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1); + print_verilog_comment( + fp, "----- Begin bitstream loading during configuration phase -----"); + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + + std::string(TOP_TB_CLOCK_REG_POSTFIX), + 1); fp << "always"; - fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " @(negedge " + << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; fp << " begin"; fp << std::endl; @@ -1013,7 +1192,8 @@ void print_verilog_full_testbench_ql_memory_bank_decoder_bitstream(std::fstream& 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 << generate_verilog_port_constant_values(config_done_port, + config_done_final_values, true); fp << ";" << std::endl; fp << "\t"; @@ -1022,14 +1202,15 @@ void print_verilog_full_testbench_ql_memory_bank_decoder_bitstream(std::fstream& fp << "\t\t"; fp << "{"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, bl_addr_port); + fp << generate_verilog_port(VERILOG_PORT_CONKT, bl_addr_port); fp << ", "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, wl_addr_port); + fp << generate_verilog_port(VERILOG_PORT_CONKT, wl_addr_port); fp << ", "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port); + fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port); fp << "}"; 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"; @@ -1045,39 +1226,33 @@ void print_verilog_full_testbench_ql_memory_bank_decoder_bitstream(std::fstream& fp << "end"; fp << std::endl; - print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); + print_verilog_comment( + fp, "----- End bitstream loading during configuration phase -----"); } -void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp, - const std::string& bitstream_file, - const ConfigProtocol& config_protocol, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricBitstream& fabric_bitstream, - const MemoryBankShiftRegisterBanks& blwl_sr_banks) { - if ( (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) - && (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) ) { - print_verilog_full_testbench_ql_memory_bank_decoder_bitstream(fp, bitstream_file, - fast_configuration, - bit_value_to_skip, - module_manager, top_module, - fabric_bitstream); - } else if ( (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) - && (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) ) { - print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(fp, bitstream_file, - fast_configuration, - bit_value_to_skip, - module_manager, top_module, - fabric_bitstream); - } else if ( (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) - && (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()) ) { - print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(fp, bitstream_file, - fast_configuration, - bit_value_to_skip, - module_manager, top_module, - fabric_bitstream, blwl_sr_banks); +void print_verilog_full_testbench_ql_memory_bank_bitstream( + std::fstream& fp, const std::string& bitstream_file, + const ConfigProtocol& config_protocol, const bool& fast_configuration, + const bool& bit_value_to_skip, const ModuleManager& module_manager, + const ModuleId& top_module, const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks) { + if ((BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) && + (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type())) { + print_verilog_full_testbench_ql_memory_bank_decoder_bitstream( + fp, bitstream_file, fast_configuration, bit_value_to_skip, module_manager, + top_module, fabric_bitstream); + } else if ((BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) && + (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type())) { + print_verilog_full_testbench_ql_memory_bank_flatten_bitstream( + fp, bitstream_file, fast_configuration, bit_value_to_skip, module_manager, + top_module, fabric_bitstream); + } else if ((BLWL_PROTOCOL_SHIFT_REGISTER == + config_protocol.bl_protocol_type()) && + (BLWL_PROTOCOL_SHIFT_REGISTER == + config_protocol.wl_protocol_type())) { + print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream( + fp, bitstream_file, fast_configuration, bit_value_to_skip, module_manager, + top_module, fabric_bitstream, blwl_sr_banks); } } diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h index 6bcd50903..dc93b9873 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h @@ -6,19 +6,20 @@ *******************************************************************/ #include #include -#include "module_manager.h" + #include "bitstream_manager.h" -#include "fabric_bitstream.h" #include "circuit_library.h" #include "config_protocol.h" -#include "vpr_context.h" -#include "pin_constraints.h" -#include "io_location_map.h" +#include "fabric_bitstream.h" #include "fabric_global_port_info.h" -#include "vpr_netlist_annotation.h" -#include "simulation_setting.h" +#include "io_location_map.h" #include "memory_bank_shift_register_banks.h" +#include "module_manager.h" +#include "pin_constraints.h" +#include "simulation_setting.h" #include "verilog_testbench_options.h" +#include "vpr_context.h" +#include "vpr_netlist_annotation.h" /******************************************************************** * Function declaration @@ -30,47 +31,41 @@ namespace openfpga { /** * @brief Print local wires for memory bank configuration protocols */ -void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigProtocol& config_protocol); +void print_verilog_top_testbench_ql_memory_bank_port( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, const ConfigProtocol& config_protocol); /** - * @brief Generate the Verilog codes that connect shift register clock stimuli to FPGA ports + * @brief Generate the Verilog codes that connect shift register clock stimuli + * to FPGA ports */ -void print_verilog_top_testbench_global_shift_register_clock_ports_stimuli(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricGlobalPortInfo& fabric_global_port_info); +void print_verilog_top_testbench_global_shift_register_clock_ports_stimuli( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info); /** - * @brief Generate the Verilog codes that generate stimuli waveforms for BL/WL protocols + * @brief Generate the Verilog codes that generate stimuli waveforms for BL/WL + * protocols */ -int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp, - const ConfigProtocol& config_protocol, - const SimulationSetting& sim_settings, - const ModuleManager& module_manager, - const ModuleId& top_module, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const FabricBitstream& fabric_bitstream, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const float& prog_clock_period, - const float& timescale); +int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus( + std::fstream& fp, const ConfigProtocol& config_protocol, + const SimulationSetting& sim_settings, const ModuleManager& module_manager, + const ModuleId& top_module, const bool& fast_configuration, + const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const float& prog_clock_period, const float& timescale); /** - * @brief Print stimulus for a FPGA fabric with a memory bank configuration protocol - * where configuration bits are programming in serial (one by one) + * @brief Print stimulus for a FPGA fabric with a memory bank configuration + * protocol where configuration bits are programming in serial (one by one) */ -void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp, - const std::string& bitstream_file, - const ConfigProtocol& config_protocol, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricBitstream& fabric_bitstream, - const MemoryBankShiftRegisterBanks& blwl_sr_banks); +void print_verilog_full_testbench_ql_memory_bank_bitstream( + std::fstream& fp, const std::string& bitstream_file, + const ConfigProtocol& config_protocol, const bool& fast_configuration, + const bool& bit_value_to_skip, const ModuleManager& module_manager, + const ModuleId& top_module, const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_wire.cpp b/openfpga/src/fpga_verilog/verilog_wire.cpp index ec565b923..5df8bb840 100644 --- a/openfpga/src/fpga_verilog/verilog_wire.cpp +++ b/openfpga/src/fpga_verilog/verilog_wire.cpp @@ -2,25 +2,22 @@ * This file includes functions to generate * Verilog submodules for wires. **********************************************/ -#include #include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" #include "vtr_log.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - #include "module_manager.h" #include "module_manager_utils.h" - +#include "openfpga_digest.h" #include "openfpga_naming.h" - #include "verilog_constants.h" #include "verilog_submodule_utils.h" -#include "verilog_writer_utils.h" #include "verilog_wire.h" +#include "verilog_writer_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -34,55 +31,67 @@ namespace openfpga { * +------+ * *******************************************************************/ -static -void print_verilog_wire_module(const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - std::fstream& fp, - const CircuitModelId& wire_model, - const e_verilog_default_net_type& default_net_type) { +static void print_verilog_wire_module( + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + std::fstream& fp, const CircuitModelId& wire_model, + const e_verilog_default_net_type& default_net_type) { /* Ensure a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); /* Find the input port, output port*/ - std::vector input_ports = circuit_lib.model_ports_by_type(wire_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector output_ports = circuit_lib.model_ports_by_type(wire_model, CIRCUIT_MODEL_PORT_OUTPUT, true); - std::vector global_ports = circuit_lib.model_global_ports_by_type(wire_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector input_ports = + circuit_lib.model_ports_by_type(wire_model, CIRCUIT_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type( + wire_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + std::vector global_ports = + circuit_lib.model_global_ports_by_type(wire_model, CIRCUIT_MODEL_PORT_INPUT, + true, true); /* Makre sure the port size is what we want */ - VTR_ASSERT (1 == input_ports.size()); - VTR_ASSERT (1 == output_ports.size()); - VTR_ASSERT (1 == circuit_lib.port_size(input_ports[0])); - VTR_ASSERT (1 == circuit_lib.port_size(output_ports[0])); + VTR_ASSERT(1 == input_ports.size()); + VTR_ASSERT(1 == output_ports.size()); + VTR_ASSERT(1 == circuit_lib.port_size(input_ports[0])); + VTR_ASSERT(1 == circuit_lib.port_size(output_ports[0])); - /* Create a Verilog Module based on the circuit model, and add to module manager */ - ModuleId wire_module = module_manager.find_module(circuit_lib.model_name(wire_model)); + /* Create a Verilog Module based on the circuit model, and add to module + * manager */ + ModuleId wire_module = + module_manager.find_module(circuit_lib.model_name(wire_model)); VTR_ASSERT(true == module_manager.valid_module_id(wire_module)); /* dump module definition + ports */ - print_verilog_module_declaration(fp, module_manager, wire_module, default_net_type); + print_verilog_module_declaration(fp, module_manager, wire_module, + default_net_type); /* Finish dumping ports */ /* Print the internal logic of Verilog module */ /* Find the input port of the module */ - ModulePortId module_input_port_id = module_manager.find_module_port(wire_module, circuit_lib.port_lib_name(input_ports[0])); + ModulePortId module_input_port_id = module_manager.find_module_port( + wire_module, circuit_lib.port_lib_name(input_ports[0])); VTR_ASSERT(ModulePortId::INVALID() != module_input_port_id); - BasicPort module_input_port = module_manager.module_port(wire_module, module_input_port_id); + BasicPort module_input_port = + module_manager.module_port(wire_module, module_input_port_id); /* Find the output port of the module */ - ModulePortId module_output_port_id = module_manager.find_module_port(wire_module, circuit_lib.port_lib_name(output_ports[0])); + ModulePortId module_output_port_id = module_manager.find_module_port( + wire_module, circuit_lib.port_lib_name(output_ports[0])); VTR_ASSERT(ModulePortId::INVALID() != module_output_port_id); - BasicPort module_output_port = module_manager.module_port(wire_module, module_output_port_id); + BasicPort module_output_port = + module_manager.module_port(wire_module, module_output_port_id); /* Print wire declaration for the inputs and outputs */ - fp << generate_verilog_port(VERILOG_PORT_WIRE, module_input_port) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_WIRE, module_output_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_WIRE, module_input_port) << ";" + << std::endl; + fp << generate_verilog_port(VERILOG_PORT_WIRE, module_output_port) << ";" + << std::endl; /* Direct shortcut */ - print_verilog_wire_connection(fp, module_output_port, module_input_port, false); - + print_verilog_wire_connection(fp, module_output_port, module_input_port, + false); + /* Print timing info */ print_verilog_submodule_timing(fp, circuit_lib, wire_model); - + /* Put an end to the Verilog module */ print_verilog_module_end(fp, circuit_lib.model_name(wire_model)); @@ -108,22 +117,25 @@ void print_verilog_submodule_wires(const ModuleManager& module_manager, check_file_stream(verilog_fpath.c_str(), fp); - /* Print out debugging information for if the file is not opened/created properly */ - VTR_LOG("Writing Verilog netlist for wires '%s'...", - verilog_fpath.c_str()); + /* Print out debugging information for if the file is not opened/created + * properly */ + VTR_LOG("Writing Verilog netlist for wires '%s'...", verilog_fpath.c_str()); - print_verilog_file_header(fp, "Wires", options.time_stamp()); + print_verilog_file_header(fp, "Wires", options.time_stamp()); /* Print Verilog models for regular wires*/ - print_verilog_comment(fp, std::string("----- BEGIN Verilog modules for regular wires -----")); - for (const auto& model : circuit_lib.models_by_type(CIRCUIT_MODEL_WIRE)) { + print_verilog_comment( + fp, std::string("----- BEGIN Verilog modules for regular wires -----")); + for (const auto& model : circuit_lib.models_by_type(CIRCUIT_MODEL_WIRE)) { /* Bypass user-defined circuit models */ if (!circuit_lib.model_verilog_netlist(model).empty()) { continue; } - print_verilog_wire_module(module_manager, circuit_lib, fp, model, options.default_net_type()); + print_verilog_wire_module(module_manager, circuit_lib, fp, model, + options.default_net_type()); } - print_verilog_comment(fp, std::string("----- END Verilog modules for regular wires -----")); + print_verilog_comment( + fp, std::string("----- END Verilog modules for regular wires -----")); /* Close the file stream */ fp.close(); diff --git a/openfpga/src/fpga_verilog/verilog_wire.h b/openfpga/src/fpga_verilog/verilog_wire.h index 9f15faab5..69cbe7f24 100644 --- a/openfpga/src/fpga_verilog/verilog_wire.h +++ b/openfpga/src/fpga_verilog/verilog_wire.h @@ -8,10 +8,10 @@ #include #include "circuit_library.h" +#include "fabric_verilog_options.h" #include "module_manager.h" #include "netlist_manager.h" #include "verilog_port_types.h" -#include "fabric_verilog_options.h" /******************************************************************** * Function declaration diff --git a/openfpga/src/fpga_verilog/verilog_writer_utils.cpp b/openfpga/src/fpga_verilog/verilog_writer_utils.cpp index d537b89f3..abfc78adb 100644 --- a/openfpga/src/fpga_verilog/verilog_writer_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_writer_utils.cpp @@ -1,12 +1,12 @@ /************************************************ * Include functions for most frequently - * used Verilog writers + * used Verilog writers ***********************************************/ #include #include -#include #include #include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" @@ -16,10 +16,9 @@ #include "circuit_types.h" /* Headers from openfpgautil library */ -#include "openfpga_digest.h" - -#include "openfpga_naming.h" #include "circuit_library_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" #include "verilog_constants.h" #include "verilog_writer_utils.h" @@ -29,24 +28,24 @@ namespace openfpga { /************************************************ * Generate the declaration for default net type ***********************************************/ -void print_verilog_default_net_type_declaration(std::fstream& fp, - const e_verilog_default_net_type& default_net_type) { +void print_verilog_default_net_type_declaration( + std::fstream& fp, const e_verilog_default_net_type& default_net_type) { VTR_ASSERT(true == valid_file_stream(fp)); fp << "//----- Default net type -----" << std::endl; - fp << "`default_nettype " << VERILOG_DEFAULT_NET_TYPE_STRING[default_net_type] << std::endl; + fp << "`default_nettype " << VERILOG_DEFAULT_NET_TYPE_STRING[default_net_type] + << std::endl; fp << std::endl; } /************************************************ * Generate header comments for a Verilog netlist - * include the description + * include the description ***********************************************/ -void print_verilog_file_header(std::fstream& fp, - const std::string& usage, +void print_verilog_file_header(std::fstream& fp, const std::string& usage, const bool& include_time_stamp) { VTR_ASSERT(true == valid_file_stream(fp)); - + fp << "//-------------------------------------------" << std::endl; fp << "//\tFPGA Synthesizable Verilog Netlist" << std::endl; fp << "//\tDescription: " << usage << std::endl; @@ -54,9 +53,9 @@ void print_verilog_file_header(std::fstream& fp, fp << "//\tOrganization: University of Utah" << std::endl; if (include_time_stamp) { - auto end = std::chrono::system_clock::now(); + auto end = std::chrono::system_clock::now(); std::time_t end_time = std::chrono::system_clock::to_time_t(end); - fp << "//\tDate: " << std::ctime(&end_time) ; + fp << "//\tDate: " << std::ctime(&end_time); } fp << "//-------------------------------------------" << std::endl; @@ -67,44 +66,41 @@ void print_verilog_file_header(std::fstream& fp, } /******************************************************************** - * Print Verilog codes to include a netlist + * Print Verilog codes to include a netlist *******************************************************************/ -void print_verilog_include_netlist(std::fstream& fp, +void print_verilog_include_netlist(std::fstream& fp, const std::string& netlist_name) { VTR_ASSERT(true == valid_file_stream(fp)); - fp << "`include \"" << netlist_name << "\"" << std::endl; + fp << "`include \"" << netlist_name << "\"" << std::endl; } /******************************************************************** * Print Verilog codes to define a preprocessing flag *******************************************************************/ -void print_verilog_define_flag(std::fstream& fp, - const std::string& flag_name, +void print_verilog_define_flag(std::fstream& fp, const std::string& flag_name, const int& flag_value) { VTR_ASSERT(true == valid_file_stream(fp)); - fp << "`define " << flag_name << " " << flag_value << std::endl; + fp << "`define " << flag_name << " " << flag_value << std::endl; } /************************************************ * Generate include files for a Verilog netlist ***********************************************/ -void print_verilog_include_defines_preproc_file(std::fstream& fp, - const std::string& verilog_dir) { - +void print_verilog_include_defines_preproc_file( + std::fstream& fp, const std::string& verilog_dir) { /* Generate the file name */ std::string include_file_path = format_dir_path(verilog_dir); include_file_path += std::string(DEFINES_VERILOG_FILE_NAME); - print_verilog_include_netlist(fp, include_file_path); + print_verilog_include_netlist(fp, include_file_path); } /************************************************ * Print a Verilog comment line ***********************************************/ -void print_verilog_comment(std::fstream& fp, - const std::string& comment) { +void print_verilog_comment(std::fstream& fp, const std::string& comment) { VTR_ASSERT(true == valid_file_stream(fp)); fp << "// " << comment << std::endl; @@ -134,17 +130,22 @@ void print_verilog_endif(std::fstream& fp) { * We use the following format: * module (); ***********************************************/ -void print_verilog_module_definition(std::fstream& fp, - const ModuleManager& module_manager, const ModuleId& module_id) { +void print_verilog_module_definition(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& module_id) { VTR_ASSERT(true == valid_file_stream(fp)); - print_verilog_comment(fp, std::string("----- Verilog module for " + module_manager.module_name(module_id) + " -----")); + print_verilog_comment( + fp, std::string("----- Verilog module for " + + module_manager.module_name(module_id) + " -----")); - std::string module_head_line = "module " + module_manager.module_name(module_id) + "("; + std::string module_head_line = + "module " + module_manager.module_name(module_id) + "("; fp << module_head_line; /* port type2type mapping */ - std::map port_type2type_map; + std::map + port_type2type_map; port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_CONKT; port_type2type_map[ModuleManager::MODULE_GPIN_PORT] = VERILOG_PORT_CONKT; port_type2type_map[ModuleManager::MODULE_GPOUT_PORT] = VERILOG_PORT_CONKT; @@ -156,12 +157,14 @@ void print_verilog_module_definition(std::fstream& fp, /* Port sequence: global, inout, input, output and clock ports, */ size_t port_cnt = 0; - bool printed_ifdef = false; /* A flag to tell if an ifdef has been printed for the last port */ + bool printed_ifdef = + false; /* A flag to tell if an ifdef has been printed for the last port */ for (const auto& kv : port_type2type_map) { - for (const auto& port : module_manager.module_ports_by_type(module_id, kv.first)) { + for (const auto& port : + module_manager.module_ports_by_type(module_id, kv.first)) { if (0 != port_cnt) { /* Do not dump a comma for the first port */ - fp << "," << std::endl; + fp << "," << std::endl; } if (true == printed_ifdef) { @@ -171,10 +174,12 @@ void print_verilog_module_definition(std::fstream& fp, printed_ifdef = false; } - ModulePortId port_id = module_manager.find_module_port(module_id, port.get_name()); + ModulePortId port_id = + module_manager.find_module_port(module_id, port.get_name()); VTR_ASSERT(ModulePortId::INVALID() != port_id); /* Print pre-processing flag for a port, if defined */ - std::string preproc_flag = module_manager.port_preproc_flag(module_id, port_id); + std::string preproc_flag = + module_manager.port_preproc_flag(module_id, port_id); if (false == preproc_flag.empty()) { /* Print an ifdef Verilog syntax */ print_verilog_preprocessing_flag(fp, preproc_flag); @@ -198,16 +203,17 @@ void print_verilog_module_definition(std::fstream& fp, } /************************************************ - * Print a Verilog module ports based on the module id + * Print a Verilog module ports based on the module id ***********************************************/ -void print_verilog_module_ports(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const e_verilog_default_net_type& default_net_type) { +void print_verilog_module_ports( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, + const e_verilog_default_net_type& default_net_type) { VTR_ASSERT(true == valid_file_stream(fp)); /* port type2type mapping */ - std::map port_type2type_map; + std::map + port_type2type_map; port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_INPUT; port_type2type_map[ModuleManager::MODULE_GPIN_PORT] = VERILOG_PORT_INPUT; port_type2type_map[ModuleManager::MODULE_GPOUT_PORT] = VERILOG_PORT_OUTPUT; @@ -219,18 +225,22 @@ void print_verilog_module_ports(std::fstream& fp, /* Port sequence: global, inout, input, output and clock ports, */ for (const auto& kv : port_type2type_map) { - for (const auto& port : module_manager.module_ports_by_type(module_id, kv.first)) { - ModulePortId port_id = module_manager.find_module_port(module_id, port.get_name()); + for (const auto& port : + module_manager.module_ports_by_type(module_id, kv.first)) { + ModulePortId port_id = + module_manager.find_module_port(module_id, port.get_name()); VTR_ASSERT(ModulePortId::INVALID() != port_id); /* Print pre-processing flag for a port, if defined */ - std::string preproc_flag = module_manager.port_preproc_flag(module_id, port_id); + std::string preproc_flag = + module_manager.port_preproc_flag(module_id, port_id); if (false == preproc_flag.empty()) { /* Print an ifdef Verilog syntax */ print_verilog_preprocessing_flag(fp, preproc_flag); } /* Print port */ - fp << "//----- " << module_manager.module_port_type_str(kv.first) << " -----" << std::endl; + fp << "//----- " << module_manager.module_port_type_str(kv.first) + << " -----" << std::endl; fp << generate_verilog_port(kv.second, port); fp << ";" << std::endl; @@ -241,21 +251,25 @@ void print_verilog_module_ports(std::fstream& fp, } } - /* Output any port that is also wire connection when default net type is not wire! */ + /* Output any port that is also wire connection when default net type is not + * wire! */ if (VERILOG_DEFAULT_NET_TYPE_WIRE != default_net_type) { fp << std::endl; - fp << "//----- BEGIN wire-connection ports -----" << std::endl; + fp << "//----- BEGIN wire-connection ports -----" << std::endl; for (const auto& kv : port_type2type_map) { - for (const auto& port : module_manager.module_ports_by_type(module_id, kv.first)) { + for (const auto& port : + module_manager.module_ports_by_type(module_id, kv.first)) { /* Skip the ports that are not registered */ - ModulePortId port_id = module_manager.find_module_port(module_id, port.get_name()); + ModulePortId port_id = + module_manager.find_module_port(module_id, port.get_name()); VTR_ASSERT(ModulePortId::INVALID() != port_id); if (false == module_manager.port_is_wire(module_id, port_id)) { continue; } /* Print pre-processing flag for a port, if defined */ - std::string preproc_flag = module_manager.port_preproc_flag(module_id, port_id); + std::string preproc_flag = + module_manager.port_preproc_flag(module_id, port_id); if (false == preproc_flag.empty()) { /* Print an ifdef Verilog syntax */ print_verilog_preprocessing_flag(fp, preproc_flag); @@ -271,24 +285,27 @@ void print_verilog_module_ports(std::fstream& fp, } } } - fp << "//----- END wire-connection ports -----" << std::endl; + fp << "//----- END wire-connection ports -----" << std::endl; fp << std::endl; } - + /* Output any port that is registered */ fp << std::endl; - fp << "//----- BEGIN Registered ports -----" << std::endl; + fp << "//----- BEGIN Registered ports -----" << std::endl; for (const auto& kv : port_type2type_map) { - for (const auto& port : module_manager.module_ports_by_type(module_id, kv.first)) { + for (const auto& port : + module_manager.module_ports_by_type(module_id, kv.first)) { /* Skip the ports that are not registered */ - ModulePortId port_id = module_manager.find_module_port(module_id, port.get_name()); + ModulePortId port_id = + module_manager.find_module_port(module_id, port.get_name()); VTR_ASSERT(ModulePortId::INVALID() != port_id); if (false == module_manager.port_is_register(module_id, port_id)) { continue; } /* Print pre-processing flag for a port, if defined */ - std::string preproc_flag = module_manager.port_preproc_flag(module_id, port_id); + std::string preproc_flag = + module_manager.port_preproc_flag(module_id, port_id); if (false == preproc_flag.empty()) { /* Print an ifdef Verilog syntax */ print_verilog_preprocessing_flag(fp, preproc_flag); @@ -304,7 +321,7 @@ void print_verilog_module_ports(std::fstream& fp, } } } - fp << "//----- END Registered ports -----" << std::endl; + fp << "//----- END Registered ports -----" << std::endl; fp << std::endl; } @@ -312,56 +329,54 @@ void print_verilog_module_ports(std::fstream& fp, * Print a Verilog module declaration (definition + port list * We use the following format: * module (); - * + * ***********************************************/ -void print_verilog_module_declaration(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const e_verilog_default_net_type& default_net_type) { +void print_verilog_module_declaration( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, + const e_verilog_default_net_type& default_net_type) { VTR_ASSERT(true == valid_file_stream(fp)); /* Apply default net type from user's option */ - print_verilog_default_net_type_declaration(fp, - default_net_type); + print_verilog_default_net_type_declaration(fp, default_net_type); print_verilog_module_definition(fp, module_manager, module_id); print_verilog_module_ports(fp, module_manager, module_id, default_net_type); } - /******************************************************************** * Print an instance in Verilog format (a generic version) * This function will require user to provide an instance name * - * This function will output the port map by referring to a port-to-port + * This function will output the port map by referring to a port-to-port * mapping: * -> - * The key of the port-to-port mapping is the port name of the module: + * The key of the port-to-port mapping is the port name of the module: * The value of the port-to-port mapping is the port information of the instance - * With link between module and instance, the function can output a Verilog + * With link between module and instance, the function can output a Verilog * instance easily, supporting both explicit port mapping: * .() * and inexplicit port mapping * * - * Note that, it is not necessary that the port-to-port mapping + * Note that, it is not necessary that the port-to-port mapping * covers all the module ports. - * Any instance/module port which are not specified in the port-to-port + * Any instance/module port which are not specified in the port-to-port * mapping will be output by the module port name. *******************************************************************/ -void print_verilog_module_instance(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const std::string& instance_name, - const std::map& port2port_name_map, - const bool& use_explicit_port_map) { - +void print_verilog_module_instance( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const std::string& instance_name, + const std::map& port2port_name_map, + const bool& use_explicit_port_map) { VTR_ASSERT(true == valid_file_stream(fp)); - /* Check: all the key ports in the port2port_name_map does exist in the child module */ + /* Check: all the key ports in the port2port_name_map does exist in the child + * module */ for (const auto& kv : port2port_name_map) { - ModulePortId module_port_id = module_manager.find_module_port(module_id, kv.first); + ModulePortId module_port_id = + module_manager.find_module_port(module_id, kv.first); VTR_ASSERT(ModulePortId::INVALID() != module_port_id); } @@ -369,10 +384,11 @@ void print_verilog_module_instance(std::fstream& fp, fp << "\t" << module_manager.module_name(module_id) << " "; /* Print instance name */ fp << instance_name << " (" << std::endl; - + /* Print each port with/without explicit port map */ /* port type2type mapping */ - std::map port_type2type_map; + std::map + port_type2type_map; port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_CONKT; port_type2type_map[ModuleManager::MODULE_GPIN_PORT] = VERILOG_PORT_CONKT; port_type2type_map[ModuleManager::MODULE_GPOUT_PORT] = VERILOG_PORT_CONKT; @@ -385,10 +401,11 @@ void print_verilog_module_instance(std::fstream& fp, /* Port sequence: global, inout, input, output and clock ports, */ size_t port_cnt = 0; for (const auto& kv : port_type2type_map) { - for (const auto& port : module_manager.module_ports_by_type(module_id, kv.first)) { + for (const auto& port : + module_manager.module_ports_by_type(module_id, kv.first)) { if (0 != port_cnt) { /* Do not dump a comma for the first port */ - fp << "," << std::endl; + fp << "," << std::endl; } /* Print port */ fp << "\t\t"; @@ -397,14 +414,19 @@ void print_verilog_module_instance(std::fstream& fp, fp << "." << port.get_name() << "("; } /* Try to find the instanced port name in the name map */ - if (port2port_name_map.find(port.get_name()) != port2port_name_map.end()) { - /* Found it, we assign the port name */ + if (port2port_name_map.find(port.get_name()) != + port2port_name_map.end()) { + /* Found it, we assign the port name */ /* TODO: make sure the port width matches! */ - ModulePortId module_port_id = module_manager.find_module_port(module_id, port.get_name()); + ModulePortId module_port_id = + module_manager.find_module_port(module_id, port.get_name()); /* Get the port from module */ - BasicPort module_port = module_manager.module_port(module_id, module_port_id); - VTR_ASSERT(module_port.get_width() == port2port_name_map.at(port.get_name()).get_width()); - fp << generate_verilog_port(kv.second, port2port_name_map.at(port.get_name())); + BasicPort module_port = + module_manager.module_port(module_id, module_port_id); + VTR_ASSERT(module_port.get_width() == + port2port_name_map.at(port.get_name()).get_width()); + fp << generate_verilog_port(kv.second, + port2port_name_map.at(port.get_name())); } else { /* Not found, we give the default port name */ fp << generate_verilog_port(kv.second, port); @@ -416,58 +438,58 @@ void print_verilog_module_instance(std::fstream& fp, port_cnt++; } } - + /* Print an end to the instance */ fp << ");" << std::endl; } - /************************************************ * Print an instance for a Verilog module * This function is a wrapper for the generic version of - * print_verilog_module_instance() + * print_verilog_module_instance() * This function create an instance name based on the index * of the child module in its parent module ***********************************************/ -void print_verilog_module_instance(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& parent_module_id, const ModuleId& child_module_id, - const std::map& port2port_name_map, - const bool& use_explicit_port_map) { - +void print_verilog_module_instance( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& parent_module_id, const ModuleId& child_module_id, + const std::map& port2port_name_map, + const bool& use_explicit_port_map) { /* Create instance name, _ */ - std::string instance_name = module_manager.module_name(child_module_id) - + "_" - + std::to_string(module_manager.num_instance(parent_module_id, child_module_id)) - + "_"; + std::string instance_name = module_manager.module_name(child_module_id) + + "_" + + std::to_string(module_manager.num_instance( + parent_module_id, child_module_id)) + + "_"; - print_verilog_module_instance(fp, module_manager, child_module_id, instance_name, - port2port_name_map, use_explicit_port_map); + print_verilog_module_instance(fp, module_manager, child_module_id, + instance_name, port2port_name_map, + use_explicit_port_map); } /************************************************ * Print an end line for a Verilog module ***********************************************/ -void print_verilog_module_end(std::fstream& fp, +void print_verilog_module_end(std::fstream& fp, const std::string& module_name) { VTR_ASSERT(true == valid_file_stream(fp)); fp << "endmodule" << std::endl; - print_verilog_comment(fp, std::string("----- END Verilog module for " + module_name + " -----")); + print_verilog_comment( + fp, std::string("----- END Verilog module for " + module_name + " -----")); fp << std::endl; /* Reset default net type to be none */ - print_verilog_default_net_type_declaration(fp, - VERILOG_DEFAULT_NET_TYPE_NONE); + print_verilog_default_net_type_declaration(fp, VERILOG_DEFAULT_NET_TYPE_NONE); } /************************************************ - * Generate a string of a Verilog port + * Generate a string of a Verilog port ***********************************************/ -std::string generate_verilog_port(const enum e_dump_verilog_port_type& verilog_port_type, - const BasicPort& port_info, - const bool& must_print_port_size, - const bool& big_endian) { +std::string generate_verilog_port( + const enum e_dump_verilog_port_type& verilog_port_type, + const BasicPort& port_info, const bool& must_print_port_size, + const bool& big_endian) { std::string verilog_line; /* Ensure the port type is valid */ @@ -475,36 +497,36 @@ std::string generate_verilog_port(const enum e_dump_verilog_port_type& verilog_p std::string size_str; if (big_endian) { - size_str = "[" + std::to_string(port_info.get_lsb()) + ":" + std::to_string(port_info.get_msb()) + "]"; + size_str = "[" + std::to_string(port_info.get_lsb()) + ":" + + std::to_string(port_info.get_msb()) + "]"; } else { - size_str = "[" + std::to_string(port_info.get_msb()) + ":" + std::to_string(port_info.get_lsb()) + "]"; + size_str = "[" + std::to_string(port_info.get_msb()) + ":" + + std::to_string(port_info.get_lsb()) + "]"; } /* Only connection require a format of [:] - * others require a format of [:] + * others require a format of [:] */ if (VERILOG_PORT_CONKT == verilog_port_type) { /* Simplication: - * - When LSB == MSB == 0, we do not need to specify size when the user option allows - * Note that user option is essential, otherwise what could happen is that - * a multi-bit verilog port used in instance port mapping is printed as a single-bit net - * For example, - * input [1:0] in; - * inv inv_inst (.A(in), .Y(out)); - * The original port width is the reference to backtrace the defintion of the port + * - When LSB == MSB == 0, we do not need to specify size when the user + * option allows Note that user option is essential, otherwise what could + * happen is that a multi-bit verilog port used in instance port mapping is + * printed as a single-bit net For example, input [1:0] in; inv inv_inst + * (.A(in), .Y(out)); The original port width is the reference to backtrace + * the defintion of the port * - When LSB == MSB, we can use a simplified format [] */ - if ((false == must_print_port_size) - && (1 == port_info.get_width()) - && (0 == port_info.get_lsb()) - && (1 == port_info.get_origin_port_width())) { + if ((false == must_print_port_size) && (1 == port_info.get_width()) && + (0 == port_info.get_lsb()) && + (1 == port_info.get_origin_port_width())) { size_str.clear(); } else if ((1 == port_info.get_width())) { size_str = "[" + std::to_string(port_info.get_lsb()) + "]"; } verilog_line = port_info.get_name() + size_str; - } else { - verilog_line = VERILOG_PORT_TYPE_STRING[verilog_port_type]; + } else { + verilog_line = VERILOG_PORT_TYPE_STRING[verilog_port_type]; verilog_line += " " + size_str + " " + port_info.get_name(); } @@ -513,7 +535,7 @@ std::string generate_verilog_port(const enum e_dump_verilog_port_type& verilog_p /******************************************************************** * Evaluate if two Verilog ports can be merged: - * If the port name is same, it can merged + * If the port name is same, it can merged *******************************************************************/ bool two_verilog_ports_mergeable(const BasicPort& portA, const BasicPort& portB) { @@ -532,27 +554,30 @@ bool two_verilog_ports_mergeable(const BasicPort& portA, BasicPort merge_two_verilog_ports(const BasicPort& portA, const BasicPort& portB) { BasicPort merged_port; - + VTR_ASSERT(true == two_verilog_ports_mergeable(portA, portB)); merged_port.set_name(portA.get_name()); - merged_port.set_lsb((size_t)std::min((int)portA.get_lsb(), (int)portB.get_lsb())); - merged_port.set_msb((size_t)std::max((int)portA.get_msb(), (int)portB.get_msb())); + merged_port.set_lsb( + (size_t)std::min((int)portA.get_lsb(), (int)portB.get_lsb())); + merged_port.set_msb( + (size_t)std::max((int)portA.get_msb(), (int)portB.get_msb())); return merged_port; } /************************************************ * This function takes a list of ports and - * combine the port string by comparing the name + * combine the port string by comparing the name * and width of ports. - * For example, two ports A and B share the same name is + * For example, two ports A and B share the same name is * mergable as long as A's MSB + 1 == B's LSB * Note that the port sequence really matters! * This function will NOT change the sequence * of ports in the list port_info ***********************************************/ -std::vector combine_verilog_ports(const std::vector& ports) { +std::vector combine_verilog_ports( + const std::vector& ports) { std::vector merged_ports; /* Directly return if there are no ports */ @@ -567,8 +592,8 @@ std::vector combine_verilog_ports(const std::vector& ports /* Bypass the first port, it is already in the list */ if (&port == &ports[0]) { continue; - } - /* Identify if the port name can be potentially merged: + } + /* Identify if the port name can be potentially merged: * if the port can be merged to the last port in the list, it may be merged */ if (false == port.mergeable(merged_ports.back())) { @@ -581,11 +606,11 @@ std::vector combine_verilog_ports(const std::vector& ports /* Unable to merge, add the port to merged port list */ merged_ports.push_back(port); continue; - } + } /* Reach here, we should merge the ports, * LSB of merged_port remains the same, - * MSB of merged_port will be updated - * to the MSB of port + * MSB of merged_port will be updated + * to the MSB of port */ BasicPort& port_to_merge = merged_ports.back(); port_to_merge.set_msb(port.get_msb()); @@ -595,20 +620,20 @@ std::vector combine_verilog_ports(const std::vector& ports } /************************************************ - * Generate the string of a list of verilog ports + * Generate the string of a list of verilog ports ***********************************************/ -std::string generate_verilog_ports(const std::vector& merged_ports) { - +std::string generate_verilog_ports(const std::vector& merged_ports) { /* Output the string of ports: * If there is only one port in the merged_port list * we only output the port. - * If there are more than one port in the merged port list, we output an concatenated port: - * {, , ... } + * If there are more than one port in the merged port list, we output an + * concatenated port: + * {, , ... } */ VTR_ASSERT(0 < merged_ports.size()); - if ( 1 == merged_ports.size()) { + if (1 == merged_ports.size()) { /* Use connection type of verilog port */ - return generate_verilog_port(VERILOG_PORT_CONKT, merged_ports[0], false); + return generate_verilog_port(VERILOG_PORT_CONKT, merged_ports[0], false); } std::string verilog_line = "{"; @@ -617,7 +642,7 @@ std::string generate_verilog_ports(const std::vector& merged_ports) { if (&port != &merged_ports[0]) { verilog_line += ", "; } - verilog_line += generate_verilog_port(VERILOG_PORT_CONKT, port, false); + verilog_line += generate_verilog_port(VERILOG_PORT_CONKT, port, false); } verilog_line += "}"; @@ -625,17 +650,18 @@ std::string generate_verilog_ports(const std::vector& merged_ports) { } /******************************************************************** - * Generate a bus port (could be used to create a local wire) + * Generate a bus port (could be used to create a local wire) * for a list of Verilog ports - * The bus port will be created by aggregating the ports in the list - * A bus port name may be need only there are many ports with + * The bus port will be created by aggregating the ports in the list + * A bus port name may be need only there are many ports with * different names. It is hard to name the bus port *******************************************************************/ -BasicPort generate_verilog_bus_port(const std::vector& input_ports, +BasicPort generate_verilog_bus_port(const std::vector& input_ports, const std::string& bus_port_name) { /* Try to combine the ports */ - std::vector combined_input_ports = combine_verilog_ports(input_ports); - + std::vector combined_input_ports = + combine_verilog_ports(input_ports); + /* Create a port data structure that is to be returned */ BasicPort bus_port; @@ -650,7 +676,7 @@ BasicPort generate_verilog_bus_port(const std::vector& input_ports, bus_port.combine(port); } } - + return bus_port; } @@ -661,12 +687,13 @@ BasicPort generate_verilog_bus_port(const std::vector& input_ports, * When there are more than two ports, a bus wiring will be created * {, , ... } *******************************************************************/ -std::string generate_verilog_local_wire(const BasicPort& output_port, - const std::vector& input_ports) { +std::string generate_verilog_local_wire( + const BasicPort& output_port, const std::vector& input_ports) { /* Try to combine the ports */ - std::vector combined_input_ports = combine_verilog_ports(input_ports); + std::vector combined_input_ports = + combine_verilog_ports(input_ports); - /* If we have more than 1 port in the combined ports , + /* If we have more than 1 port in the combined ports , * output a local wire */ VTR_ASSERT(0 < combined_input_ports.size()); @@ -674,10 +701,10 @@ std::string generate_verilog_local_wire(const BasicPort& output_port, size_t input_ports_width = 0; for (const auto& port : combined_input_ports) { /* We must have valid ports! */ - VTR_ASSERT( 0 < port.get_width() ); + VTR_ASSERT(0 < port.get_width()); input_ports_width += port.get_width(); } - VTR_ASSERT( input_ports_width == output_port.get_width() ); + VTR_ASSERT(input_ports_width == output_port.get_width()); std::string wire_str; wire_str += generate_verilog_port(VERILOG_PORT_WIRE, output_port); @@ -697,8 +724,8 @@ std::string generate_verilog_local_wire(const BasicPort& output_port, * for all-zero/all-one vectors * {{1'b}} *******************************************************************/ -std::string generate_verilog_constant_values(const std::vector& const_values, - const bool& short_constant) { +std::string generate_verilog_constant_values( + const std::vector& const_values, const bool& short_constant) { VTR_ASSERT(!const_values.empty()); bool same_values = true; @@ -718,9 +745,9 @@ std::string generate_verilog_constant_values(const std::vector& const_va std::string str; - if ( (true == short_constant) - && (true == same_values) ) { - str = "{" + std::to_string(const_values.size()) + "{1'b" + std::to_string(first_val) + "}}"; + if ((true == short_constant) && (true == same_values)) { + str = "{" + std::to_string(const_values.size()) + "{1'b" + + std::to_string(first_val) + "}}"; } else { str = std::to_string(const_values.size()); str += "'b"; @@ -734,13 +761,13 @@ std::string generate_verilog_constant_values(const std::vector& const_va /******************************************************************** * Generate a verilog port with a deposit of constant values ********************************************************************/ -std::string generate_verilog_port_constant_values(const BasicPort& output_port, - const std::vector& const_values, - const bool& is_register) { +std::string generate_verilog_port_constant_values( + const BasicPort& output_port, const std::vector& const_values, + const bool& is_register) { std::string port_str; /* Must check: the port width matches */ - VTR_ASSERT( const_values.size() == output_port.get_width() ); + VTR_ASSERT(const_values.size() == output_port.get_width()); port_str = generate_verilog_port(VERILOG_PORT_CONKT, output_port); if (is_register) { @@ -756,9 +783,9 @@ std::string generate_verilog_port_constant_values(const BasicPort& output_port, /******************************************************************** * Generate a list of verilog ports with a deposit of constant values ********************************************************************/ -std::string generate_verilog_ports_constant_values(const std::vector& output_ports, - const std::vector& const_values, - const bool& is_register) { +std::string generate_verilog_ports_constant_values( + const std::vector& output_ports, + const std::vector& const_values, const bool& is_register) { std::string port_str; /* Must check: the port width matches */ @@ -766,7 +793,7 @@ std::string generate_verilog_ports_constant_values(const std::vector& for (const BasicPort& port : output_ports) { total_width += port.get_width(); } - VTR_ASSERT( const_values.size() == total_width ); + VTR_ASSERT(const_values.size() == total_width); port_str = generate_verilog_ports(output_ports); if (is_register) { @@ -780,12 +807,12 @@ std::string generate_verilog_ports_constant_values(const std::vector& } /******************************************************************** - * Generate a wire connection, that assigns constant values to a - * Verilog port + * Generate a wire connection, that assigns constant values to a + * Verilog port *******************************************************************/ -void print_verilog_wire_constant_values(std::fstream& fp, - const BasicPort& output_port, - const std::vector& const_values) { +void print_verilog_wire_constant_values( + std::fstream& fp, const BasicPort& output_port, + const std::vector& const_values) { /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); @@ -796,11 +823,11 @@ void print_verilog_wire_constant_values(std::fstream& fp, } /******************************************************************** - * Deposit constant values to a Verilog port + * Deposit constant values to a Verilog port *******************************************************************/ -void print_verilog_deposit_wire_constant_values(std::fstream& fp, - const BasicPort& output_port, - const std::vector& const_values) { +void print_verilog_deposit_wire_constant_values( + std::fstream& fp, const BasicPort& output_port, + const std::vector& const_values) { /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); @@ -813,12 +840,12 @@ void print_verilog_deposit_wire_constant_values(std::fstream& fp, } /******************************************************************** - * Generate a wire connection, that assigns constant values to a - * Verilog port + * Generate a wire connection, that assigns constant values to a + * Verilog port *******************************************************************/ -void print_verilog_force_wire_constant_values(std::fstream& fp, - const BasicPort& output_port, - const std::vector& const_values) { +void print_verilog_force_wire_constant_values( + std::fstream& fp, const BasicPort& output_port, + const std::vector& const_values) { /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); @@ -829,24 +856,24 @@ void print_verilog_force_wire_constant_values(std::fstream& fp, } /******************************************************************** - * Generate a wire connection for two Verilog ports - * using "assign" syntax + * Generate a wire connection for two Verilog ports + * using "assign" syntax *******************************************************************/ void print_verilog_wire_connection(std::fstream& fp, const BasicPort& output_port, - const BasicPort& input_port, + const BasicPort& input_port, const bool& inverted) { /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); /* Must check: the port width matches */ - VTR_ASSERT( input_port.get_width() == output_port.get_width() ); + VTR_ASSERT(input_port.get_width() == output_port.get_width()); fp << "\t"; fp << "assign "; fp << generate_verilog_port(VERILOG_PORT_CONKT, output_port); fp << " = "; - + if (true == inverted) { fp << "~"; } @@ -856,23 +883,23 @@ void print_verilog_wire_connection(std::fstream& fp, } /******************************************************************** - * Generate a wire connection for two Verilog ports - * using "assign" syntax + * Generate a wire connection for two Verilog ports + * using "assign" syntax *******************************************************************/ void print_verilog_register_connection(std::fstream& fp, const BasicPort& output_port, - const BasicPort& input_port, + const BasicPort& input_port, const bool& inverted) { /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); /* Must check: the port width matches */ - VTR_ASSERT( input_port.get_width() == output_port.get_width() ); + VTR_ASSERT(input_port.get_width() == output_port.get_width()); fp << "\t"; fp << generate_verilog_port(VERILOG_PORT_CONKT, output_port); fp << " <= "; - + if (true == inverted) { fp << "~"; } @@ -881,69 +908,82 @@ void print_verilog_register_connection(std::fstream& fp, fp << ";" << std::endl; } - /******************************************************************** - * Generate an instance of a buffer module + * Generate an instance of a buffer module * with given information about the input and output ports of instance * * Buffer instance * +----------------------------------------+ - * instance_input_port --->| buffer_input_port buffer_output_port|----> instance_output_port + * instance_input_port --->| buffer_input_port buffer_output_port|----> + *instance_output_port * +----------------------------------------+ * * Restrictions: - * Buffer must have only 1 input (non-global) port and 1 output (non-global) port + * Buffer must have only 1 input (non-global) port and 1 output (non-global) + *port *******************************************************************/ void print_verilog_buffer_instance(std::fstream& fp, - ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const ModuleId& parent_module_id, - const CircuitModelId& buffer_model, + ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const ModuleId& parent_module_id, + const CircuitModelId& buffer_model, const BasicPort& instance_input_port, const BasicPort& instance_output_port) { /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); - /* To match the context, Buffer should have only 2 non-global ports: 1 input port and 1 output port */ - std::vector buffer_model_input_ports = circuit_lib.model_ports_by_type(buffer_model, CIRCUIT_MODEL_PORT_INPUT, true); - std::vector buffer_model_output_ports = circuit_lib.model_ports_by_type(buffer_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + /* To match the context, Buffer should have only 2 non-global ports: 1 input + * port and 1 output port */ + std::vector buffer_model_input_ports = + circuit_lib.model_ports_by_type(buffer_model, CIRCUIT_MODEL_PORT_INPUT, + true); + std::vector buffer_model_output_ports = + circuit_lib.model_ports_by_type(buffer_model, CIRCUIT_MODEL_PORT_OUTPUT, + true); VTR_ASSERT(1 == buffer_model_input_ports.size()); VTR_ASSERT(1 == buffer_model_output_ports.size()); /* Get the moduleId for the buffer module */ - ModuleId buffer_module_id = module_manager.find_module(circuit_lib.model_name(buffer_model)); + ModuleId buffer_module_id = + module_manager.find_module(circuit_lib.model_name(buffer_model)); /* We must have one */ VTR_ASSERT(ModuleId::INVALID() != buffer_module_id); /* Create a port-to-port map */ std::map buffer_port2port_name_map; - /* Build the link between buffer_input_port[0] and output_node_pre_buffer + /* Build the link between buffer_input_port[0] and output_node_pre_buffer * Build the link between buffer_output_port[0] and output_node_bufferred */ { /* Create a code block to accommodate the local variables */ - std::string module_input_port_name = circuit_lib.port_lib_name(buffer_model_input_ports[0]); - buffer_port2port_name_map[module_input_port_name] = instance_input_port; - std::string module_output_port_name = circuit_lib.port_lib_name(buffer_model_output_ports[0]); - buffer_port2port_name_map[module_output_port_name] = instance_output_port; + std::string module_input_port_name = + circuit_lib.port_lib_name(buffer_model_input_ports[0]); + buffer_port2port_name_map[module_input_port_name] = instance_input_port; + std::string module_output_port_name = + circuit_lib.port_lib_name(buffer_model_output_ports[0]); + buffer_port2port_name_map[module_output_port_name] = instance_output_port; } /* Output an instance of the module */ - print_verilog_module_instance(fp, module_manager, parent_module_id, buffer_module_id, buffer_port2port_name_map, circuit_lib.dump_explicit_port_map(buffer_model)); + print_verilog_module_instance( + fp, module_manager, parent_module_id, buffer_module_id, + buffer_port2port_name_map, + circuit_lib.dump_explicit_port_map(buffer_model)); /* IMPORTANT: this update MUST be called after the instance outputting!!!! - * update the module manager with the relationship between the parent and child modules + * update the module manager with the relationship between the parent and + * child modules */ module_manager.add_child_module(parent_module_id, buffer_module_id); } /******************************************************************** - * Print local wires that are used for SRAM configuration + * Print local wires that are used for SRAM configuration * The local wires are strongly dependent on the organization of SRAMs. - * Standalone SRAMs: + * Standalone SRAMs: * ----------------- * No need for local wires, their outputs are port of the module - * + * * Module * +------------------------------+ * | Sub-module | @@ -953,7 +993,7 @@ void print_verilog_buffer_instance(std::fstream& fp, * | | sram_out|---->|---->sram_out * | | | | * | +---------------------+ | - * +------------------------------+ + * +------------------------------+ * * Configuration chain-style * ------------------------- @@ -966,7 +1006,8 @@ void print_verilog_buffer_instance(std::fstream& fp, * | [0] [1] [2] [N] | * | | | | | | * | v v v v | - * ccff_head| ----------+ +---------+ +------------+ +----------------|-> ccff_tail + * ccff_head| ----------+ +---------+ +------------+ +----------------|-> + ccff_tail * | | ^ | ^ | ^ | * | head v |tail v | v | | * | +----------+ +----------+ +----------+ | @@ -986,8 +1027,8 @@ void print_verilog_buffer_instance(std::fstream& fp, * * Memory bank-style * ----------------- - * two ports will be added, which are regular output and inverted output - * Note that the outputs are the data outputs of SRAMs + * two ports will be added, which are regular output and inverted output + * Note that the outputs are the data outputs of SRAMs * BL/WLs of memory decoders are ports of module but not local wires * * Module @@ -1026,53 +1067,69 @@ void print_verilog_local_sram_wires(std::fstream& fp, } /* Depend on the configuraion style */ - switch(sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - /* Nothing to do here */ - break; - case CONFIG_MEM_SCAN_CHAIN: { - /* Generate the name of local wire for the CCFF inputs, CCFF output and inverted output */ - /* [0] => CCFF input */ - BasicPort ccff_config_bus_port(generate_local_config_bus_port_name(), port_size); - fp << generate_verilog_port(VERILOG_PORT_WIRE, ccff_config_bus_port) << ";" << std::endl; - /* Connect first CCFF to the head */ - /* Head is always a 1-bit port */ - BasicPort ccff_head_port(generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_INPUT), 1); - BasicPort ccff_head_local_port(ccff_config_bus_port.get_name(), 1); - print_verilog_wire_connection(fp, ccff_head_local_port, ccff_head_port, false); - /* Connect last CCFF to the tail */ - /* Tail is always a 1-bit port */ - BasicPort ccff_tail_port(generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_OUTPUT), 1); - BasicPort ccff_tail_local_port(ccff_config_bus_port.get_name(), ccff_config_bus_port.get_msb(), ccff_config_bus_port.get_msb()); - print_verilog_wire_connection(fp, ccff_tail_local_port, ccff_tail_port, false); - break; - } - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: { - /* Generate the name of local wire for the SRAM output and inverted output */ - std::vector sram_ports; - /* [0] => SRAM output */ - sram_ports.push_back(BasicPort(generate_sram_local_port_name(circuit_lib, sram_model, sram_orgz_type, CIRCUIT_MODEL_PORT_INPUT), port_size)); - /* [1] => SRAM inverted output */ - sram_ports.push_back(BasicPort(generate_sram_local_port_name(circuit_lib, sram_model, sram_orgz_type, CIRCUIT_MODEL_PORT_OUTPUT), port_size)); - /* Print local wire definition */ - for (const auto& sram_port : sram_ports) { - fp << generate_verilog_port(VERILOG_PORT_WIRE, sram_port) << ";" << std::endl; + switch (sram_orgz_type) { + case CONFIG_MEM_STANDALONE: + /* Nothing to do here */ + break; + case CONFIG_MEM_SCAN_CHAIN: { + /* Generate the name of local wire for the CCFF inputs, CCFF output and + * inverted output */ + /* [0] => CCFF input */ + BasicPort ccff_config_bus_port(generate_local_config_bus_port_name(), + port_size); + fp << generate_verilog_port(VERILOG_PORT_WIRE, ccff_config_bus_port) + << ";" << std::endl; + /* Connect first CCFF to the head */ + /* Head is always a 1-bit port */ + BasicPort ccff_head_port( + generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_INPUT), 1); + BasicPort ccff_head_local_port(ccff_config_bus_port.get_name(), 1); + print_verilog_wire_connection(fp, ccff_head_local_port, ccff_head_port, + false); + /* Connect last CCFF to the tail */ + /* Tail is always a 1-bit port */ + BasicPort ccff_tail_port( + generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_OUTPUT), 1); + BasicPort ccff_tail_local_port(ccff_config_bus_port.get_name(), + ccff_config_bus_port.get_msb(), + ccff_config_bus_port.get_msb()); + print_verilog_wire_connection(fp, ccff_tail_local_port, ccff_tail_port, + false); + break; } + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: { + /* Generate the name of local wire for the SRAM output and inverted output + */ + std::vector sram_ports; + /* [0] => SRAM output */ + sram_ports.push_back(BasicPort( + generate_sram_local_port_name(circuit_lib, sram_model, sram_orgz_type, + CIRCUIT_MODEL_PORT_INPUT), + port_size)); + /* [1] => SRAM inverted output */ + sram_ports.push_back(BasicPort( + generate_sram_local_port_name(circuit_lib, sram_model, sram_orgz_type, + CIRCUIT_MODEL_PORT_OUTPUT), + port_size)); + /* Print local wire definition */ + for (const auto& sram_port : sram_ports) { + fp << generate_verilog_port(VERILOG_PORT_WIRE, sram_port) << ";" + << std::endl; + } - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid SRAM organization!\n"); - exit(1); + break; + } + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid SRAM organization!\n"); + exit(1); } } /********************************************************************* * Print a number of bus ports which are wired to the configuration * ports of a CMOS (SRAM-based) routing multiplexer - * This port is supposed to be used locally inside a Verilog/SPICE module + * This port is supposed to be used locally inside a Verilog/SPICE module * * The following shows a few representative examples: * @@ -1121,53 +1178,57 @@ void print_verilog_local_sram_wires(std::fstream& fp, * | Module | | Module | ... | Module | * | [0] | | [1] | | [N] | * +----------+ +----------+ +----------+ - * + * *********************************************************************/ -void print_verilog_local_config_bus(std::fstream& fp, - const std::string& prefix, - const e_config_protocol_type& sram_orgz_type, - const size_t& instance_id, - const size_t& num_conf_bits) { +void print_verilog_local_config_bus( + std::fstream& fp, const std::string& prefix, + const e_config_protocol_type& sram_orgz_type, const size_t& instance_id, + const size_t& num_conf_bits) { /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); - switch(sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - /* Not need for configuration bus - * The configuration ports of SRAM are directly wired to the ports of modules - */ - break; - case CONFIG_MEM_SCAN_CHAIN: - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: { - /* Two configuration buses should be outputted - * One for the regular SRAM ports of a routing multiplexer - * The other for the inverted SRAM ports of a routing multiplexer - */ - BasicPort config_port(generate_local_sram_port_name(prefix, instance_id, CIRCUIT_MODEL_PORT_INPUT), - num_conf_bits); - fp << generate_verilog_port(VERILOG_PORT_WIRE, config_port) << ";" << std::endl; - BasicPort inverted_config_port(generate_local_sram_port_name(prefix, instance_id, CIRCUIT_MODEL_PORT_OUTPUT), - num_conf_bits); - fp << generate_verilog_port(VERILOG_PORT_WIRE, inverted_config_port) << ";" << std::endl; - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid SRAM organization!\n"); - exit(1); + switch (sram_orgz_type) { + case CONFIG_MEM_STANDALONE: + /* Not need for configuration bus + * The configuration ports of SRAM are directly wired to the ports of + * modules + */ + break; + case CONFIG_MEM_SCAN_CHAIN: + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: { + /* Two configuration buses should be outputted + * One for the regular SRAM ports of a routing multiplexer + * The other for the inverted SRAM ports of a routing multiplexer + */ + BasicPort config_port(generate_local_sram_port_name( + prefix, instance_id, CIRCUIT_MODEL_PORT_INPUT), + num_conf_bits); + fp << generate_verilog_port(VERILOG_PORT_WIRE, config_port) << ";" + << std::endl; + BasicPort inverted_config_port( + generate_local_sram_port_name(prefix, instance_id, + CIRCUIT_MODEL_PORT_OUTPUT), + num_conf_bits); + fp << generate_verilog_port(VERILOG_PORT_WIRE, inverted_config_port) + << ";" << std::endl; + break; + } + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid SRAM organization!\n"); + exit(1); } } /********************************************************************* * Print a number of bus ports which are wired to the configuration * ports of a ReRAM-based routing multiplexer - * This port is supposed to be used locally inside a Verilog/SPICE module + * This port is supposed to be used locally inside a Verilog/SPICE module * - * Currently support: + * Currently support: * For memory-bank configuration style: * ------------------------------------ - * Different than CMOS routing multiplexers, ReRAM multiplexers require + * Different than CMOS routing multiplexers, ReRAM multiplexers require * reserved BL/WLs to be grouped in buses * * Module Port @@ -1186,88 +1247,109 @@ void print_verilog_local_config_bus(std::fstream& fp, * | Routing | | Routing | * | MUX [0] | | MUX[1] | ... * +-----------+ +-----------+ - * + * *********************************************************************/ -static -void print_verilog_rram_mux_config_bus(std::fstream& fp, - const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const e_config_protocol_type& sram_orgz_type, - const size_t& mux_size, - const size_t& mux_instance_id, - const size_t& num_reserved_conf_bits, - const size_t& num_conf_bits) { +static void print_verilog_rram_mux_config_bus( + std::fstream& fp, const CircuitLibrary& circuit_lib, + const CircuitModelId& mux_model, const e_config_protocol_type& sram_orgz_type, + const size_t& mux_size, const size_t& mux_instance_id, + const size_t& num_reserved_conf_bits, const size_t& num_conf_bits) { /* Make sure we have a valid file handler*/ VTR_ASSERT(true == valid_file_stream(fp)); - switch(sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - /* Not need for configuration bus - * The configuration ports of SRAM are directly wired to the ports of modules - */ - break; - case CONFIG_MEM_SCAN_CHAIN: { - /* Not supported yet. - * Configuration chain may be only applied to ReRAM-based multiplexers with local decoders - */ - break; + switch (sram_orgz_type) { + case CONFIG_MEM_STANDALONE: + /* Not need for configuration bus + * The configuration ports of SRAM are directly wired to the ports of + * modules + */ + break; + case CONFIG_MEM_SCAN_CHAIN: { + /* Not supported yet. + * Configuration chain may be only applied to ReRAM-based multiplexers + * with local decoders + */ + break; + } + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: { + /* This is currently most used in ReRAM FPGAs */ + /* Print configuration bus to group reserved BL/WLs */ + BasicPort reserved_bl_bus( + generate_reserved_sram_port_name(CIRCUIT_MODEL_PORT_BL), + num_reserved_conf_bits); + fp << generate_verilog_port(VERILOG_PORT_WIRE, reserved_bl_bus) << ";" + << std::endl; + BasicPort reserved_wl_bus( + generate_reserved_sram_port_name(CIRCUIT_MODEL_PORT_WL), + num_reserved_conf_bits); + fp << generate_verilog_port(VERILOG_PORT_WIRE, reserved_wl_bus) << ";" + << std::endl; + + /* Print configuration bus to group BL/WLs */ + BasicPort bl_bus(generate_mux_config_bus_port_name(circuit_lib, mux_model, + mux_size, 0, false), + num_conf_bits + num_reserved_conf_bits); + fp << generate_verilog_port(VERILOG_PORT_WIRE, bl_bus) << ";" + << std::endl; + BasicPort wl_bus(generate_mux_config_bus_port_name(circuit_lib, mux_model, + mux_size, 1, false), + num_conf_bits + num_reserved_conf_bits); + fp << generate_verilog_port(VERILOG_PORT_WIRE, wl_bus) << ";" + << std::endl; + + /* Print bus to group SRAM outputs, this is to interface memory cells to + * routing multiplexers */ + BasicPort sram_output_bus( + generate_mux_sram_port_name(circuit_lib, mux_model, mux_size, + mux_instance_id, CIRCUIT_MODEL_PORT_INPUT), + num_conf_bits); + fp << generate_verilog_port(VERILOG_PORT_WIRE, sram_output_bus) << ";" + << std::endl; + BasicPort inverted_sram_output_bus( + generate_mux_sram_port_name(circuit_lib, mux_model, mux_size, + mux_instance_id, CIRCUIT_MODEL_PORT_OUTPUT), + num_conf_bits); + fp << generate_verilog_port(VERILOG_PORT_WIRE, inverted_sram_output_bus) + << ";" << std::endl; + + /* Get the SRAM model of the mux_model */ + std::vector sram_models = + find_circuit_sram_models(circuit_lib, mux_model); + /* TODO: maybe later multiplexers may have mode select ports... This + * should be relaxed */ + VTR_ASSERT(1 == sram_models.size()); + + /* Wire the reserved configuration bits to part of bl/wl buses */ + BasicPort bl_bus_reserved_bits(bl_bus.get_name(), num_reserved_conf_bits); + print_verilog_wire_connection(fp, bl_bus_reserved_bits, reserved_bl_bus, + false); + BasicPort wl_bus_reserved_bits(wl_bus.get_name(), num_reserved_conf_bits); + print_verilog_wire_connection(fp, wl_bus_reserved_bits, reserved_wl_bus, + false); + + /* Connect SRAM BL/WLs to bus */ + BasicPort mux_bl_wire( + generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_BL), + num_conf_bits); + BasicPort bl_bus_regular_bits(bl_bus.get_name(), num_reserved_conf_bits, + num_reserved_conf_bits + num_conf_bits - 1); + print_verilog_wire_connection(fp, bl_bus_regular_bits, mux_bl_wire, + false); + BasicPort mux_wl_wire( + generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_WL), + num_conf_bits); + BasicPort wl_bus_regular_bits(wl_bus.get_name(), num_reserved_conf_bits, + num_reserved_conf_bits + num_conf_bits - 1); + print_verilog_wire_connection(fp, wl_bus_regular_bits, mux_wl_wire, + false); + + break; + } + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid SRAM organization!\n"); + exit(1); } - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: { - /* This is currently most used in ReRAM FPGAs */ - /* Print configuration bus to group reserved BL/WLs */ - BasicPort reserved_bl_bus(generate_reserved_sram_port_name(CIRCUIT_MODEL_PORT_BL), - num_reserved_conf_bits); - fp << generate_verilog_port(VERILOG_PORT_WIRE, reserved_bl_bus) << ";" << std::endl; - BasicPort reserved_wl_bus(generate_reserved_sram_port_name(CIRCUIT_MODEL_PORT_WL), - num_reserved_conf_bits); - fp << generate_verilog_port(VERILOG_PORT_WIRE, reserved_wl_bus) << ";" << std::endl; - - /* Print configuration bus to group BL/WLs */ - BasicPort bl_bus(generate_mux_config_bus_port_name(circuit_lib, mux_model, mux_size, 0, false), - num_conf_bits + num_reserved_conf_bits); - fp << generate_verilog_port(VERILOG_PORT_WIRE, bl_bus) << ";" << std::endl; - BasicPort wl_bus(generate_mux_config_bus_port_name(circuit_lib, mux_model, mux_size, 1, false), - num_conf_bits + num_reserved_conf_bits); - fp << generate_verilog_port(VERILOG_PORT_WIRE, wl_bus) << ";" << std::endl; - - /* Print bus to group SRAM outputs, this is to interface memory cells to routing multiplexers */ - BasicPort sram_output_bus(generate_mux_sram_port_name(circuit_lib, mux_model, mux_size, mux_instance_id, CIRCUIT_MODEL_PORT_INPUT), - num_conf_bits); - fp << generate_verilog_port(VERILOG_PORT_WIRE, sram_output_bus) << ";" << std::endl; - BasicPort inverted_sram_output_bus(generate_mux_sram_port_name(circuit_lib, mux_model, mux_size, mux_instance_id, CIRCUIT_MODEL_PORT_OUTPUT), - num_conf_bits); - fp << generate_verilog_port(VERILOG_PORT_WIRE, inverted_sram_output_bus) << ";" << std::endl; - - /* Get the SRAM model of the mux_model */ - std::vector sram_models = find_circuit_sram_models(circuit_lib, mux_model); - /* TODO: maybe later multiplexers may have mode select ports... This should be relaxed */ - VTR_ASSERT( 1 == sram_models.size() ); - - /* Wire the reserved configuration bits to part of bl/wl buses */ - BasicPort bl_bus_reserved_bits(bl_bus.get_name(), num_reserved_conf_bits); - print_verilog_wire_connection(fp, bl_bus_reserved_bits, reserved_bl_bus, false); - BasicPort wl_bus_reserved_bits(wl_bus.get_name(), num_reserved_conf_bits); - print_verilog_wire_connection(fp, wl_bus_reserved_bits, reserved_wl_bus, false); - - /* Connect SRAM BL/WLs to bus */ - BasicPort mux_bl_wire(generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_BL), - num_conf_bits); - BasicPort bl_bus_regular_bits(bl_bus.get_name(), num_reserved_conf_bits, num_reserved_conf_bits + num_conf_bits - 1); - print_verilog_wire_connection(fp, bl_bus_regular_bits, mux_bl_wire, false); - BasicPort mux_wl_wire(generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_WL), - num_conf_bits); - BasicPort wl_bus_regular_bits(wl_bus.get_name(), num_reserved_conf_bits, num_reserved_conf_bits + num_conf_bits - 1); - print_verilog_wire_connection(fp, wl_bus_regular_bits, mux_wl_wire, false); - - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid SRAM organization!\n"); - exit(1); - } - } /********************************************************************* @@ -1278,65 +1360,70 @@ void print_verilog_rram_mux_config_bus(std::fstream& fp, * module, rather than the programming routing multiplexers, LUTs, IOs * etc. This helps us to keep clean and simple Verilog generation *********************************************************************/ -void print_verilog_mux_config_bus(std::fstream& fp, - const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const e_config_protocol_type& sram_orgz_type, - const size_t& mux_size, - const size_t& mux_instance_id, - const size_t& num_reserved_conf_bits, - const size_t& num_conf_bits) { +void print_verilog_mux_config_bus( + std::fstream& fp, const CircuitLibrary& circuit_lib, + const CircuitModelId& mux_model, const e_config_protocol_type& sram_orgz_type, + const size_t& mux_size, const size_t& mux_instance_id, + const size_t& num_reserved_conf_bits, const size_t& num_conf_bits) { /* Depend on the design technology of this MUX: * bus connections are different * SRAM MUX: bus is connected to the output ports of SRAM * RRAM MUX: bus is connected to the BL/WL of MUX - * TODO: Maybe things will become even more complicated, + * TODO: Maybe things will become even more complicated, * the bus connections may depend on the type of configuration circuit... * Currently, this is fine. */ switch (circuit_lib.design_tech_type(mux_model)) { - case CIRCUIT_MODEL_DESIGN_CMOS: { - std::string prefix = generate_mux_subckt_name(circuit_lib, mux_model, mux_size, std::string()); - print_verilog_local_config_bus(fp, prefix, sram_orgz_type, mux_instance_id, num_conf_bits); - break; - } - case CIRCUIT_MODEL_DESIGN_RRAM: - print_verilog_rram_mux_config_bus(fp, circuit_lib, mux_model, sram_orgz_type, mux_size, mux_instance_id, num_reserved_conf_bits, num_conf_bits); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid design technology for routing multiplexer!\n"); - exit(1); + case CIRCUIT_MODEL_DESIGN_CMOS: { + std::string prefix = generate_mux_subckt_name(circuit_lib, mux_model, + mux_size, std::string()); + print_verilog_local_config_bus(fp, prefix, sram_orgz_type, + mux_instance_id, num_conf_bits); + break; + } + case CIRCUIT_MODEL_DESIGN_RRAM: + print_verilog_rram_mux_config_bus( + fp, circuit_lib, mux_model, sram_orgz_type, mux_size, mux_instance_id, + num_reserved_conf_bits, num_conf_bits); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid design technology for routing multiplexer!\n"); + exit(1); } } /********************************************************************* - * Print a wire to connect MUX configuration ports + * Print a wire to connect MUX configuration ports * This function connects the sram ports to the ports of a Verilog module * used for formal verification * - * Note: MSB and LSB of formal verification configuration bus MUST be updated + * Note: MSB and LSB of formal verification configuration bus MUST be updated * before running this function !!!! *********************************************************************/ -void print_verilog_formal_verification_mux_sram_ports_wiring(std::fstream& fp, - const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const size_t& mux_size, - const size_t& mux_instance_id, - const size_t& num_conf_bits, - const BasicPort& fm_config_bus) { - BasicPort mux_sram_output(generate_mux_sram_port_name(circuit_lib, mux_model, mux_size, mux_instance_id, CIRCUIT_MODEL_PORT_INPUT), - num_conf_bits); +void print_verilog_formal_verification_mux_sram_ports_wiring( + std::fstream& fp, const CircuitLibrary& circuit_lib, + const CircuitModelId& mux_model, const size_t& mux_size, + const size_t& mux_instance_id, const size_t& num_conf_bits, + const BasicPort& fm_config_bus) { + BasicPort mux_sram_output( + generate_mux_sram_port_name(circuit_lib, mux_model, mux_size, + mux_instance_id, CIRCUIT_MODEL_PORT_INPUT), + num_conf_bits); /* Get the SRAM model of the mux_model */ - std::vector sram_models = find_circuit_sram_models(circuit_lib, mux_model); - /* TODO: maybe later multiplexers may have mode select ports... This should be relaxed */ - VTR_ASSERT( 1 == sram_models.size() ); + std::vector sram_models = + find_circuit_sram_models(circuit_lib, mux_model); + /* TODO: maybe later multiplexers may have mode select ports... This should be + * relaxed */ + VTR_ASSERT(1 == sram_models.size()); BasicPort formal_verification_port; - formal_verification_port.set_name(generate_formal_verification_sram_port_name(circuit_lib, sram_models[0])); + formal_verification_port.set_name( + generate_formal_verification_sram_port_name(circuit_lib, sram_models[0])); VTR_ASSERT(num_conf_bits == fm_config_bus.get_width()); formal_verification_port.set_lsb(fm_config_bus.get_lsb()); formal_verification_port.set_msb(fm_config_bus.get_msb()); - print_verilog_wire_connection(fp, mux_sram_output, formal_verification_port, false); + print_verilog_wire_connection(fp, mux_sram_output, formal_verification_port, + false); } /******************************************************************** @@ -1344,12 +1431,11 @@ void print_verilog_formal_verification_mux_sram_ports_wiring(std::fstream& fp, * * |<--- pulse width --->| * +------ flip_value - * | - * initial_value ----------------------+ + * | + * initial_value ----------------------+ * *******************************************************************/ -void print_verilog_pulse_stimuli(std::fstream& fp, - const BasicPort& port, +void print_verilog_pulse_stimuli(std::fstream& fp, const BasicPort& port, const size_t& initial_value, const float& pulse_width, const size_t& flip_value) { @@ -1364,10 +1450,12 @@ void print_verilog_pulse_stimuli(std::fstream& fp, fp << "\t"; fp << generate_verilog_port_constant_values(port, initial_values); fp << ";" << std::endl; - - /* if flip_value is the same as initial value, we do not need to flip the signal ! */ + + /* if flip_value is the same as initial value, we do not need to flip the + * signal ! */ if (flip_value != initial_value) { - fp << "\t" << "#" << std::setprecision(10) << pulse_width; + fp << "\t" + << "#" << std::setprecision(10) << pulse_width; std::vector port_flip_values(port.get_width(), flip_value); fp << "\t"; fp << generate_verilog_port_constant_values(port, port_flip_values); @@ -1380,18 +1468,17 @@ void print_verilog_pulse_stimuli(std::fstream& fp, fp << std::endl; } - /******************************************************************** * Print stimuli for a clock pulse generation * This function supports the delay at the beginning of the waveform * * |<-- Initial delay -->|<--- pulse width --->| * +------ flip_value - * | - * initial_value --------------------------------------------+ + * | + * initial_value --------------------------------------------+ * *******************************************************************/ -void print_verilog_shifted_clock_stimuli(std::fstream& fp, +void print_verilog_shifted_clock_stimuli(std::fstream& fp, const BasicPort& port, const float& initial_delay, const float& pulse_width, @@ -1417,13 +1504,13 @@ void print_verilog_shifted_clock_stimuli(std::fstream& fp, fp << ";" << std::endl; write_tab_to_file(fp, 2); - fp << "forever "; + fp << "forever "; fp << generate_verilog_port(VERILOG_PORT_CONKT, port); - fp << " = "; + fp << " = "; fp << "#" << std::setprecision(10) << pulse_width; fp << " ~" << generate_verilog_port(VERILOG_PORT_CONKT, port); fp << ";" << std::endl; - + write_tab_to_file(fp, 1); fp << "end" << std::endl; @@ -1437,13 +1524,13 @@ void print_verilog_shifted_clock_stimuli(std::fstream& fp, * * |<-- wait condition -->| * |<--- pulse width --->| - * +------ flip_values - * | - * initial_value ------- ... --------------------------------+ + * +------ + *flip_values + * | + * initial_value ------- ... --------------------------------+ * *******************************************************************/ -void print_verilog_pulse_stimuli(std::fstream& fp, - const BasicPort& port, +void print_verilog_pulse_stimuli(std::fstream& fp, const BasicPort& port, const size_t& initial_value, const std::vector& pulse_widths, const std::vector& flip_values, @@ -1464,11 +1551,12 @@ void print_verilog_pulse_stimuli(std::fstream& fp, if (false == wait_condition.empty()) { fp << "\twait(" << wait_condition << ")" << std::endl; } - + /* Number of flip conditions and values should match */ VTR_ASSERT(flip_values.size() == pulse_widths.size()); for (size_t ipulse = 0; ipulse < pulse_widths.size(); ++ipulse) { - fp << "\t" << "#" << std::setprecision(10) << pulse_widths[ipulse]; + fp << "\t" + << "#" << std::setprecision(10) << pulse_widths[ipulse]; std::vector port_flip_value(port.get_width(), flip_values[ipulse]); fp << "\t"; fp << generate_verilog_port_constant_values(port, port_flip_value); @@ -1484,7 +1572,7 @@ void print_verilog_pulse_stimuli(std::fstream& fp, /******************************************************************** * Print stimuli for a clock signal * This function can support if the clock signal should wait for a period - * of time and then start + * of time and then start * pulse width * |<----->| * +-------+ +-------+ @@ -1493,8 +1581,7 @@ void print_verilog_pulse_stimuli(std::fstream& fp, * |<--wait_condition-->| * *******************************************************************/ -void print_verilog_clock_stimuli(std::fstream& fp, - const BasicPort& port, +void print_verilog_clock_stimuli(std::fstream& fp, const BasicPort& port, const size_t& initial_value, const float& pulse_width, const std::string& wait_condition) { @@ -1521,7 +1608,8 @@ void print_verilog_clock_stimuli(std::fstream& fp, } fp << "\tbegin" << std::endl; - fp << "\t\t" << "#" << std::setprecision(10) << pulse_width; + fp << "\t\t" + << "#" << std::setprecision(10) << pulse_width; fp << "\t"; fp << generate_verilog_port(VERILOG_PORT_CONKT, port); @@ -1540,12 +1628,12 @@ void print_verilog_clock_stimuli(std::fstream& fp, * Output a header file that includes a number of Verilog netlists * so that it can be easily included in a top-level netlist ********************************************************************/ -void print_verilog_netlist_include_header_file(const std::vector& netlists_to_be_included, - const char* subckt_dir, - const char* header_file_name, - const bool& include_time_stamp) { - - std::string verilog_fname(std::string(subckt_dir) + std::string(header_file_name)); +void print_verilog_netlist_include_header_file( + const std::vector& netlists_to_be_included, + const char* subckt_dir, const char* header_file_name, + const bool& include_time_stamp) { + std::string verilog_fname(std::string(subckt_dir) + + std::string(header_file_name)); /* Create the file stream */ std::fstream fp; @@ -1554,7 +1642,8 @@ void print_verilog_netlist_include_header_file(const std::vector& n VTR_ASSERT(true == valid_file_stream(fp)); /* Generate the descriptions*/ - print_verilog_file_header(fp, "Header file to include other Verilog netlists", include_time_stamp); + print_verilog_file_header(fp, "Header file to include other Verilog netlists", + include_time_stamp); /* Output file names */ for (const std::string& netlist_name : netlists_to_be_included) { diff --git a/openfpga/src/fpga_verilog/verilog_writer_utils.h b/openfpga/src/fpga_verilog/verilog_writer_utils.h index 180df8e45..cf9faa6b9 100644 --- a/openfpga/src/fpga_verilog/verilog_writer_utils.h +++ b/openfpga/src/fpga_verilog/verilog_writer_utils.h @@ -1,21 +1,22 @@ /************************************************ * Header file for verilog_writer_utils.cpp * Include function declaration for most frequently - * used Verilog writers + * used Verilog writers ***********************************************/ -#ifndef VERILOG_WRITER_UTILS_H -#define VERILOG_WRITER_UTILS_H +#ifndef VERILOG_WRITER_UTILS_H +#define VERILOG_WRITER_UTILS_H /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ #include -#include #include -#include "openfpga_port.h" -#include "verilog_port_types.h" +#include + #include "circuit_library.h" #include "module_manager.h" +#include "openfpga_port.h" +#include "verilog_port_types.h" /******************************************************************** * Function declaration @@ -26,69 +27,66 @@ namespace openfpga { /* Tips: for naming your function in this header/source file * If a function outputs to a file, its name should begin with "print_verilog" - * If a function creates a string without outputting to a file, its name should begin with "generate_verilog" - * Please show respect to this naming convention, in order to keep a clean header/source file - * as well maintain a easy way to identify the functions + * If a function creates a string without outputting to a file, its name should + * begin with "generate_verilog" Please show respect to this naming convention, + * in order to keep a clean header/source file as well maintain a easy way to + * identify the functions */ -void print_verilog_default_net_type_declaration(std::fstream& fp, - const e_verilog_default_net_type& default_net_type); +void print_verilog_default_net_type_declaration( + std::fstream& fp, const e_verilog_default_net_type& default_net_type); -void print_verilog_file_header(std::fstream& fp, - const std::string& usage, +void print_verilog_file_header(std::fstream& fp, const std::string& usage, const bool& include_time_stamp); -void print_verilog_include_netlist(std::fstream& fp, +void print_verilog_include_netlist(std::fstream& fp, const std::string& netlist_name); -void print_verilog_define_flag(std::fstream& fp, - const std::string& flag_name, +void print_verilog_define_flag(std::fstream& fp, const std::string& flag_name, const int& flag_value); -void print_verilog_include_defines_preproc_file(std::fstream& fp, +void print_verilog_include_defines_preproc_file(std::fstream& fp, const std::string& verilog_dir); -void print_verilog_comment(std::fstream& fp, - const std::string& comment); +void print_verilog_comment(std::fstream& fp, const std::string& comment); void print_verilog_preprocessing_flag(std::fstream& fp, const std::string& preproc_flag); void print_verilog_endif(std::fstream& fp); -void print_verilog_module_definition(std::fstream& fp, - const ModuleManager& module_manager, const ModuleId& module_id); +void print_verilog_module_definition(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& module_id); -void print_verilog_module_ports(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const e_verilog_default_net_type& default_net_type); +void print_verilog_module_ports( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, + const e_verilog_default_net_type& default_net_type); -void print_verilog_module_declaration(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const e_verilog_default_net_type& default_net_type); +void print_verilog_module_declaration( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, + const e_verilog_default_net_type& default_net_type); -void print_verilog_module_instance(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& module_id, - const std::string& instance_name, - const std::map& port2port_name_map, - const bool& use_explicit_port_map); +void print_verilog_module_instance( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& module_id, const std::string& instance_name, + const std::map& port2port_name_map, + const bool& use_explicit_port_map); -void print_verilog_module_instance(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& parent_module_id, const ModuleId& child_module_id, - const std::map& port2port_name_map, - const bool& use_explicit_port_map); +void print_verilog_module_instance( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& parent_module_id, const ModuleId& child_module_id, + const std::map& port2port_name_map, + const bool& use_explicit_port_map); -void print_verilog_module_end(std::fstream& fp, - const std::string& module_name); +void print_verilog_module_end(std::fstream& fp, const std::string& module_name); -std::string generate_verilog_port(const enum e_dump_verilog_port_type& dump_port_type, - const BasicPort& port_info, - const bool& must_print_port_size = true, - const bool& big_endian = true); +std::string generate_verilog_port( + const enum e_dump_verilog_port_type& dump_port_type, + const BasicPort& port_info, const bool& must_print_port_size = true, + const bool& big_endian = true); bool two_verilog_ports_mergeable(const BasicPort& portA, const BasicPort& portB); @@ -96,38 +94,39 @@ bool two_verilog_ports_mergeable(const BasicPort& portA, BasicPort merge_two_verilog_ports(const BasicPort& portA, const BasicPort& portB); -std::vector combine_verilog_ports(const std::vector& ports); +std::vector combine_verilog_ports( + const std::vector& ports); -std::string generate_verilog_ports(const std::vector& merged_ports); +std::string generate_verilog_ports(const std::vector& merged_ports); -BasicPort generate_verilog_bus_port(const std::vector& input_ports, +BasicPort generate_verilog_bus_port(const std::vector& input_ports, const std::string& bus_port_name); -std::string generate_verilog_local_wire(const BasicPort& output_port, - const std::vector& input_ports); +std::string generate_verilog_local_wire( + const BasicPort& output_port, const std::vector& input_ports); -std::string generate_verilog_constant_values(const std::vector& const_values, - const bool& short_constant = true); +std::string generate_verilog_constant_values( + const std::vector& const_values, const bool& short_constant = true); -std::string generate_verilog_port_constant_values(const BasicPort& output_port, - const std::vector& const_values, - const bool& is_register = false); +std::string generate_verilog_port_constant_values( + const BasicPort& output_port, const std::vector& const_values, + const bool& is_register = false); -std::string generate_verilog_ports_constant_values(const std::vector& output_ports, - const std::vector& const_values, - const bool& is_register = false); +std::string generate_verilog_ports_constant_values( + const std::vector& output_ports, + const std::vector& const_values, const bool& is_register = false); -void print_verilog_wire_constant_values(std::fstream& fp, - const BasicPort& output_port, - const std::vector& const_values); +void print_verilog_wire_constant_values( + std::fstream& fp, const BasicPort& output_port, + const std::vector& const_values); -void print_verilog_deposit_wire_constant_values(std::fstream& fp, - const BasicPort& output_port, - const std::vector& const_values); +void print_verilog_deposit_wire_constant_values( + std::fstream& fp, const BasicPort& output_port, + const std::vector& const_values); -void print_verilog_force_wire_constant_values(std::fstream& fp, - const BasicPort& output_port, - const std::vector& const_values); +void print_verilog_force_wire_constant_values( + std::fstream& fp, const BasicPort& output_port, + const std::vector& const_values); void print_verilog_wire_connection(std::fstream& fp, const BasicPort& output_port, @@ -136,14 +135,14 @@ void print_verilog_wire_connection(std::fstream& fp, void print_verilog_register_connection(std::fstream& fp, const BasicPort& output_port, - const BasicPort& input_port, + const BasicPort& input_port, const bool& inverted); void print_verilog_buffer_instance(std::fstream& fp, - ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const ModuleId& parent_module_id, - const CircuitModelId& buffer_model, + ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const ModuleId& parent_module_id, + const CircuitModelId& buffer_model, const BasicPort& instance_input_port, const BasicPort& instance_output_port); @@ -153,58 +152,49 @@ void print_verilog_local_sram_wires(std::fstream& fp, const e_config_protocol_type sram_orgz_type, const size_t& port_size); -void print_verilog_local_config_bus(std::fstream& fp, - const std::string& prefix, - const e_config_protocol_type& sram_orgz_type, - const size_t& instance_id, - const size_t& num_conf_bits); +void print_verilog_local_config_bus( + std::fstream& fp, const std::string& prefix, + const e_config_protocol_type& sram_orgz_type, const size_t& instance_id, + const size_t& num_conf_bits); -void print_verilog_mux_config_bus(std::fstream& fp, - const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const e_config_protocol_type& sram_orgz_type, - const size_t& mux_size, - const size_t& mux_instance_id, - const size_t& num_reserved_conf_bits, - const size_t& num_conf_bits); +void print_verilog_mux_config_bus( + std::fstream& fp, const CircuitLibrary& circuit_lib, + const CircuitModelId& mux_model, const e_config_protocol_type& sram_orgz_type, + const size_t& mux_size, const size_t& mux_instance_id, + const size_t& num_reserved_conf_bits, const size_t& num_conf_bits); -void print_verilog_formal_verification_mux_sram_ports_wiring(std::fstream& fp, - const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const size_t& mux_size, - const size_t& mux_instance_id, - const size_t& num_conf_bits, - const BasicPort& fm_config_bus); +void print_verilog_formal_verification_mux_sram_ports_wiring( + std::fstream& fp, const CircuitLibrary& circuit_lib, + const CircuitModelId& mux_model, const size_t& mux_size, + const size_t& mux_instance_id, const size_t& num_conf_bits, + const BasicPort& fm_config_bus); -void print_verilog_shifted_clock_stimuli(std::fstream& fp, +void print_verilog_shifted_clock_stimuli(std::fstream& fp, const BasicPort& port, const float& initial_delay, const float& pulse_width, const size_t& initial_value); -void print_verilog_pulse_stimuli(std::fstream& fp, - const BasicPort& port, +void print_verilog_pulse_stimuli(std::fstream& fp, const BasicPort& port, const size_t& initial_value, const float& pulse_width, const size_t& flip_value); -void print_verilog_pulse_stimuli(std::fstream& fp, - const BasicPort& port, +void print_verilog_pulse_stimuli(std::fstream& fp, const BasicPort& port, const size_t& initial_value, const std::vector& pulse_widths, const std::vector& flip_values, const std::string& wait_condition); -void print_verilog_clock_stimuli(std::fstream& fp, - const BasicPort& port, +void print_verilog_clock_stimuli(std::fstream& fp, const BasicPort& port, const size_t& initial_value, const float& pulse_width, const std::string& wait_condition); -void print_verilog_netlist_include_header_file(const std::vector& netlists_to_be_included, - const char* subckt_dir, - const char* header_file_name, - const bool& include_time_stamp); +void print_verilog_netlist_include_header_file( + const std::vector& netlists_to_be_included, + const char* subckt_dir, const char* header_file_name, + const bool& include_time_stamp); } /* end namespace openfpga */ diff --git a/openfpga/src/main.cpp b/openfpga/src/main.cpp index 8b4404c84..31e389db4 100644 --- a/openfpga/src/main.cpp +++ b/openfpga/src/main.cpp @@ -1,56 +1,60 @@ /******************************************************************** - * Build the OpenFPGA shell interface + * Build the OpenFPGA shell interface *******************************************************************/ /* Header file from vtrutil library */ -#include "vtr_time.h" #include "vtr_log.h" +#include "vtr_time.h" /* Header file from libopenfpgashell library */ -#include "command_parser.h" #include "command_echo.h" +#include "command_parser.h" #include "shell.h" /* Header file from openfpga */ -#include "vpr_command.h" -#include "openfpga_setup_command.h" -#include "openfpga_verilog_command.h" -#include "openfpga_bitstream_command.h" -#include "openfpga_spice_command.h" -#include "openfpga_sdc_command.h" #include "basic_command.h" - -#include "openfpga_title.h" +#include "openfpga_bitstream_command.h" #include "openfpga_context.h" +#include "openfpga_sdc_command.h" +#include "openfpga_setup_command.h" +#include "openfpga_spice_command.h" +#include "openfpga_title.h" +#include "openfpga_verilog_command.h" +#include "vpr_command.h" /******************************************************************** * Main function to start OpenFPGA shell interface *******************************************************************/ int main(int argc, char** argv) { - /* Create the command to launch shell in different modes */ openfpga::Command start_cmd("OpenFPGA"); /* Add options to openfpga shell interface */ /* '--interactive', -i': launch the interactive mode */ - openfpga::CommandOptionId opt_interactive = start_cmd.add_option("interactive", false, "Launch OpenFPGA in interactive mode"); + openfpga::CommandOptionId opt_interactive = start_cmd.add_option( + "interactive", false, "Launch OpenFPGA in interactive mode"); start_cmd.set_option_short_name(opt_interactive, "i"); /* '--file', -f': launch the script mode */ - openfpga::CommandOptionId opt_script_mode = start_cmd.add_option("file", false, "Launch OpenFPGA in script mode"); + openfpga::CommandOptionId opt_script_mode = + start_cmd.add_option("file", false, "Launch OpenFPGA in script mode"); start_cmd.set_option_require_value(opt_script_mode, openfpga::OPT_STRING); start_cmd.set_option_short_name(opt_script_mode, "f"); - /* '--batch_execution': execute the script in batch mode. - * Will exit immediately when fatal errors occurred + /* '--batch_execution': execute the script in batch mode. + * Will exit immediately when fatal errors occurred */ - openfpga::CommandOptionId opt_batch_exec = start_cmd.add_option("batch_execution", false, "Launch OpenFPGA in batch mode when running scripts"); + openfpga::CommandOptionId opt_batch_exec = + start_cmd.add_option("batch_execution", false, + "Launch OpenFPGA in batch mode when running scripts"); start_cmd.set_option_short_name(opt_batch_exec, "batch"); /* '--version', -v': print version information */ - openfpga::CommandOptionId opt_version = start_cmd.add_option("version", false, "Show OpenFPGA version"); + openfpga::CommandOptionId opt_version = + start_cmd.add_option("version", false, "Show OpenFPGA version"); start_cmd.set_option_short_name(opt_version, "v"); /* '--help', -h': print help desk */ - openfpga::CommandOptionId opt_help = start_cmd.add_option("help", false, "Help desk"); + openfpga::CommandOptionId opt_help = + start_cmd.add_option("help", false, "Help desk"); start_cmd.set_option_short_name(opt_help, "h"); /* Create a shell object @@ -80,17 +84,18 @@ int main(int argc, char** argv) { /* Add openfpga sdc commands */ openfpga::add_openfpga_sdc_commands(shell); - /* Add basic commands: exit, help, etc. + /* Add basic commands: exit, help, etc. * Note: - * This MUST be the last command group to be added! + * This MUST be the last command group to be added! */ openfpga::add_basic_commands(shell); /* Create the data base for the shell */ OpenfpgaContext openfpga_context; - /* Parse the option, to avoid issues, we use the command name to replace the argv[0] */ - std::vector cmd_opts; + /* Parse the option, to avoid issues, we use the command name to replace the + * argv[0] */ + std::vector cmd_opts; cmd_opts.push_back(start_cmd.name()); for (int iarg = 1; iarg < argc; ++iarg) { cmd_opts.push_back(std::string(argv[iarg])); @@ -101,23 +106,23 @@ int main(int argc, char** argv) { /* Parse fail: Echo the command */ openfpga::print_command_options(start_cmd); } else { - /* Parse succeed. Branch on options */ + /* Parse succeed. Branch on options */ /* Show version */ if (true == start_cmd_context.option_enable(start_cmd, opt_version)) { print_openfpga_version_info(); return 0; } - /* Start a shell */ + /* Start a shell */ if (true == start_cmd_context.option_enable(start_cmd, opt_interactive)) { - shell.run_interactive_mode(openfpga_context); return shell.exit_code(); - } + } if (true == start_cmd_context.option_enable(start_cmd, opt_script_mode)) { - shell.run_script_mode(start_cmd_context.option_value(start_cmd, opt_script_mode).c_str(), - openfpga_context, - start_cmd_context.option_enable(start_cmd, opt_batch_exec)); + shell.run_script_mode( + start_cmd_context.option_value(start_cmd, opt_script_mode).c_str(), + openfpga_context, + start_cmd_context.option_enable(start_cmd, opt_batch_exec)); return shell.exit_code(); } /* Reach here there is something wrong, show the help desk */ @@ -125,7 +130,7 @@ int main(int argc, char** argv) { } /* Reach here, it means shell execution has critical errors. - * Return a code with fatal errors + * Return a code with fatal errors */ return 1; } diff --git a/openfpga/src/mux_lib/decoder_library.cpp b/openfpga/src/mux_lib/decoder_library.cpp index 8d6017f40..f13e08492 100644 --- a/openfpga/src/mux_lib/decoder_library.cpp +++ b/openfpga/src/mux_lib/decoder_library.cpp @@ -1,9 +1,10 @@ /*************************************************************************************** * This file includes memeber functions for data structure DecoderLibrary **************************************************************************************/ -#include "vtr_assert.h" #include "decoder_library.h" +#include "vtr_assert.h" + /* Begin namespace openfpga */ namespace openfpga { @@ -15,7 +16,7 @@ DecoderLibrary::decoder_range DecoderLibrary::decoders() const { } /*************************************************************************************** - * Public Accessors: Data query + * Public Accessors: Data query **************************************************************************************/ /* Get the size of address input of a decoder */ size_t DecoderLibrary::addr_size(const DecoderId& decoder) const { @@ -24,7 +25,7 @@ size_t DecoderLibrary::addr_size(const DecoderId& decoder) const { } /* Get the size of data output of a decoder */ -size_t DecoderLibrary::data_size(const DecoderId& decoder) const { +size_t DecoderLibrary::data_size(const DecoderId& decoder) const { VTR_ASSERT_SAFE(valid_decoder_id(decoder)); return data_sizes_[decoder]; } @@ -41,7 +42,8 @@ bool DecoderLibrary::use_data_in(const DecoderId& decoder) const { return use_data_in_[decoder]; } -/* Get the flag if a decoder includes a data_inv port which is an inversion of the regular data output port */ +/* Get the flag if a decoder includes a data_inv port which is an inversion of + * the regular data output port */ bool DecoderLibrary::use_data_inv_port(const DecoderId& decoder) const { VTR_ASSERT_SAFE(valid_decoder_id(decoder)); return use_data_inv_port_[decoder]; @@ -55,26 +57,25 @@ bool DecoderLibrary::use_readback(const DecoderId& decoder) const { /* Find a decoder to the library, with the specification. * If found, return the id of decoder. * If not found, return an invalid id of decoder - * To avoid duplicated decoders, this function should be used before adding a decoder - * Example: - * DecoderId decoder_id == decoder_lib.find_decoder(); - * if (DecoderId::INVALID() == decoder_id) { + * To avoid duplicated decoders, this function should be used before adding a + * decoder Example: DecoderId decoder_id == decoder_lib.find_decoder(); if + * (DecoderId::INVALID() == decoder_id) { * // Add decoder - * } + * } */ -DecoderId DecoderLibrary::find_decoder(const size_t& addr_size, - const size_t& data_size, - const bool& use_enable, - const bool& use_data_in, +DecoderId DecoderLibrary::find_decoder(const size_t& addr_size, + const size_t& data_size, + const bool& use_enable, + const bool& use_data_in, const bool& use_data_inv_port, const bool& use_readback) const { for (auto decoder : decoders()) { - if ( (addr_size == addr_sizes_[decoder]) - && (data_size == data_sizes_[decoder]) - && (use_enable == use_enable_[decoder]) - && (use_data_in == use_data_in_[decoder]) - && (use_data_inv_port == use_data_inv_port_[decoder]) - && (use_readback == use_readback_[decoder]) ) { + if ((addr_size == addr_sizes_[decoder]) && + (data_size == data_sizes_[decoder]) && + (use_enable == use_enable_[decoder]) && + (use_data_in == use_data_in_[decoder]) && + (use_data_inv_port == use_data_inv_port_[decoder]) && + (use_readback == use_readback_[decoder])) { return decoder; } } @@ -88,17 +89,18 @@ DecoderId DecoderLibrary::find_decoder(const size_t& addr_size, **************************************************************************************/ /* Validate ids */ bool DecoderLibrary::valid_decoder_id(const DecoderId& decoder) const { - return size_t(decoder) < decoder_ids_.size() && decoder_ids_[decoder] == decoder; + return size_t(decoder) < decoder_ids_.size() && + decoder_ids_[decoder] == decoder; } /*************************************************************************************** - * Public Mutators : Basic Operations + * Public Mutators : Basic Operations **************************************************************************************/ /* Add a decoder to the library */ -DecoderId DecoderLibrary::add_decoder(const size_t& addr_size, - const size_t& data_size, - const bool& use_enable, - const bool& use_data_in, +DecoderId DecoderLibrary::add_decoder(const size_t& addr_size, + const size_t& data_size, + const bool& use_enable, + const bool& use_data_in, const bool& use_data_inv_port, const bool& use_readback) { DecoderId decoder = DecoderId(decoder_ids_.size()); diff --git a/openfpga/src/mux_lib/decoder_library.h b/openfpga/src/mux_lib/decoder_library.h index 7340f4375..c0aa59e34 100644 --- a/openfpga/src/mux_lib/decoder_library.h +++ b/openfpga/src/mux_lib/decoder_library.h @@ -1,13 +1,13 @@ /*************************************************************************************** * This file includes key data structures to describe decoders which are used - * in FPGA fabrics + * in FPGA fabrics * A decoder is a circuit to convert a binary input to one-hot codes * The outputs are assumes to be one-hot codes (at most only one '1' exist) * Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2)) - * All the decoders are assumed to follow the port map : + * All the decoders are assumed to follow the port map : * - * Inputs - * | | ... | + * Inputs + * | | ... | * v v v * +-----------+ * / \ @@ -22,79 +22,73 @@ #ifndef DECODER_LIBRARY_H #define DECODER_LIBRARY_H -#include "vtr_vector.h" -#include "vtr_range.h" #include "decoder_library_fwd.h" +#include "vtr_range.h" +#include "vtr_vector.h" /* Begin namespace openfpga */ namespace openfpga { class DecoderLibrary { - public: /* Types and ranges */ - typedef vtr::vector::const_iterator decoder_iterator; + public: /* Types and ranges */ + typedef vtr::vector::const_iterator decoder_iterator; - typedef vtr::Range decoder_range; + typedef vtr::Range decoder_range; - public: /* Public accessors: Aggregates */ - /* Get all the decoders */ - decoder_range decoders() const; + public: /* Public accessors: Aggregates */ + /* Get all the decoders */ + decoder_range decoders() const; - public: /* Public accessors: Data query */ - /* Get the size of address input of a decoder */ - size_t addr_size(const DecoderId& decoder) const; - /* Get the size of data output of a decoder */ - size_t data_size(const DecoderId& decoder) const; - /* Get the flag if a decoder includes an ENABLE signal */ - bool use_enable(const DecoderId& decoder) const; - /* Get the flag if a decoder includes an DATA_IN signal */ - bool use_data_in(const DecoderId& decoder) const; - /* Get the flag if a decoder includes a data_inv port which is an inversion of the regular data output port */ - bool use_data_inv_port(const DecoderId& decoder) const; - /* Get the flag if a decoder includes a readback port which enables readback from configurable memories */ - bool use_readback(const DecoderId& decoder) const; - /* Find a decoder to the library, with the specification. - * If found, return the id of decoder. - * If not found, return an invalid id of decoder - * To avoid duplicated decoders, this function should be used before adding a decoder - * Example: - * DecoderId decoder_id == decoder_lib.find_decoder(); - * if (DecoderId::INVALID() == decoder_id) { - * // Add decoder - * } - */ - DecoderId find_decoder(const size_t& addr_size, - const size_t& data_size, - const bool& use_enable, - const bool& use_data_in, - const bool& use_data_inv_port, - const bool& use_readback) const; + public: /* Public accessors: Data query */ + /* Get the size of address input of a decoder */ + size_t addr_size(const DecoderId& decoder) const; + /* Get the size of data output of a decoder */ + size_t data_size(const DecoderId& decoder) const; + /* Get the flag if a decoder includes an ENABLE signal */ + bool use_enable(const DecoderId& decoder) const; + /* Get the flag if a decoder includes an DATA_IN signal */ + bool use_data_in(const DecoderId& decoder) const; + /* Get the flag if a decoder includes a data_inv port which is an inversion of + * the regular data output port */ + bool use_data_inv_port(const DecoderId& decoder) const; + /* Get the flag if a decoder includes a readback port which enables readback + * from configurable memories */ + bool use_readback(const DecoderId& decoder) const; + /* Find a decoder to the library, with the specification. + * If found, return the id of decoder. + * If not found, return an invalid id of decoder + * To avoid duplicated decoders, this function should be used before adding a + * decoder Example: DecoderId decoder_id == decoder_lib.find_decoder(); if + * (DecoderId::INVALID() == decoder_id) { + * // Add decoder + * } + */ + DecoderId find_decoder(const size_t& addr_size, const size_t& data_size, + const bool& use_enable, const bool& use_data_in, + const bool& use_data_inv_port, + const bool& use_readback) const; - public: /* Public validators */ - /* valid ids */ - bool valid_decoder_id(const DecoderId& decoder) const; + public: /* Public validators */ + /* valid ids */ + bool valid_decoder_id(const DecoderId& decoder) const; - public: /* Private mutators : basic operations */ - /* Add a decoder to the library */ - DecoderId add_decoder(const size_t& addr_size, - const size_t& data_size, - const bool& use_enable, - const bool& use_data_in, - const bool& use_data_inv_port, - const bool& use_readback); - - private: /* Internal Data */ - vtr::vector decoder_ids_; - vtr::vector addr_sizes_; - vtr::vector data_sizes_; - vtr::vector use_enable_; - vtr::vector use_data_in_; - vtr::vector use_data_inv_port_; - vtr::vector use_readback_; + public: /* Private mutators : basic operations */ + /* Add a decoder to the library */ + DecoderId add_decoder(const size_t& addr_size, const size_t& data_size, + const bool& use_enable, const bool& use_data_in, + const bool& use_data_inv_port, + const bool& use_readback); + + private: /* Internal Data */ + vtr::vector decoder_ids_; + vtr::vector addr_sizes_; + vtr::vector data_sizes_; + vtr::vector use_enable_; + vtr::vector use_data_in_; + vtr::vector use_data_inv_port_; + vtr::vector use_readback_; }; } /* End namespace openfpga*/ - - #endif - diff --git a/openfpga/src/mux_lib/decoder_library_fwd.h b/openfpga/src/mux_lib/decoder_library_fwd.h index e56a7ce82..266b259dc 100644 --- a/openfpga/src/mux_lib/decoder_library_fwd.h +++ b/openfpga/src/mux_lib/decoder_library_fwd.h @@ -1,5 +1,5 @@ /************************************************** - * This file includes only declarations for + * This file includes only declarations for * the data structures to describe decoders * Please refer to decoder_library.h for more details *************************************************/ @@ -20,4 +20,4 @@ class DecoderLibrary; } /* End namespace openfpga*/ -#endif +#endif diff --git a/openfpga/src/mux_lib/mux_graph.cpp b/openfpga/src/mux_lib/mux_graph.cpp index d8066c055..3a5fcb14a 100644 --- a/openfpga/src/mux_lib/mux_graph.cpp +++ b/openfpga/src/mux_lib/mux_graph.cpp @@ -1,19 +1,18 @@ /************************************************** - * This file includes member functions for the + * This file includes member functions for the * data structures in mux_graph.h *************************************************/ +#include #include #include #include -#include /* Headers from vtrutil library */ +#include "mux_graph.h" +#include "mux_utils.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "mux_utils.h" -#include "mux_graph.h" - /* Begin namespace openfpga */ namespace openfpga { @@ -22,29 +21,27 @@ namespace openfpga { *************************************************/ /************************************************** - * Public Constructors + * Public Constructors *************************************************/ /* Create an object based on a Circuit Model which is MUX */ -MuxGraph::MuxGraph(const CircuitLibrary& circuit_lib, +MuxGraph::MuxGraph(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, const size_t& mux_size) { /* Build the graph for a given multiplexer model */ build_mux_graph(circuit_lib, circuit_model, mux_size); -} +} /************************************************** * Private Constructors *************************************************/ /* Create an empty graph */ -MuxGraph::MuxGraph() { - return; -} +MuxGraph::MuxGraph() { return; } /************************************************** * Public Accessors : Aggregates *************************************************/ -//Accessors +// Accessors MuxGraph::node_range MuxGraph::nodes() const { return vtr::make_range(node_ids_.begin(), node_ids_.end()); } @@ -54,17 +51,18 @@ std::vector MuxGraph::non_input_nodes() const { /* Must be an valid graph */ VTR_ASSERT_SAFE(valid_mux_graph()); std::vector node_list; - + /* Build the node list, level by level */ for (size_t level = 0; level < num_node_levels(); ++level) { - for (size_t node_type = 0; node_type < size_t(NUM_MUX_NODE_TYPES); ++node_type) { + for (size_t node_type = 0; node_type < size_t(NUM_MUX_NODE_TYPES); + ++node_type) { /* Bypass any nodes which are not OUTPUT and INTERNAL */ - if (size_t(MUX_INPUT_NODE) == node_type) { + if (size_t(MUX_INPUT_NODE) == node_type) { continue; } - /* Reach here, this is either an OUTPUT or INTERNAL node */ - for (auto node : node_lookup_[level][node_type]) { - node_list.push_back(node); + /* Reach here, this is either an OUTPUT or INTERNAL node */ + for (auto node : node_lookup_[level][node_type]) { + node_list.push_back(node); } } } @@ -114,12 +112,14 @@ size_t MuxGraph::num_inputs() const { /* Return the node ids of all the inputs of the multiplexer */ std::vector MuxGraph::inputs() const { - std::vector input_nodes; + std::vector input_nodes; /* need to check if the graph is valid or not */ VTR_ASSERT_SAFE(valid_mux_graph()); /* Add the input nodes in each level */ for (auto node_per_level : node_lookup_) { - input_nodes.insert(input_nodes.end(), node_per_level[MUX_INPUT_NODE].begin(), node_per_level[MUX_INPUT_NODE].end()); + input_nodes.insert(input_nodes.end(), + node_per_level[MUX_INPUT_NODE].begin(), + node_per_level[MUX_INPUT_NODE].end()); } return input_nodes; } @@ -138,18 +138,21 @@ size_t MuxGraph::num_outputs() const { /* Return the node ids of all the outputs of the multiplexer */ std::vector MuxGraph::outputs() const { - std::vector output_nodes; + std::vector output_nodes; /* need to check if the graph is valid or not */ VTR_ASSERT_SAFE(valid_mux_graph()); /* Add the output nodes in each level */ for (auto node_per_level : node_lookup_) { - output_nodes.insert(output_nodes.end(), node_per_level[MUX_OUTPUT_NODE].begin(), node_per_level[MUX_OUTPUT_NODE].end()); + output_nodes.insert(output_nodes.end(), + node_per_level[MUX_OUTPUT_NODE].begin(), + node_per_level[MUX_OUTPUT_NODE].end()); } return output_nodes; } /* Find the edge between two MUX nodes */ -std::vector MuxGraph::find_edges(const MuxNodeId& from_node, const MuxNodeId& to_node) const { +std::vector MuxGraph::find_edges(const MuxNodeId& from_node, + const MuxNodeId& to_node) const { std::vector edges; VTR_ASSERT(valid_node_id(from_node)); @@ -171,22 +174,23 @@ std::vector MuxGraph::find_edges(const MuxNodeId& from_node, const Mu size_t MuxGraph::num_levels() const { /* need to check if the graph is valid or not */ VTR_ASSERT_SAFE(valid_mux_graph()); - /* The num_levels by definition excludes the level for outputs, so a deduection is applied */ - return node_lookup_.size() - 1; + /* The num_levels by definition excludes the level for outputs, so a + * deduection is applied */ + return node_lookup_.size() - 1; } /* Find the actual number of levels in the MUX graph */ size_t MuxGraph::num_node_levels() const { /* need to check if the graph is valid or not */ VTR_ASSERT_SAFE(valid_mux_graph()); - return node_lookup_.size(); + return node_lookup_.size(); } /* Find the number of configuration memories in the MUX graph */ size_t MuxGraph::num_memory_bits() const { /* need to check if the graph is valid or not */ VTR_ASSERT_SAFE(valid_mux_graph()); - return mem_ids_.size(); + return mem_ids_.size(); } /* Find the number of SRAMs at a level in the MUX graph */ @@ -194,7 +198,7 @@ size_t MuxGraph::num_memory_bits_at_level(const size_t& level) const { /* need to check if the graph is valid or not */ VTR_ASSERT_SAFE(valid_level(level)); VTR_ASSERT_SAFE(valid_mux_graph()); - return mem_lookup_[level].size(); + return mem_lookup_[level].size(); } /* Return memory id at level */ @@ -202,7 +206,7 @@ std::vector MuxGraph::memories_at_level(const size_t& level) const { /* need to check if the graph is valid or not */ VTR_ASSERT_SAFE(valid_level(level)); VTR_ASSERT_SAFE(valid_mux_graph()); - return mem_lookup_[level]; + return mem_lookup_[level]; } /* Find the number of nodes at a given level in the MUX graph */ @@ -210,26 +214,27 @@ size_t MuxGraph::num_nodes_at_level(const size_t& level) const { /* validate the level numbers */ VTR_ASSERT_SAFE(valid_level(level)); VTR_ASSERT_SAFE(valid_mux_graph()); - + size_t num_nodes = 0; - for (size_t node_type = 0; node_type < size_t(NUM_MUX_NODE_TYPES); ++node_type) { - num_nodes += node_lookup_[level][node_type].size(); + for (size_t node_type = 0; node_type < size_t(NUM_MUX_NODE_TYPES); + ++node_type) { + num_nodes += node_lookup_[level][node_type].size(); } - return num_nodes; + return num_nodes; } /* Find the level of a node */ size_t MuxGraph::node_level(const MuxNodeId& node) const { /* validate the node */ VTR_ASSERT(valid_node_id(node)); - return node_levels_[node]; + return node_levels_[node]; } /* Find the index of a node at its level */ size_t MuxGraph::node_index_at_level(const MuxNodeId& node) const { /* validate the node */ VTR_ASSERT(valid_node_id(node)); - return node_ids_at_level_[node]; + return node_ids_at_level_[node]; } /* Find the input edges for a node */ @@ -263,11 +268,12 @@ bool MuxGraph::is_edge_use_inv_mem(const MuxEdgeId& edge) const { /* Find the sizes of each branch of a MUX */ std::vector MuxGraph::branch_sizes() const { std::vector branch; - /* Visit each internal nodes/output nodes and find the the number of incoming edges */ - for (auto node : node_ids_ ) { + /* Visit each internal nodes/output nodes and find the the number of incoming + * edges */ + for (auto node : node_ids_) { /* Bypass input nodes */ - if ( (MUX_OUTPUT_NODE != node_types_[node]) - && (MUX_INTERNAL_NODE != node_types_[node]) ) { + if ((MUX_OUTPUT_NODE != node_types_[node]) && + (MUX_INTERNAL_NODE != node_types_[node])) { continue; } @@ -276,10 +282,12 @@ std::vector MuxGraph::branch_sizes() const { /* make sure the branch size is valid */ VTR_ASSERT_SAFE(valid_mux_implementation_num_inputs(branch_size)); - /* Nodes with the same number of incoming edges, indicate the same size of branch circuit */ - std::vector::iterator it; + /* Nodes with the same number of incoming edges, indicate the same size of + * branch circuit */ + std::vector::iterator it; it = std::find(branch.begin(), branch.end(), branch_size); - /* if already exists a branch with the same size, skip updating the vector */ + /* if already exists a branch with the same size, skip updating the vector + */ if (it != branch.end()) { continue; } @@ -295,15 +303,16 @@ std::vector MuxGraph::branch_sizes() const { /* Find the sizes of each branch of a MUX at a given level */ std::vector MuxGraph::branch_sizes(const size_t& level) const { std::vector branch; - /* Visit each internal nodes/output nodes and find the the number of incoming edges */ - for (auto node : node_ids_ ) { + /* Visit each internal nodes/output nodes and find the the number of incoming + * edges */ + for (auto node : node_ids_) { /* Bypass input nodes */ - if ( (MUX_OUTPUT_NODE != node_types_[node]) - && (MUX_INTERNAL_NODE != node_types_[node]) ) { + if ((MUX_OUTPUT_NODE != node_types_[node]) && + (MUX_INTERNAL_NODE != node_types_[node])) { continue; } /* Bypass nodes that is not at the level */ - if ( level != node_levels_[node]) { + if (level != node_levels_[node]) { continue; } @@ -312,10 +321,12 @@ std::vector MuxGraph::branch_sizes(const size_t& level) const { /* make sure the branch size is valid */ VTR_ASSERT_SAFE(valid_mux_implementation_num_inputs(branch_size)); - /* Nodes with the same number of incoming edges, indicate the same size of branch circuit */ - std::vector::iterator it; + /* Nodes with the same number of incoming edges, indicate the same size of + * branch circuit */ + std::vector::iterator it; it = std::find(branch.begin(), branch.end(), branch_size); - /* if already exists a branch with the same size, skip updating the vector */ + /* if already exists a branch with the same size, skip updating the vector + */ if (it != branch.end()) { continue; } @@ -328,9 +339,8 @@ std::vector MuxGraph::branch_sizes(const size_t& level) const { return branch; } - /* Build a subgraph from the given node - * The strategy is very simple, we just + * The strategy is very simple, we just * extract a 1-level graph from here */ MuxGraph MuxGraph::subgraph(const MuxNodeId& root_node) const { @@ -349,7 +359,7 @@ MuxGraph MuxGraph::subgraph(const MuxNodeId& root_node) const { /* Add output nodes to subgraph */ MuxNodeId to_node_subgraph = mux_graph.add_node(MUX_OUTPUT_NODE); mux_graph.node_levels_[to_node_subgraph] = 1; - mux_graph.node_ids_at_level_[to_node_subgraph] = 0; + mux_graph.node_ids_at_level_[to_node_subgraph] = 0; mux_graph.node_output_ids_[to_node_subgraph] = MuxOutputId(0); /* Update the node-to-node map */ node2node_map[root_node] = to_node_subgraph; @@ -363,19 +373,20 @@ MuxGraph MuxGraph::subgraph(const MuxNodeId& root_node) const { MuxNodeId from_node_subgraph = mux_graph.add_node(MUX_INPUT_NODE); /* Configure the nodes */ mux_graph.node_levels_[from_node_subgraph] = 0; - mux_graph.node_ids_at_level_[from_node_subgraph] = input_cnt; + mux_graph.node_ids_at_level_[from_node_subgraph] = input_cnt; mux_graph.node_input_ids_[from_node_subgraph] = MuxInputId(input_cnt); input_cnt++; /* Update the node-to-node map */ node2node_map[from_node_origin] = from_node_subgraph; /* Add edges */ - MuxEdgeId edge_subgraph = mux_graph.add_edge(node2node_map[from_node_origin], node2node_map[root_node]); - edge2edge_map[edge_origin] = edge_subgraph; + MuxEdgeId edge_subgraph = mux_graph.add_edge( + node2node_map[from_node_origin], node2node_map[root_node]); + edge2edge_map[edge_origin] = edge_subgraph; /* Configure edges */ mux_graph.edge_models_[edge_subgraph] = this->edge_models_[edge_origin]; mux_graph.edge_inv_mem_[edge_subgraph] = this->edge_inv_mem_[edge_origin]; - } + } /* A map to record mem-to-mem mapping from origin graph to subgraph */ std::map mem2mem_map; @@ -389,7 +400,8 @@ MuxGraph MuxGraph::subgraph(const MuxNodeId& root_node) const { /* Found, we skip mem addition. But make sure we have a valid one */ VTR_ASSERT_SAFE(MuxMemId::INVALID() != mem2mem_map[mem_origin]); /* configure the edge */ - mux_graph.edge_mem_ids_[edge2edge_map[edge_origin]] = mem2mem_map[mem_origin]; + mux_graph.edge_mem_ids_[edge2edge_map[edge_origin]] = + mem2mem_map[mem_origin]; continue; } /* Not found, we add a memory bit and record in the mem-to-mem map */ @@ -404,26 +416,28 @@ MuxGraph MuxGraph::subgraph(const MuxNodeId& root_node) const { mux_graph.build_node_lookup(); mux_graph.build_mem_lookup(); - return mux_graph; + return mux_graph; } /* Generate MUX graphs for its branches * Similar to the branch_sizes() method, - * we search all the internal nodes and - * find out what are the input sizes of - * the branches. - * Then we extract unique subgraphs and return + * we search all the internal nodes and + * find out what are the input sizes of + * the branches. + * Then we extract unique subgraphs and return */ std::vector MuxGraph::build_mux_branch_graphs() const { - std::map branch_done; /* A map showing the status of graph generation */ + std::map + branch_done; /* A map showing the status of graph generation */ std::vector branch_graphs; - /* Visit each internal nodes/output nodes and find the the number of incoming edges */ - for (auto node : node_ids_ ) { + /* Visit each internal nodes/output nodes and find the the number of incoming + * edges */ + for (auto node : node_ids_) { /* Bypass input nodes */ - if ( (MUX_OUTPUT_NODE != node_types_[node]) - && (MUX_INTERNAL_NODE != node_types_[node]) ) { + if ((MUX_OUTPUT_NODE != node_types_[node]) && + (MUX_INTERNAL_NODE != node_types_[node])) { continue; } @@ -448,7 +462,7 @@ std::vector MuxGraph::build_mux_branch_graphs() const { } return branch_graphs; -} +} /* Get the input id of a given node */ MuxInputId MuxGraph::input_id(const MuxNodeId& node_id) const { @@ -488,10 +502,10 @@ MuxNodeId MuxGraph::node_id(const MuxInputId& input_id) const { for (const auto& lvl : node_lookup_) { for (const auto& cand_node : lvl[MUX_INPUT_NODE]) { if (input_id == node_input_ids_[cand_node]) { - return cand_node; + return cand_node; } } - } + } return MuxNodeId::INVALID(); } @@ -502,29 +516,29 @@ MuxNodeId MuxGraph::node_id(const MuxOutputId& output_id) const { for (const auto& lvl : node_lookup_) { for (const auto& cand_node : lvl[MUX_OUTPUT_NODE]) { if (output_id == node_output_ids_[cand_node]) { - return cand_node; + return cand_node; } } - } + } return MuxNodeId::INVALID(); } - /* Get the node id w.r.t. the node level and node_index at the level - * Return an invalid value if not found + * Return an invalid value if not found */ -MuxNodeId MuxGraph::node_id(const size_t& node_level, const size_t& node_index_at_level) const { +MuxNodeId MuxGraph::node_id(const size_t& node_level, + const size_t& node_index_at_level) const { /* Ensure we have a valid node_look-up */ VTR_ASSERT_SAFE(valid_node_lookup()); - MuxNodeId ret_node = MuxNodeId::INVALID(); + MuxNodeId ret_node = MuxNodeId::INVALID(); /* Search in the fast look up */ if (node_level >= node_lookup_.size()) { - return ret_node; + return ret_node; } - + size_t node_cnt = 0; /* Node level is valid, search in the node list */ for (const auto& nodes_by_type : node_lookup_[node_level]) { @@ -532,10 +546,10 @@ MuxNodeId MuxGraph::node_id(const size_t& node_level, const size_t& node_index_a for (const auto& node : nodes_by_type) { if (node_index_at_level != node_ids_at_level_[node]) { continue; - } + } /* Find the node, assign value and update the counter */ ret_node = node; - node_cnt++; + node_cnt++; } } @@ -546,9 +560,9 @@ MuxNodeId MuxGraph::node_id(const size_t& node_level, const size_t& node_index_a } /* Decode memory bits based on an input id and an output id */ -vtr::vector MuxGraph::decode_memory_bits(const MuxInputId& input_id, - const MuxOutputId& output_id) const { - /* initialize the memory bits: TODO: support default value */ +vtr::vector MuxGraph::decode_memory_bits( + const MuxInputId& input_id, const MuxOutputId& output_id) const { + /* initialize the memory bits: TODO: support default value */ vtr::vector mem_bits(mem_ids_.size(), false); /* valid the input and output */ @@ -556,37 +570,37 @@ vtr::vector MuxGraph::decode_memory_bits(const MuxInputId& input VTR_ASSERT_SAFE(valid_output_id(output_id)); /* Mark all the nodes as not visited */ - vtr::vector visited(nodes().size(), false); + vtr::vector visited(nodes().size(), false); - /* Create a queue for Breadth-First Search */ - std::list queue; + /* Create a queue for Breadth-First Search */ + std::list queue; /* Mark the input node as visited and enqueue it */ - visited[node_id(input_id)] = true; - queue.push_back(node_id(input_id)); + visited[node_id(input_id)] = true; + queue.push_back(node_id(input_id)); /* Create a flag to indicate if the route is success or not */ bool route_success = false; - while(!queue.empty()) { - /* Dequeue a mux node from queue, + while (!queue.empty()) { + /* Dequeue a mux node from queue, * we will walk through all the fan-in of this node in this loop */ - MuxNodeId node_to_expand = queue.front(); - queue.pop_front(); - /* Get all fan-in nodes of the dequeued node - * If the node has not been visited, + MuxNodeId node_to_expand = queue.front(); + queue.pop_front(); + /* Get all fan-in nodes of the dequeued node + * If the node has not been visited, * then mark it visited and enqueue it */ - VTR_ASSERT_SAFE (1 == node_out_edges_[node_to_expand].size()); + VTR_ASSERT_SAFE(1 == node_out_edges_[node_to_expand].size()); MuxEdgeId edge = node_out_edges_[node_to_expand][0]; - /* Configure the mem bits: - * if inv_mem is enabled, it means 0 to enable this edge + /* Configure the mem bits: + * if inv_mem is enabled, it means 0 to enable this edge * otherwise, it is 1 to enable this edge */ MuxMemId mem = edge_mem_ids_[edge]; - VTR_ASSERT_SAFE (valid_mem_id(mem)); + VTR_ASSERT_SAFE(valid_mem_id(mem)); if (true == edge_inv_mem_[edge]) { mem_bits[mem] = false; } else { @@ -594,10 +608,10 @@ vtr::vector MuxGraph::decode_memory_bits(const MuxInputId& input } /* each edge must have 1 fan-out */ - VTR_ASSERT_SAFE (1 == edge_sink_nodes_[edge].size()); + VTR_ASSERT_SAFE(1 == edge_sink_nodes_[edge].size()); /* Get the fan-out node */ - MuxNodeId next_node = edge_sink_nodes_[edge][0]; + MuxNodeId next_node = edge_sink_nodes_[edge][0]; /* If next node is the output node we want, we can finish here */ if (next_node == node_id(output_id)) { @@ -606,9 +620,9 @@ vtr::vector MuxGraph::decode_memory_bits(const MuxInputId& input } /* Add next node to the queue if not visited yet */ - if (false == visited[next_node]) { - visited[next_node] = true; - queue.push_back(next_node); + if (false == visited[next_node]) { + visited[next_node] = true; + queue.push_back(next_node); } } @@ -618,13 +632,14 @@ vtr::vector MuxGraph::decode_memory_bits(const MuxInputId& input return mem_bits; } -/* Find the input node that the memory bits will route an output node to +/* Find the input node that the memory bits will route an output node to * This function backward propagate from the output node to an input node - * assuming the memory bits are applied + * assuming the memory bits are applied */ -MuxInputId MuxGraph::find_input_node_driven_by_output_node(const std::map& memory_bits, - const MuxOutputId& output_id) const { - /* Ensure that the memory bits fit the size of memory bits in this MUX */ +MuxInputId MuxGraph::find_input_node_driven_by_output_node( + const std::map& memory_bits, + const MuxOutputId& output_id) const { + /* Ensure that the memory bits fit the size of memory bits in this MUX */ VTR_ASSERT(memory_bits.size() == mem_ids_.size()); /* valid the output */ @@ -632,37 +647,37 @@ MuxInputId MuxGraph::find_input_node_driven_by_output_node(const std::map visited(nodes().size(), false); + vtr::vector visited(nodes().size(), false); - /* Create a queue for Breadth-First Search */ - std::list queue; + /* Create a queue for Breadth-First Search */ + std::list queue; /* Mark the output node as visited and enqueue it */ - visited[node_id(output_id)] = true; - queue.push_back(node_id(output_id)); + visited[node_id(output_id)] = true; + queue.push_back(node_id(output_id)); /* Record the destination input id */ MuxInputId des_input_id = MuxInputId::INVALID(); - while(!queue.empty()) { - /* Dequeue a mux node from queue, + while (!queue.empty()) { + /* Dequeue a mux node from queue, * we will walk through all the fan-in of this node in this loop */ - MuxNodeId node_to_expand = queue.front(); - queue.pop_front(); - /* Get all fan-in nodes of the dequeued node - * If the node has not been visited, + MuxNodeId node_to_expand = queue.front(); + queue.pop_front(); + /* Get all fan-in nodes of the dequeued node + * If the node has not been visited, * then mark it visited and enqueue it */ - MuxEdgeId next_edge = MuxEdgeId::INVALID(); + MuxEdgeId next_edge = MuxEdgeId::INVALID(); for (const MuxEdgeId& edge : node_in_edges_[node_to_expand]) { - /* Configure the mem bits and find the edge that will propagate the signal - * if inv_mem is enabled, it means false to enable this edge + /* Configure the mem bits and find the edge that will propagate the signal + * if inv_mem is enabled, it means false to enable this edge * otherwise, it is true to enable this edge */ MuxMemId mem = edge_mem_ids_[edge]; - VTR_ASSERT_SAFE (valid_mem_id(mem)); - if (edge_inv_mem_[edge] == !memory_bits.at(mem)) { + VTR_ASSERT_SAFE(valid_mem_id(mem)); + if (edge_inv_mem_[edge] == !memory_bits.at(mem)) { next_edge = edge; break; } @@ -671,10 +686,10 @@ MuxInputId MuxGraph::find_input_node_driven_by_output_node(const std::map+ * | * input_node --->| @@ -794,9 +810,9 @@ void MuxGraph::set_edge_mem_id(const MuxEdgeId& edge, const MuxMemId& mem) { * | | * input_node --->| | * |--->+ - * ... | - * | - * input_node --->+ + * ... | + * | + * input_node --->+ * * tree-like multiplexer graph will look like: * -------------------------------------------- @@ -811,11 +827,12 @@ void MuxGraph::set_edge_mem_id(const MuxEdgeId& edge, const MuxMemId& mem) { * |---> ... * input_node --->+ | * |--->+ - * input_node --->+ + * input_node --->+ * */ -void MuxGraph::build_multilevel_mux_graph(const size_t& mux_size, - const size_t& num_levels, const size_t& num_inputs_per_branch, +void MuxGraph::build_multilevel_mux_graph(const size_t& mux_size, + const size_t& num_levels, + const size_t& num_inputs_per_branch, const CircuitModelId& pgl_model) { /* Make sure mux_size for each branch is valid */ VTR_ASSERT(valid_mux_implementation_num_inputs(num_inputs_per_branch)); @@ -823,8 +840,8 @@ void MuxGraph::build_multilevel_mux_graph(const size_t& mux_size, /* In regular cases, there is 1 mem bit for each input of a branch */ size_t num_mems_per_level = num_inputs_per_branch; /* For 2-input branch, only 1 mem bit is needed for each level! */ - if (2 == num_inputs_per_branch) { - num_mems_per_level = 1; + if (2 == num_inputs_per_branch) { + num_mems_per_level = 1; } /* Number of memory bits is definite, add them */ for (size_t ilvl = 0; ilvl < num_levels; ++ilvl) { @@ -838,85 +855,93 @@ void MuxGraph::build_multilevel_mux_graph(const size_t& mux_size, * Only used for building the graph * it sorts the nodes by levels and ids at each level */ - std::vector> node_lookup; /* [num_levels][num_nodes_per_level] */ - node_lookup.resize(num_levels + 1); + std::vector> + node_lookup; /* [num_levels][num_nodes_per_level] */ + node_lookup.resize(num_levels + 1); /* Number of outputs is definite, add and configure */ MuxNodeId output_node = add_node(MUX_OUTPUT_NODE); - node_levels_[output_node] = num_levels; - node_ids_at_level_[output_node] = 0; - node_output_ids_[output_node] = MuxOutputId(0); + node_levels_[output_node] = num_levels; + node_ids_at_level_[output_node] = 0; + node_output_ids_[output_node] = MuxOutputId(0); /* Update node lookup */ node_lookup[num_levels].push_back(output_node); /* keep a list of node ids which can be candidates for input nodes */ std::vector input_node_ids; - - /* Add internal nodes level by level, + + /* Add internal nodes level by level, * we start from the last level, following a strategy like tree growing */ - for (size_t lvl = num_levels - 1; ; --lvl) { - /* Expand from the existing nodes - * Last level should expand from output_node + for (size_t lvl = num_levels - 1;; --lvl) { + /* Expand from the existing nodes + * Last level should expand from output_node * Other levels will expand from internal nodes! */ - size_t node_cnt_per_level = 0; /* A counter to record node indices at each level */ + size_t node_cnt_per_level = + 0; /* A counter to record node indices at each level */ for (MuxNodeId seed_node : node_lookup[lvl + 1]) { - /* Add a new node and connect to seed_node, until we reach the num_inputs_per_branch */ + /* Add a new node and connect to seed_node, until we reach the + * num_inputs_per_branch */ for (size_t i = 0; i < num_inputs_per_branch; ++i) { - /* We deposite a type of INTERNAL_NODE, - * later it will be configured to INPUT if it is in the input list + /* We deposite a type of INTERNAL_NODE, + * later it will be configured to INPUT if it is in the input list */ - MuxNodeId expand_node = add_node(MUX_INTERNAL_NODE); + MuxNodeId expand_node = add_node(MUX_INTERNAL_NODE); /* Node level is deterministic */ - node_levels_[expand_node] = lvl; - node_ids_at_level_[expand_node] = node_cnt_per_level; + node_levels_[expand_node] = lvl; + node_ids_at_level_[expand_node] = node_cnt_per_level; /* update level node counter */ node_cnt_per_level++; - + /* Create an edge and connect the two nodes */ - MuxEdgeId edge = add_edge(expand_node, seed_node); + MuxEdgeId edge = add_edge(expand_node, seed_node); /* Configure the edge */ edge_models_[edge] = pgl_model; - /* Memory id depends on the level and offset in the current branch - * if number of inputs per branch is 2, it indicates a tree-like multiplexer, - * every two edges will share one memory bit - * otherwise, each edge corresponds to a memory bit + /* Memory id depends on the level and offset in the current branch + * if number of inputs per branch is 2, it indicates a tree-like + * multiplexer, every two edges will share one memory bit otherwise, + * each edge corresponds to a memory bit */ - - if ( 2 == num_inputs_per_branch) { + + if (2 == num_inputs_per_branch) { MuxMemId mem_id = MuxMemId(lvl); set_edge_mem_id(edge, mem_id); - /* If this is a second edge in the branch, we will assign it to an inverted edge */ + /* If this is a second edge in the branch, we will assign it to an + * inverted edge */ if (0 != i % num_inputs_per_branch) { edge_inv_mem_[edge] = true; } } else { - MuxMemId mem_id = MuxMemId( lvl * num_inputs_per_branch + i ); + MuxMemId mem_id = MuxMemId(lvl * num_inputs_per_branch + i); set_edge_mem_id(edge, mem_id); } /* Update node lookup */ node_lookup[lvl].push_back(expand_node); - /* Push the node to input list, and then remove the seed_node from the list */ + /* Push the node to input list, and then remove the seed_node from the + * list */ input_node_ids.push_back(expand_node); /* Remove the node if the seed node is the list */ - std::vector::iterator it = find(input_node_ids.begin(), input_node_ids.end(), seed_node); + std::vector::iterator it = + find(input_node_ids.begin(), input_node_ids.end(), seed_node); if (it != input_node_ids.end()) { input_node_ids.erase(it); } - /* Check the number of input nodes, if already meet the demand, we can finish here */ + /* Check the number of input nodes, if already meet the demand, we can + * finish here */ if (mux_size != input_node_ids.size()) { continue; /* We need more inputs, keep looping */ } - /* The graph is done, we configure the input nodes and then we can return */ + /* The graph is done, we configure the input nodes and then we can + * return */ /* We must be in level 0 !*/ - VTR_ASSERT( 0 == lvl ) ; + VTR_ASSERT(0 == lvl); for (MuxNodeId input_node : input_node_ids) { node_types_[input_node] = MUX_INPUT_NODE; } @@ -926,7 +951,7 @@ void MuxGraph::build_multilevel_mux_graph(const size_t& mux_size, for (auto lvl_nodes : node_lookup) { for (MuxNodeId cand_node : lvl_nodes) { if (MUX_INPUT_NODE != node_types_[cand_node]) { - continue; + continue; } /* Update the input node ids */ node_input_ids_[cand_node] = MuxInputId(input_cnt); @@ -940,13 +965,13 @@ void MuxGraph::build_multilevel_mux_graph(const size_t& mux_size, return; } } - } + } /* Finish building the graph for a multi-level multiplexer */ -} +} -/* Build the graph for a given one-level multiplexer implementation +/* Build the graph for a given one-level multiplexer implementation * a N:1 one-level MUX - * + * * input_node --->+ * | * input_node --->| @@ -955,53 +980,54 @@ void MuxGraph::build_multilevel_mux_graph(const size_t& mux_size, * | * input_node --->+ */ -void MuxGraph::build_onelevel_mux_graph(const size_t& mux_size, +void MuxGraph::build_onelevel_mux_graph(const size_t& mux_size, const CircuitModelId& pgl_model) { /* Make sure mux_size is valid */ VTR_ASSERT(valid_mux_implementation_num_inputs(mux_size)); - /* We definitely know how many nodes we need, + /* We definitely know how many nodes we need, * N inputs, 1 output and 0 internal nodes */ MuxNodeId output_node = add_node(MUX_OUTPUT_NODE); - node_levels_[output_node] = 1; - node_ids_at_level_[output_node] = 0; - node_output_ids_[output_node] = MuxOutputId(0); + node_levels_[output_node] = 1; + node_ids_at_level_[output_node] = 0; + node_output_ids_[output_node] = MuxOutputId(0); for (size_t i = 0; i < mux_size; ++i) { MuxNodeId input_node = add_node(MUX_INPUT_NODE); /* All the node belong to level 0 (we have only 1 level) */ node_input_ids_[input_node] = MuxInputId(i); - node_levels_[input_node] = 0; - node_ids_at_level_[input_node] = i; + node_levels_[input_node] = 0; + node_ids_at_level_[input_node] = i; - /* We definitely know how many edges we need, + /* We definitely know how many edges we need, * the same as mux_size, add a edge connecting two nodes */ - MuxEdgeId edge = add_edge(input_node, output_node); + MuxEdgeId edge = add_edge(input_node, output_node); /* Configure the edge */ edge_models_[edge] = pgl_model; /* Create a memory bit*/ - MuxMemId mem = add_mem(); + MuxMemId mem = add_mem(); mem_levels_[mem] = 0; /* Link the edge to a memory bit */ set_edge_mem_id(edge, mem); } /* Finish building the graph for a one-level multiplexer */ -} +} /* Convert some internal nodes to be additional outputs * according to the fracturable LUT port definition - * We will iterate over each output port of a circuit model - * and find the frac_level and output_mask + * We will iterate over each output port of a circuit model + * and find the frac_level and output_mask * Then, the internal nodes at the frac_level will be converted * to output nodes with a given output_mask */ -void MuxGraph::add_fracturable_outputs(const CircuitLibrary& circuit_lib, +void MuxGraph::add_fracturable_outputs(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model) { /* Iterate over output ports */ - for (const auto& port : circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, false)) { + for (const auto& port : circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, false)) { /* Get the fracturable_level */ size_t frac_level = circuit_lib.port_lut_frac_level(port); /* Bypass invalid frac_level */ @@ -1011,19 +1037,20 @@ void MuxGraph::add_fracturable_outputs(const CircuitLibrary& circuit_lib, /* Iterate over output masks */ for (const auto& output_idx : circuit_lib.port_lut_output_mask(port)) { size_t num_matched_nodes = 0; - /* Iterate over node and find the internal nodes, which match the frac_level and output_idx */ + /* Iterate over node and find the internal nodes, which match the + * frac_level and output_idx */ for (const auto& node : node_lookup_[frac_level][MUX_INTERNAL_NODE]) { if (node_ids_at_level_[node] != output_idx) { /* Bypass condition */ continue; } /* Reach here, this is the node we want - * Convert it to output nodes and update the counter + * Convert it to output nodes and update the counter */ node_types_[node] = MUX_OUTPUT_NODE; - node_output_ids_[node] = MuxOutputId(num_outputs()); + node_output_ids_[node] = MuxOutputId(num_outputs()); num_matched_nodes++; - } + } /* Either find 1 or 0 matched nodes */ if (0 != num_matched_nodes) { /* We should find only one node that matches! */ @@ -1038,64 +1065,74 @@ void MuxGraph::add_fracturable_outputs(const CircuitLibrary& circuit_lib, /* Bypass condition */ continue; } - /* Reach here, this is the node we want - * Just update the counter + /* Reach here, this is the node we want + * Just update the counter */ num_matched_nodes++; } /* We should find only one node that matches! */ VTR_ASSERT(1 == num_matched_nodes); - } + } } } /* Build the graph for a given multiplexer model */ -void MuxGraph::build_mux_graph(const CircuitLibrary& circuit_lib, +void MuxGraph::build_mux_graph(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, const size_t& mux_size) { /* Make sure this model is a MUX */ - VTR_ASSERT((CIRCUIT_MODEL_MUX == circuit_lib.model_type(circuit_model)) - || (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)) ); + VTR_ASSERT((CIRCUIT_MODEL_MUX == circuit_lib.model_type(circuit_model)) || + (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model))); /* Make sure mux_size is valid */ VTR_ASSERT(valid_mux_implementation_num_inputs(mux_size)); - size_t impl_mux_size = find_mux_implementation_num_inputs(circuit_lib, circuit_model, mux_size); + size_t impl_mux_size = + find_mux_implementation_num_inputs(circuit_lib, circuit_model, mux_size); - /* Depends on the mux size, the implemented multiplexer structure may change! */ - enum e_circuit_model_structure impl_structure = find_mux_implementation_structure(circuit_lib, circuit_model, impl_mux_size); + /* Depends on the mux size, the implemented multiplexer structure may change! + */ + enum e_circuit_model_structure impl_structure = + find_mux_implementation_structure(circuit_lib, circuit_model, + impl_mux_size); - /* Branch on multiplexer structures, leading to different building strategies */ + /* Branch on multiplexer structures, leading to different building strategies + */ switch (impl_structure) { - case CIRCUIT_MODEL_STRUCTURE_TREE: { - /* Find the number of levels */ - size_t num_levels = find_treelike_mux_num_levels(impl_mux_size); + case CIRCUIT_MODEL_STRUCTURE_TREE: { + /* Find the number of levels */ + size_t num_levels = find_treelike_mux_num_levels(impl_mux_size); - /* Find the number of inputs per branch, this is not final */ - size_t num_inputs_per_branch = 2; + /* Find the number of inputs per branch, this is not final */ + size_t num_inputs_per_branch = 2; - /* Build a multilevel mux graph */ - build_multilevel_mux_graph(impl_mux_size, num_levels, num_inputs_per_branch, circuit_lib.pass_gate_logic_model(circuit_model)); - break; - } - case CIRCUIT_MODEL_STRUCTURE_ONELEVEL: { - build_onelevel_mux_graph(impl_mux_size, circuit_lib.pass_gate_logic_model(circuit_model)); - break; - } - case CIRCUIT_MODEL_STRUCTURE_MULTILEVEL: { - /* Find the number of inputs per branch, this is not final */ - size_t num_inputs_per_branch = find_multilevel_mux_branch_num_inputs(impl_mux_size, circuit_lib.mux_num_levels(circuit_model)); + /* Build a multilevel mux graph */ + build_multilevel_mux_graph( + impl_mux_size, num_levels, num_inputs_per_branch, + circuit_lib.pass_gate_logic_model(circuit_model)); + break; + } + case CIRCUIT_MODEL_STRUCTURE_ONELEVEL: { + build_onelevel_mux_graph( + impl_mux_size, circuit_lib.pass_gate_logic_model(circuit_model)); + break; + } + case CIRCUIT_MODEL_STRUCTURE_MULTILEVEL: { + /* Find the number of inputs per branch, this is not final */ + size_t num_inputs_per_branch = find_multilevel_mux_branch_num_inputs( + impl_mux_size, circuit_lib.mux_num_levels(circuit_model)); - /* Build a multilevel mux graph */ - build_multilevel_mux_graph(impl_mux_size, circuit_lib.mux_num_levels(circuit_model), - num_inputs_per_branch, - circuit_lib.pass_gate_logic_model(circuit_model)); - break; - } - default: - VTR_LOG_ERROR("Invalid multiplexer structure for circuit model '%s'!\n", - circuit_lib.model_name(circuit_model).c_str()); - exit(1); + /* Build a multilevel mux graph */ + build_multilevel_mux_graph( + impl_mux_size, circuit_lib.mux_num_levels(circuit_model), + num_inputs_per_branch, + circuit_lib.pass_gate_logic_model(circuit_model)); + break; + } + default: + VTR_LOG_ERROR("Invalid multiplexer structure for circuit model '%s'!\n", + circuit_lib.model_name(circuit_model).c_str()); + exit(1); } /* Since the graph is finalized, it is time to build the fast look-up */ @@ -1103,8 +1140,8 @@ void MuxGraph::build_mux_graph(const CircuitLibrary& circuit_lib, build_mem_lookup(); /* For fracturable LUTs, we need to add more outputs to the MUX graph */ - if ( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)) - && (true == circuit_lib.is_lut_fracturable(circuit_model)) ) { + if ((CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)) && + (true == circuit_lib.is_lut_fracturable(circuit_model))) { add_fracturable_outputs(circuit_lib, circuit_model); } } @@ -1153,15 +1190,11 @@ void MuxGraph::build_mem_lookup() { } /* Invalidate (empty) the node fast lookup*/ -void MuxGraph::invalidate_node_lookup() { - node_lookup_.clear(); -} +void MuxGraph::invalidate_node_lookup() { node_lookup_.clear(); } /* Invalidate (empty) the mem fast lookup*/ -void MuxGraph::invalidate_mem_lookup() { - mem_lookup_.clear(); -} - +void MuxGraph::invalidate_mem_lookup() { mem_lookup_.clear(); } + /************************************************** * Private validators *************************************************/ @@ -1179,7 +1212,8 @@ bool MuxGraph::valid_mem_id(const MuxMemId& mem) const { return size_t(mem) < mem_ids_.size() && mem_ids_[mem] == mem; } -/* validate an input id (from which data path signal will be progagated to the output) */ +/* validate an input id (from which data path signal will be progagated to the + * output) */ bool MuxGraph::valid_input_id(const MuxInputId& input_id) const { for (const auto& lvl : node_lookup_) { for (const auto& node : lvl[MUX_INPUT_NODE]) { @@ -1187,7 +1221,7 @@ bool MuxGraph::valid_input_id(const MuxInputId& input_id) const { return false; } } - } + } return true; } @@ -1200,24 +1234,22 @@ bool MuxGraph::valid_output_id(const MuxOutputId& output_id) const { return false; } } - } + } return true; } bool MuxGraph::valid_level(const size_t& level) const { - return level < num_node_levels(); + return level < num_node_levels(); } -bool MuxGraph::valid_node_lookup() const { - return node_lookup_.empty(); -} +bool MuxGraph::valid_node_lookup() const { return node_lookup_.empty(); } /* validate a mux graph and see if it is valid */ bool MuxGraph::valid_mux_graph() const { /* A valid MUX graph should be * 1. every node has 1 fan-out except output node - * 2. every input can be routed to the output node + * 2. every input can be routed to the output node */ for (const auto& node : nodes()) { /* output node has 0 fan-out*/ @@ -1234,19 +1266,19 @@ bool MuxGraph::valid_mux_graph() const { for (const auto& node : nodes()) { if (MUX_INPUT_NODE == node_types_[node]) { MuxNodeId next_node = node; - while ( 0 < node_out_edges_[next_node].size() ) { + while (0 < node_out_edges_[next_node].size()) { MuxEdgeId edge = node_out_edges_[next_node][0]; /* each edge must have 1 fan-out */ if (1 != edge_sink_nodes_[edge].size()) { return false; } - next_node = edge_sink_nodes_[edge][0]; + next_node = edge_sink_nodes_[edge][0]; } if (MUX_OUTPUT_NODE != node_types_[next_node]) { return false; } } - } + } return true; } diff --git a/openfpga/src/mux_lib/mux_graph.h b/openfpga/src/mux_lib/mux_graph.h index fd2fbbf6d..6a5930b35 100644 --- a/openfpga/src/mux_lib/mux_graph.h +++ b/openfpga/src/mux_lib/mux_graph.h @@ -5,10 +5,11 @@ * Include header files required by the data structure definition *******************************************************************/ #include -#include "vtr_vector.h" -#include "vtr_range.h" -#include "mux_graph_fwd.h" + #include "circuit_library.h" +#include "mux_graph_fwd.h" +#include "vtr_range.h" +#include "vtr_vector.h" /* Begin namespace openfpga */ namespace openfpga { @@ -16,9 +17,9 @@ namespace openfpga { /************************************************** * This file includes a data structure to describe * the internal structure of a multiplexer - * using a generic graph representation - * A Branch is a N:1 MUX in the part of MUX graph - * + * using a generic graph representation + * A Branch is a N:1 MUX in the part of MUX graph + * * branch_input --->+ * | * branch_input --->| @@ -27,7 +28,7 @@ namespace openfpga { * | * branch_input --->+ * - * A short example of how a two-level MUX is organized by branches + * A short example of how a two-level MUX is organized by branches * * +-----------+ +--------+ * mux_inputs--->| Branch[0] |--->| | @@ -39,173 +40,200 @@ namespace openfpga { * *************************************************/ class MuxGraph { - private: /* data types used only in this class */ - enum e_mux_graph_node_type { - MUX_INPUT_NODE, - MUX_INTERNAL_NODE, - MUX_OUTPUT_NODE, - NUM_MUX_NODE_TYPES - }; - public: /* Types and ranges */ - typedef vtr::vector::const_iterator node_iterator; - typedef vtr::vector::const_iterator edge_iterator; - typedef vtr::vector::const_iterator mem_iterator; + private: /* data types used only in this class */ + enum e_mux_graph_node_type { + MUX_INPUT_NODE, + MUX_INTERNAL_NODE, + MUX_OUTPUT_NODE, + NUM_MUX_NODE_TYPES + }; - typedef vtr::Range node_range; - typedef vtr::Range edge_range; - typedef vtr::Range mem_range; - public: /* Public Constructors */ - /* Create an object based on a Circuit Model which is MUX */ - MuxGraph(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const size_t& mux_size); - private: /* Private Constructors*/ - /* Create an empty graph */ - MuxGraph(); - public: /* Public accessors: Aggregates */ - node_range nodes() const; - /* Find the non-input nodes */ - std::vector non_input_nodes() const; - edge_range edges() const; - mem_range memories() const; - /* Find the number of levels in terms of the multiplexer */ - std::vector levels() const; - /* Find the actual number of levels in the graph */ - std::vector node_levels() const; - public: /* Public accessors: Data query */ - /* Find the number of inputs in the MUX graph */ - size_t num_inputs() const; - std::vector inputs() const; - /* Find the number of outputs in the MUX graph */ - size_t num_outputs() const; - std::vector outputs() const; - /* Find the edge between two MUX nodes */ - std::vector find_edges(const MuxNodeId& from_node, const MuxNodeId& to_node) const; - /* Find the number of levels in the MUX graph */ - size_t num_levels() const; - size_t num_node_levels() const; - /* Find the number of SRAMs in the MUX graph */ - size_t num_memory_bits() const; - /* Find the number of SRAMs at a level in the MUX graph */ - size_t num_memory_bits_at_level(const size_t& level) const; - /* Return memory id at level */ - std::vector memories_at_level(const size_t& level) const; - /* Find the number of nodes at a given level in the MUX graph */ - size_t num_nodes_at_level(const size_t& level) const; - /* Find the level of a node */ - size_t node_level(const MuxNodeId& node) const; - /* Find the index of a node at its level */ - size_t node_index_at_level(const MuxNodeId& node) const; - /* Find the input edges for a node */ - std::vector node_in_edges(const MuxNodeId& node) const; - /* Find the input nodes for a edge */ - std::vector edge_src_nodes(const MuxEdgeId& edge) const; - /* Find the mem that control the edge */ - MuxMemId find_edge_mem(const MuxEdgeId& edge) const; - /* Identify if the edge is controlled by the inverted output of a mem */ - bool is_edge_use_inv_mem(const MuxEdgeId& edge) const; - /* Find the sizes of each branch of a MUX */ - std::vector branch_sizes() const; - /* Find the sizes of each branch of a MUX at a given level */ - std::vector branch_sizes(const size_t& level) const; - /* Generate MUX graphs for its branches */ - MuxGraph subgraph(const MuxNodeId& node) const; - std::vector build_mux_branch_graphs() const; - /* Get the node id of a given input */ - MuxNodeId node_id(const MuxInputId& input_id) const; - /* Get the node id of a given output */ - MuxNodeId node_id(const MuxOutputId& output_id) const; - /* Get the node id w.r.t. the node level and node_index at the level */ - MuxNodeId node_id(const size_t& node_level, const size_t& node_index_at_level) const; - /* Get the input id of a given node */ - MuxInputId input_id(const MuxNodeId& node_id) const; - /* Identify if the node is an input of the MUX */ - bool is_node_input(const MuxNodeId& node_id) const; - /* Get the output id of a given node */ - MuxOutputId output_id(const MuxNodeId& node_id) const; - /* Identify if the node is an output of the MUX */ - bool is_node_output(const MuxNodeId& node_id) const; - /* Decode memory bits based on an input id and an output id - * This function will start from the input node - * and do a forward propagation until reaching the output node - */ - vtr::vector decode_memory_bits(const MuxInputId& input_id, - const MuxOutputId& output_id) const; - /* Find the input node that the memory bits will route an output node to - * This function backward propagate from the output node to an input node - * assuming the memory bits are applied - * Note: This function is mainly used for decoding LUT MUXes - */ - MuxInputId find_input_node_driven_by_output_node(const std::map& memory_bits, - const MuxOutputId& output_id) const; - private: /* Private mutators : basic operations */ - /* Add a unconfigured node to the MuxGraph */ - MuxNodeId add_node(const enum e_mux_graph_node_type& node_type); - /* Add a edge connecting two nodes */ - MuxEdgeId add_edge(const MuxNodeId& from_node, const MuxNodeId& to_node); - /* Add a memory bit to the MuxGraph */ - MuxMemId add_mem(); - /* Configure the level of a memory */ - void set_mem_level(const MuxMemId& mem, const size_t& level); - /* Link an edge to a mem */ - void set_edge_mem_id(const MuxEdgeId& edge, const MuxMemId& mem); - private: /* Private mutators : graph builders */ - void build_multilevel_mux_graph(const size_t& mux_size, - const size_t& num_levels, const size_t& num_inputs_per_branch, - const CircuitModelId& pgl_model) ; - /* Build the graph for a given one-level multiplexer implementation */ - void build_onelevel_mux_graph(const size_t& mux_size, - const CircuitModelId& pgl_model) ; - /* Build the graph for a given multiplexer model */ - void build_mux_graph(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const size_t& mux_size); - /* Convert some internal node to outputs according to fracturable LUT circuit design specifications */ - void add_fracturable_outputs(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model); - /* Build fast node lookup */ - void build_node_lookup(); - /* Build fast mem lookup */ - void build_mem_lookup(); - private: /* Private validators */ - /* valid ids */ - bool valid_node_id(const MuxNodeId& node) const; - bool valid_edge_id(const MuxEdgeId& edge) const; - bool valid_mem_id(const MuxMemId& mem) const; - bool valid_input_id(const MuxInputId& input_id) const; - bool valid_output_id(const MuxOutputId& output_id) const; - bool valid_level(const size_t& level) const; - /* validate/invalidate node lookup */ - bool valid_node_lookup() const; - void invalidate_node_lookup(); - void invalidate_mem_lookup(); - /* validate graph */ - bool valid_mux_graph() const; - private: /* Internal data */ - vtr::vector node_ids_; /* Unique ids for each node */ - vtr::vector node_types_; /* type of each node, input/output/internal */ - vtr::vector node_input_ids_; /* Unique ids for each node as an input of the MUX */ - vtr::vector node_output_ids_; /* Unique ids for each node as an input of the MUX */ - vtr::vector node_levels_; /* at which level, each node belongs to */ - vtr::vector node_ids_at_level_; /* the index at the level that each node belongs to */ - vtr::vector> node_in_edges_; /* ids of incoming edges to each node */ - vtr::vector> node_out_edges_; /* ids of outgoing edges from each node */ + public: /* Types and ranges */ + typedef vtr::vector::const_iterator node_iterator; + typedef vtr::vector::const_iterator edge_iterator; + typedef vtr::vector::const_iterator mem_iterator; - vtr::vector edge_ids_; /* Unique ids for each edge */ - vtr::vector> edge_src_nodes_; /* source nodes drive this edge */ - vtr::vector> edge_sink_nodes_; /* sink nodes this edge drives */ - vtr::vector edge_models_; /* type of each edge: tgate/pass-gate */ - vtr::vector edge_mem_ids_; /* ids of memory bit that control the edge */ - vtr::vector edge_inv_mem_; /* if the edge is controlled by an inverted output of a memory bit */ + typedef vtr::Range node_range; + typedef vtr::Range edge_range; + typedef vtr::Range mem_range; - vtr::vector mem_ids_; /* ids of configuration memories */ - vtr::vector mem_levels_; /* ids of configuration memories */ + public: /* Public Constructors */ + /* Create an object based on a Circuit Model which is MUX */ + MuxGraph(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, const size_t& mux_size); - /* fast look-up */ - typedef std::vector>> NodeLookup; - mutable NodeLookup node_lookup_; /* [num_levels][num_types][num_nodes_per_level] */ - typedef std::vector> MemLookup; - mutable MemLookup mem_lookup_; /* [num_levels][num_mems_per_level] */ + private: /* Private Constructors*/ + /* Create an empty graph */ + MuxGraph(); + + public: /* Public accessors: Aggregates */ + node_range nodes() const; + /* Find the non-input nodes */ + std::vector non_input_nodes() const; + edge_range edges() const; + mem_range memories() const; + /* Find the number of levels in terms of the multiplexer */ + std::vector levels() const; + /* Find the actual number of levels in the graph */ + std::vector node_levels() const; + + public: /* Public accessors: Data query */ + /* Find the number of inputs in the MUX graph */ + size_t num_inputs() const; + std::vector inputs() const; + /* Find the number of outputs in the MUX graph */ + size_t num_outputs() const; + std::vector outputs() const; + /* Find the edge between two MUX nodes */ + std::vector find_edges(const MuxNodeId& from_node, + const MuxNodeId& to_node) const; + /* Find the number of levels in the MUX graph */ + size_t num_levels() const; + size_t num_node_levels() const; + /* Find the number of SRAMs in the MUX graph */ + size_t num_memory_bits() const; + /* Find the number of SRAMs at a level in the MUX graph */ + size_t num_memory_bits_at_level(const size_t& level) const; + /* Return memory id at level */ + std::vector memories_at_level(const size_t& level) const; + /* Find the number of nodes at a given level in the MUX graph */ + size_t num_nodes_at_level(const size_t& level) const; + /* Find the level of a node */ + size_t node_level(const MuxNodeId& node) const; + /* Find the index of a node at its level */ + size_t node_index_at_level(const MuxNodeId& node) const; + /* Find the input edges for a node */ + std::vector node_in_edges(const MuxNodeId& node) const; + /* Find the input nodes for a edge */ + std::vector edge_src_nodes(const MuxEdgeId& edge) const; + /* Find the mem that control the edge */ + MuxMemId find_edge_mem(const MuxEdgeId& edge) const; + /* Identify if the edge is controlled by the inverted output of a mem */ + bool is_edge_use_inv_mem(const MuxEdgeId& edge) const; + /* Find the sizes of each branch of a MUX */ + std::vector branch_sizes() const; + /* Find the sizes of each branch of a MUX at a given level */ + std::vector branch_sizes(const size_t& level) const; + /* Generate MUX graphs for its branches */ + MuxGraph subgraph(const MuxNodeId& node) const; + std::vector build_mux_branch_graphs() const; + /* Get the node id of a given input */ + MuxNodeId node_id(const MuxInputId& input_id) const; + /* Get the node id of a given output */ + MuxNodeId node_id(const MuxOutputId& output_id) const; + /* Get the node id w.r.t. the node level and node_index at the level */ + MuxNodeId node_id(const size_t& node_level, + const size_t& node_index_at_level) const; + /* Get the input id of a given node */ + MuxInputId input_id(const MuxNodeId& node_id) const; + /* Identify if the node is an input of the MUX */ + bool is_node_input(const MuxNodeId& node_id) const; + /* Get the output id of a given node */ + MuxOutputId output_id(const MuxNodeId& node_id) const; + /* Identify if the node is an output of the MUX */ + bool is_node_output(const MuxNodeId& node_id) const; + /* Decode memory bits based on an input id and an output id + * This function will start from the input node + * and do a forward propagation until reaching the output node + */ + vtr::vector decode_memory_bits( + const MuxInputId& input_id, const MuxOutputId& output_id) const; + /* Find the input node that the memory bits will route an output node to + * This function backward propagate from the output node to an input node + * assuming the memory bits are applied + * Note: This function is mainly used for decoding LUT MUXes + */ + MuxInputId find_input_node_driven_by_output_node( + const std::map& memory_bits, + const MuxOutputId& output_id) const; + + private: /* Private mutators : basic operations */ + /* Add a unconfigured node to the MuxGraph */ + MuxNodeId add_node(const enum e_mux_graph_node_type& node_type); + /* Add a edge connecting two nodes */ + MuxEdgeId add_edge(const MuxNodeId& from_node, const MuxNodeId& to_node); + /* Add a memory bit to the MuxGraph */ + MuxMemId add_mem(); + /* Configure the level of a memory */ + void set_mem_level(const MuxMemId& mem, const size_t& level); + /* Link an edge to a mem */ + void set_edge_mem_id(const MuxEdgeId& edge, const MuxMemId& mem); + + private: /* Private mutators : graph builders */ + void build_multilevel_mux_graph(const size_t& mux_size, + const size_t& num_levels, + const size_t& num_inputs_per_branch, + const CircuitModelId& pgl_model); + /* Build the graph for a given one-level multiplexer implementation */ + void build_onelevel_mux_graph(const size_t& mux_size, + const CircuitModelId& pgl_model); + /* Build the graph for a given multiplexer model */ + void build_mux_graph(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const size_t& mux_size); + /* Convert some internal node to outputs according to fracturable LUT circuit + * design specifications */ + void add_fracturable_outputs(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model); + /* Build fast node lookup */ + void build_node_lookup(); + /* Build fast mem lookup */ + void build_mem_lookup(); + + private: /* Private validators */ + /* valid ids */ + bool valid_node_id(const MuxNodeId& node) const; + bool valid_edge_id(const MuxEdgeId& edge) const; + bool valid_mem_id(const MuxMemId& mem) const; + bool valid_input_id(const MuxInputId& input_id) const; + bool valid_output_id(const MuxOutputId& output_id) const; + bool valid_level(const size_t& level) const; + /* validate/invalidate node lookup */ + bool valid_node_lookup() const; + void invalidate_node_lookup(); + void invalidate_mem_lookup(); + /* validate graph */ + bool valid_mux_graph() const; + + private: /* Internal data */ + vtr::vector node_ids_; /* Unique ids for each node */ + vtr::vector + node_types_; /* type of each node, input/output/internal */ + vtr::vector + node_input_ids_; /* Unique ids for each node as an input of the MUX */ + vtr::vector + node_output_ids_; /* Unique ids for each node as an input of the MUX */ + vtr::vector + node_levels_; /* at which level, each node belongs to */ + vtr::vector + node_ids_at_level_; /* the index at the level that each node belongs to */ + vtr::vector> + node_in_edges_; /* ids of incoming edges to each node */ + vtr::vector> + node_out_edges_; /* ids of outgoing edges from each node */ + + vtr::vector edge_ids_; /* Unique ids for each edge */ + vtr::vector> + edge_src_nodes_; /* source nodes drive this edge */ + vtr::vector> + edge_sink_nodes_; /* sink nodes this edge drives */ + vtr::vector + edge_models_; /* type of each edge: tgate/pass-gate */ + vtr::vector + edge_mem_ids_; /* ids of memory bit that control the edge */ + vtr::vector + edge_inv_mem_; /* if the edge is controlled by an inverted output of a + memory bit */ + + vtr::vector mem_ids_; /* ids of configuration memories */ + vtr::vector mem_levels_; /* ids of configuration memories */ + + /* fast look-up */ + typedef std::vector>> NodeLookup; + mutable NodeLookup + node_lookup_; /* [num_levels][num_types][num_nodes_per_level] */ + typedef std::vector> MemLookup; + mutable MemLookup mem_lookup_; /* [num_levels][num_mems_per_level] */ }; } /* End namespace openfpga*/ diff --git a/openfpga/src/mux_lib/mux_graph_fwd.h b/openfpga/src/mux_lib/mux_graph_fwd.h index 75fd5b1e1..ea97e353a 100644 --- a/openfpga/src/mux_lib/mux_graph_fwd.h +++ b/openfpga/src/mux_lib/mux_graph_fwd.h @@ -1,5 +1,5 @@ /************************************************** - * This file includes only declarations for + * This file includes only declarations for * the data structures to describe multiplexer structures * Please refer to mux_graph.h for more details *************************************************/ @@ -11,7 +11,6 @@ /* begin namespace openfpga */ namespace openfpga { - /* Strong Ids for MUXes */ struct mux_node_id_tag; struct mux_edge_id_tag; @@ -29,5 +28,4 @@ class MuxGraph; } /* end namespace openfpga */ - -#endif +#endif diff --git a/openfpga/src/mux_lib/mux_library.cpp b/openfpga/src/mux_lib/mux_library.cpp index 20e590fdf..ffef77202 100644 --- a/openfpga/src/mux_lib/mux_library.cpp +++ b/openfpga/src/mux_lib/mux_library.cpp @@ -1,12 +1,12 @@ /************************************************** - * This file includes member functions for the + * This file includes member functions for the * data structures in mux_library.h *************************************************/ -#include "vtr_assert.h" - #include "mux_library.h" +#include "vtr_assert.h" + /* begin namespace openfpga */ namespace openfpga { @@ -25,7 +25,7 @@ MuxLibrary::mux_range MuxLibrary::muxes() const { * Public accessors: data query *************************************************/ /* Get a MUX graph (read-only) */ -MuxId MuxLibrary::mux_graph(const CircuitModelId& circuit_model, +MuxId MuxLibrary::mux_graph(const CircuitModelId& circuit_model, const size_t& mux_size) const { /* Make sure we have a valid mux look-up */ VTR_ASSERT_SAFE(valid_mux_lookup()); @@ -60,7 +60,9 @@ size_t MuxLibrary::max_mux_size() const { * Private mutators: *************************************************/ /* Add a mux to the library */ -void MuxLibrary::add_mux(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, const size_t& mux_size) { +void MuxLibrary::add_mux(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const size_t& mux_size) { /* First, check if there is already an existing graph */ if (valid_mux_size(circuit_model, mux_size)) { return; @@ -77,7 +79,7 @@ void MuxLibrary::add_mux(const CircuitLibrary& circuit_lib, const CircuitModelId /* update mux_lookup*/ mux_lookup_[circuit_model][mux_size] = mux; -} +} /************************************************** * Private accessors: validator and invalidators @@ -86,20 +88,21 @@ bool MuxLibrary::valid_mux_id(const MuxId& mux) const { return size_t(mux) < mux_ids_.size() && mux_ids_[mux] == mux; } -bool MuxLibrary::valid_mux_lookup() const { - return mux_lookup_.empty(); -} +bool MuxLibrary::valid_mux_lookup() const { return mux_lookup_.empty(); } -bool MuxLibrary::valid_mux_circuit_model_id(const CircuitModelId& circuit_model) const { +bool MuxLibrary::valid_mux_circuit_model_id( + const CircuitModelId& circuit_model) const { MuxLookup::iterator it = mux_lookup_.find(circuit_model); return (it != mux_lookup_.end()); } -bool MuxLibrary::valid_mux_size(const CircuitModelId& circuit_model, const size_t& mux_size) const { +bool MuxLibrary::valid_mux_size(const CircuitModelId& circuit_model, + const size_t& mux_size) const { if (false == valid_mux_circuit_model_id(circuit_model)) { return false; } - std::map::iterator it = mux_lookup_[circuit_model].find(mux_size); + std::map::iterator it = + mux_lookup_[circuit_model].find(mux_size); return (it != mux_lookup_[circuit_model].end()); } @@ -114,8 +117,6 @@ void MuxLibrary::build_mux_lookup() { } /* Invalidate (empty) the mux fast lookup*/ -void MuxLibrary::invalidate_mux_lookup() { - mux_lookup_.clear(); -} +void MuxLibrary::invalidate_mux_lookup() { mux_lookup_.clear(); } } /* end namespace openfpga */ diff --git a/openfpga/src/mux_lib/mux_library.h b/openfpga/src/mux_lib/mux_library.h index 03f406738..120290151 100644 --- a/openfpga/src/mux_lib/mux_library.h +++ b/openfpga/src/mux_lib/mux_library.h @@ -1,9 +1,9 @@ /************************************************** * This file includes a data structure to describe * the multiplexer implementations in FPGA architectures - * MuxLibrary is a collection of multiplexers + * MuxLibrary is a collection of multiplexers * with various circuit-level description (related to - * the information available in CircuitLibrary + * the information available in CircuitLibrary * and the input size of multiplexers) *************************************************/ @@ -11,6 +11,7 @@ #define MUX_LIBRARY_H #include + #include "mux_graph.h" #include "mux_library_fwd.h" @@ -18,45 +19,59 @@ namespace openfpga { class MuxLibrary { - public: /* Types and ranges */ - typedef vtr::vector::const_iterator mux_iterator; + public: /* Types and ranges */ + typedef vtr::vector::const_iterator mux_iterator; - typedef vtr::Range mux_range; - public: /* Public accessors: Aggregates */ - mux_range muxes() const; - public: /* Public accessors */ - /* Get a MUX graph (read-only) */ - MuxId mux_graph(const CircuitModelId& circuit_model, const size_t& mux_size) const; - const MuxGraph& mux_graph(const MuxId& mux_id) const; - /* Get a mux circuit model id */ - CircuitModelId mux_circuit_model(const MuxId& mux_id) const; - /* Find the mux sizes */ - size_t max_mux_size() const; - public: /* Public mutators */ - /* Add a mux to the library */ - void add_mux(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, const size_t& mux_size); - public: /* Public validators */ - bool valid_mux_id(const MuxId& mux) const; - private: /* Private accessors */ - bool valid_mux_lookup() const; - bool valid_mux_circuit_model_id(const CircuitModelId& circuit_model) const; - bool valid_mux_size(const CircuitModelId& circuit_model, const size_t& mux_size) const; - private: /* Private mutators: mux_lookup */ - void build_mux_lookup(); - /* Invalidate (empty) the mux fast lookup*/ - void invalidate_mux_lookup(); - private: /* Internal data */ - /* MUX graph-based desription */ - vtr::vector mux_ids_; /* Unique identifier for each mux graph */ - vtr::vector mux_graphs_; /* Graphs describing MUX internal structures */ - vtr::vector mux_circuit_models_; /* circuit model id in circuit library */ + typedef vtr::Range mux_range; - /* Local encoder description */ - //vtr::vector mux_local_encoders_; /* Graphs describing MUX internal structures */ + public: /* Public accessors: Aggregates */ + mux_range muxes() const; - /* a fast look-up to search mux_graphs with given circuit model and mux size */ - typedef std::map> MuxLookup; - mutable MuxLookup mux_lookup_; + public: /* Public accessors */ + /* Get a MUX graph (read-only) */ + MuxId mux_graph(const CircuitModelId& circuit_model, + const size_t& mux_size) const; + const MuxGraph& mux_graph(const MuxId& mux_id) const; + /* Get a mux circuit model id */ + CircuitModelId mux_circuit_model(const MuxId& mux_id) const; + /* Find the mux sizes */ + size_t max_mux_size() const; + + public: /* Public mutators */ + /* Add a mux to the library */ + void add_mux(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, const size_t& mux_size); + + public: /* Public validators */ + bool valid_mux_id(const MuxId& mux) const; + + private: /* Private accessors */ + bool valid_mux_lookup() const; + bool valid_mux_circuit_model_id(const CircuitModelId& circuit_model) const; + bool valid_mux_size(const CircuitModelId& circuit_model, + const size_t& mux_size) const; + + private: /* Private mutators: mux_lookup */ + void build_mux_lookup(); + /* Invalidate (empty) the mux fast lookup*/ + void invalidate_mux_lookup(); + + private: /* Internal data */ + /* MUX graph-based desription */ + vtr::vector mux_ids_; /* Unique identifier for each mux graph */ + vtr::vector + mux_graphs_; /* Graphs describing MUX internal structures */ + vtr::vector + mux_circuit_models_; /* circuit model id in circuit library */ + + /* Local encoder description */ + // vtr::vector mux_local_encoders_; /* Graphs + // describing MUX internal structures */ + + /* a fast look-up to search mux_graphs with given circuit model and mux size + */ + typedef std::map> MuxLookup; + mutable MuxLookup mux_lookup_; }; } /* end namespace openfpga */ diff --git a/openfpga/src/mux_lib/mux_library_builder.cpp b/openfpga/src/mux_lib/mux_library_builder.cpp index 5d46990eb..add2acf53 100644 --- a/openfpga/src/mux_lib/mux_library_builder.cpp +++ b/openfpga/src/mux_lib/mux_library_builder.cpp @@ -4,22 +4,20 @@ #include /* Headers from vtrutil library */ -#include "vtr_time.h" #include "vtr_assert.h" #include "vtr_log.h" +#include "vtr_time.h" /* Headers from readarchopenfpga library */ -#include "circuit_types.h" #include "circuit_library.h" #include "circuit_library_utils.h" - -#include "mux_utils.h" -#include "pb_type_utils.h" -#include "pb_graph_utils.h" -#include "openfpga_rr_graph_utils.h" - +#include "circuit_types.h" #include "mux_library.h" #include "mux_library_builder.h" +#include "mux_utils.h" +#include "openfpga_rr_graph_utils.h" +#include "pb_graph_utils.h" +#include "pb_type_utils.h" /* Begin namespace openfpga */ namespace openfpga { @@ -28,114 +26,114 @@ namespace openfpga { * Update MuxLibrary with the unique multiplexer structures * found in the global routing architecture *******************************************************************/ -static -void build_routing_arch_mux_library(const RRGraphView& rr_graph, - const CircuitLibrary& circuit_lib, - const VprDeviceAnnotation& vpr_device_annotation, - MuxLibrary& mux_lib) { - /* The routing path is. +static void build_routing_arch_mux_library( + const RRGraphView& rr_graph, const CircuitLibrary& circuit_lib, + const VprDeviceAnnotation& vpr_device_annotation, MuxLibrary& mux_lib) { + /* The routing path is. * OPIN ----> CHAN ----> ... ----> CHAN ----> IPIN * Each edge is a switch, for IPIN, the switch is a connection block, * for the rest is a switch box */ - /* Count the sizes of muliplexers in routing architecture */ + /* Count the sizes of muliplexers in routing architecture */ for (const RRNodeId& node : rr_graph.nodes()) { switch (rr_graph.node_type(node)) { - case IPIN: - case CHANX: - case CHANY: { - /* Have to consider the fan_in only, it is a connection block (multiplexer)*/ - if ( (0 == rr_graph.node_in_edges(node).size()) - || (1 == rr_graph.node_in_edges(node).size()) ) { - break; + case IPIN: + case CHANX: + case CHANY: { + /* Have to consider the fan_in only, it is a connection block + * (multiplexer)*/ + if ((0 == rr_graph.node_in_edges(node).size()) || + (1 == rr_graph.node_in_edges(node).size())) { + break; + } + /* Find the circuit_model for multiplexers in connection blocks */ + std::vector driver_switches = + get_rr_graph_driver_switches(rr_graph, node); + VTR_ASSERT(1 == driver_switches.size()); + const CircuitModelId& rr_switch_circuit_model = + vpr_device_annotation.rr_switch_circuit_model(driver_switches[0]); + /* we should select a circuit model for the routing resource switch */ + 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); + 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()); + exit(1); + } + + VTR_ASSERT(CircuitModelId::INVALID() != rr_switch_circuit_model); + /* Add the mux to mux_library */ + mux_lib.add_mux(circuit_lib, rr_switch_circuit_model, + rr_graph.node_in_edges(node).size()); + break; } - /* Find the circuit_model for multiplexers in connection blocks */ - std::vector driver_switches = get_rr_graph_driver_switches(rr_graph, node); - VTR_ASSERT(1 == driver_switches.size()); - const CircuitModelId& rr_switch_circuit_model = vpr_device_annotation.rr_switch_circuit_model(driver_switches[0]); - /* we should select a circuit model for the routing resource switch */ - 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); - 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()); - exit(1); - } - - VTR_ASSERT(CircuitModelId::INVALID() != rr_switch_circuit_model); - /* Add the mux to mux_library */ - mux_lib.add_mux(circuit_lib, rr_switch_circuit_model, rr_graph.node_in_edges(node).size()); - break; - } - default: - /* We do not care other types of rr_node */ - break; + default: + /* We do not care other types of rr_node */ + break; } } } - /******************************************************************** * For a given pin of a pb_graph_node - * - Identify the interconnect implementation + * - Identify the interconnect implementation * - Find the number of inputs for the interconnect implementation * - Update the mux_library is the implementation is multiplexers ********************************************************************/ -static -void build_pb_graph_pin_interconnect_mux_library(t_pb_graph_pin* pb_graph_pin, - t_mode* interconnect_mode, - const CircuitLibrary& circuit_lib, - const VprDeviceAnnotation& vpr_device_annotation, - MuxLibrary& mux_lib) { +static void build_pb_graph_pin_interconnect_mux_library( + t_pb_graph_pin* pb_graph_pin, t_mode* interconnect_mode, + const CircuitLibrary& circuit_lib, + const VprDeviceAnnotation& vpr_device_annotation, MuxLibrary& mux_lib) { /* Find the interconnect in the physical mode that drives this pin */ - t_interconnect* physical_interc = pb_graph_pin_interc(pb_graph_pin, interconnect_mode); + t_interconnect* physical_interc = + pb_graph_pin_interc(pb_graph_pin, interconnect_mode); /* Bypass if the interc does not indicate multiplexers */ - if (MUX_INTERC != vpr_device_annotation.interconnect_physical_type(physical_interc)) { + if (MUX_INTERC != + vpr_device_annotation.interconnect_physical_type(physical_interc)) { return; } - size_t mux_size = pb_graph_pin_inputs(pb_graph_pin, physical_interc).size(); + size_t mux_size = pb_graph_pin_inputs(pb_graph_pin, physical_interc).size(); VTR_ASSERT(true == valid_mux_implementation_num_inputs(mux_size)); - const CircuitModelId& interc_circuit_model = vpr_device_annotation.interconnect_circuit_model(physical_interc); - VTR_ASSERT(CircuitModelId::INVALID() != interc_circuit_model); + const CircuitModelId& interc_circuit_model = + vpr_device_annotation.interconnect_circuit_model(physical_interc); + VTR_ASSERT(CircuitModelId::INVALID() != interc_circuit_model); /* Add the mux model to library */ mux_lib.add_mux(circuit_lib, interc_circuit_model, mux_size); } /******************************************************************** - * Update MuxLibrary with the unique multiplexer structures + * Update MuxLibrary with the unique multiplexer structures * found in programmable logic blocks ********************************************************************/ -static -void rec_build_vpr_physical_pb_graph_node_mux_library(t_pb_graph_node* pb_graph_node, - const CircuitLibrary& circuit_lib, - const VprDeviceAnnotation& vpr_device_annotation, - MuxLibrary& mux_lib) { +static void rec_build_vpr_physical_pb_graph_node_mux_library( + t_pb_graph_node* pb_graph_node, const CircuitLibrary& circuit_lib, + const VprDeviceAnnotation& vpr_device_annotation, MuxLibrary& mux_lib) { /* Find the number of inputs for each interconnect of this pb_graph_node - * This is only applicable to each interconnect which will be implemented with multiplexers + * This is only applicable to each interconnect which will be implemented with + * multiplexers */ t_mode* parent_physical_mode = nullptr; if (false == pb_graph_node->is_root()) { - parent_physical_mode = vpr_device_annotation.physical_mode(pb_graph_node->parent_pb_graph_node->pb_type); + parent_physical_mode = vpr_device_annotation.physical_mode( + pb_graph_node->parent_pb_graph_node->pb_type); } for (int iport = 0; iport < pb_graph_node->num_input_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) { - build_pb_graph_pin_interconnect_mux_library(&(pb_graph_node->input_pins[iport][ipin]), - parent_physical_mode, - circuit_lib, - vpr_device_annotation, - mux_lib); + build_pb_graph_pin_interconnect_mux_library( + &(pb_graph_node->input_pins[iport][ipin]), parent_physical_mode, + circuit_lib, vpr_device_annotation, mux_lib); } } for (int iport = 0; iport < pb_graph_node->num_clock_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_clock_pins[iport]; ++ipin) { - build_pb_graph_pin_interconnect_mux_library(&(pb_graph_node->clock_pins[iport][ipin]), - parent_physical_mode, - circuit_lib, - vpr_device_annotation, - mux_lib); + build_pb_graph_pin_interconnect_mux_library( + &(pb_graph_node->clock_pins[iport][ipin]), parent_physical_mode, + circuit_lib, vpr_device_annotation, mux_lib); } } @@ -143,28 +141,29 @@ void rec_build_vpr_physical_pb_graph_node_mux_library(t_pb_graph_node* pb_graph_ if (true == is_primitive_pb_type(pb_graph_node->pb_type)) { return; } - + /* Get the physical mode, primitive node does not have physical mode */ - t_mode* physical_mode = vpr_device_annotation.physical_mode(pb_graph_node->pb_type); + t_mode* physical_mode = + vpr_device_annotation.physical_mode(pb_graph_node->pb_type); VTR_ASSERT(nullptr != physical_mode); - /* Note that the output port interconnect should be considered for non-primitive nodes */ + /* Note that the output port interconnect should be considered for + * non-primitive nodes */ for (int iport = 0; iport < pb_graph_node->num_output_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ++ipin) { - build_pb_graph_pin_interconnect_mux_library(&(pb_graph_node->output_pins[iport][ipin]), - physical_mode, - circuit_lib, - vpr_device_annotation, - mux_lib); + build_pb_graph_pin_interconnect_mux_library( + &(pb_graph_node->output_pins[iport][ipin]), physical_mode, circuit_lib, + vpr_device_annotation, mux_lib); } } - + /* Visit all the child nodes in the physical mode */ for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) { - for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; ++jpb) { - rec_build_vpr_physical_pb_graph_node_mux_library(&(pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), - circuit_lib, vpr_device_annotation, - mux_lib); + for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; + ++jpb) { + rec_build_vpr_physical_pb_graph_node_mux_library( + &(pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), + circuit_lib, vpr_device_annotation, mux_lib); } } } @@ -173,9 +172,8 @@ void rec_build_vpr_physical_pb_graph_node_mux_library(t_pb_graph_node* pb_graph_ * Update MuxLibrary with the unique multiplexers required by * LUTs in the circuit library ********************************************************************/ -static -void build_lut_mux_library(MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib) { +static void build_lut_mux_library(MuxLibrary& mux_lib, + const CircuitLibrary& circuit_lib) { /* Find all the circuit models which are LUTs in the circuit library */ for (const auto& circuit_model : circuit_lib.models()) { /* Bypass non-LUT circuit models */ @@ -184,20 +182,23 @@ void build_lut_mux_library(MuxLibrary& mux_lib, } /* Find the MUX size required by the LUT */ /* Get input ports which are not global ports! */ - std::vector input_ports = find_lut_circuit_model_input_port(circuit_lib, circuit_model, false); + std::vector input_ports = + find_lut_circuit_model_input_port(circuit_lib, circuit_model, false); VTR_ASSERT(1 == input_ports.size()); /* MUX size = 2^lut_size */ - size_t lut_mux_size = (size_t)pow(2., (double)(circuit_lib.port_size(input_ports[0]))); + size_t lut_mux_size = + (size_t)pow(2., (double)(circuit_lib.port_size(input_ports[0]))); /* Add mux to the mux library */ mux_lib.add_mux(circuit_lib, circuit_model, lut_mux_size); } } /* Statistic for all the multiplexers in FPGA - * We determine the sizes and its structure (according to spice_model) for each type of multiplexers - * We search multiplexers in Switch Blocks, Connection blocks and Configurable Logic Blocks - * In additional to multiplexers, this function also consider crossbars. - * All the statistics are stored in a linked list, as a return value + * We determine the sizes and its structure (according to spice_model) for each + * type of multiplexers We search multiplexers in Switch Blocks, Connection + * blocks and Configurable Logic Blocks In additional to multiplexers, this + * function also consider crossbars. All the statistics are stored in a linked + * list, as a return value */ MuxLibrary build_device_mux_library(const DeviceContext& vpr_device_ctx, const OpenfpgaContext& openfpga_ctx) { @@ -206,30 +207,30 @@ MuxLibrary build_device_mux_library(const DeviceContext& vpr_device_ctx, /* MuxLibrary to store the information of Multiplexers*/ MuxLibrary mux_lib; - /* Step 1: We should check the multiplexer spice models defined in routing architecture.*/ - build_routing_arch_mux_library(vpr_device_ctx.rr_graph, openfpga_ctx.arch().circuit_lib, - openfpga_ctx.vpr_device_annotation(), - mux_lib); + /* Step 1: We should check the multiplexer spice models defined in routing + * architecture.*/ + build_routing_arch_mux_library(vpr_device_ctx.rr_graph, + openfpga_ctx.arch().circuit_lib, + openfpga_ctx.vpr_device_annotation(), mux_lib); - /* Step 2: Count the sizes of multiplexers in complex logic blocks */ - for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + /* Step 2: Count the sizes of multiplexers in complex logic blocks */ + for (const t_logical_block_type& lb_type : + vpr_device_ctx.logical_block_types) { /* By pass nullptr for pb_graph head */ if (nullptr == lb_type.pb_graph_head) { continue; } - rec_build_vpr_physical_pb_graph_node_mux_library(lb_type.pb_graph_head, - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.vpr_device_annotation(), - mux_lib); + rec_build_vpr_physical_pb_graph_node_mux_library( + lb_type.pb_graph_head, openfpga_ctx.arch().circuit_lib, + openfpga_ctx.vpr_device_annotation(), mux_lib); } /* Step 3: count the size of multiplexer that will be used in LUTs*/ - build_lut_mux_library(mux_lib, openfpga_ctx.arch().circuit_lib); + build_lut_mux_library(mux_lib, openfpga_ctx.arch().circuit_lib); 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()); + VTR_LOG("Maximum multiplexer size is %lu.\n", mux_lib.max_mux_size()); return mux_lib; } diff --git a/openfpga/src/mux_lib/mux_library_builder.h b/openfpga/src/mux_lib/mux_library_builder.h index d303e7e76..e9bc02ef1 100644 --- a/openfpga/src/mux_lib/mux_library_builder.h +++ b/openfpga/src/mux_lib/mux_library_builder.h @@ -4,9 +4,9 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" -#include "openfpga_context.h" #include "mux_library.h" +#include "openfpga_context.h" +#include "vpr_context.h" /******************************************************************** * Function declaration diff --git a/openfpga/src/mux_lib/mux_library_fwd.h b/openfpga/src/mux_lib/mux_library_fwd.h index f9a8697d6..58356874b 100644 --- a/openfpga/src/mux_lib/mux_library_fwd.h +++ b/openfpga/src/mux_lib/mux_library_fwd.h @@ -1,5 +1,5 @@ /************************************************** - * This file includes only declarations for + * This file includes only declarations for * the data structures to describe multiplexer structures * Please refer to mux_library.h for more details *************************************************/ @@ -22,4 +22,4 @@ class MuxLibrary; } /* end namespace openfpga */ -#endif +#endif diff --git a/openfpga/src/repack/build_physical_lb_rr_graph.cpp b/openfpga/src/repack/build_physical_lb_rr_graph.cpp index ae9fc4c65..5c40d61b4 100644 --- a/openfpga/src/repack/build_physical_lb_rr_graph.cpp +++ b/openfpga/src/repack/build_physical_lb_rr_graph.cpp @@ -3,31 +3,30 @@ ***************************************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" -#include "vtr_assert.h" -#include "vtr_time.h" - -#include "pb_type_utils.h" - #include "build_physical_lb_rr_graph.h" + #include "check_lb_rr_graph.h" +#include "pb_type_utils.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" /* begin namespace openfpga */ namespace openfpga { /*************************************************************************************** * Create all the intermediate nodes for lb_rr_graph for each pb_graph_node. - * Different from the lb_rr_graph builder in VPR packer, this function only consider - * the pb_graph_node under physical modes + * Different from the lb_rr_graph builder in VPR packer, this function only + *consider the pb_graph_node under physical modes ***************************************************************************************/ -static -void rec_build_physical_lb_rr_node_for_pb_graph_node(t_pb_graph_node* pb_graph_node, - LbRRGraph& lb_rr_graph, - const VprDeviceAnnotation& device_annotation) { +static void rec_build_physical_lb_rr_node_for_pb_graph_node( + t_pb_graph_node* pb_graph_node, LbRRGraph& lb_rr_graph, + const VprDeviceAnnotation& device_annotation) { t_pb_type* pb_type = pb_graph_node->pb_type; - /* TODO: think if we need to consider wire mode of LUT when creating the lb_rr_graph here! - * Should we create edges through the LUT input and output nodes? + /* TODO: think if we need to consider wire mode of LUT when creating the + * lb_rr_graph here! Should we create edges through the LUT input and output + * nodes? */ /* The only difference between primitive node and intermediate nodes is @@ -36,7 +35,7 @@ void rec_build_physical_lb_rr_node_for_pb_graph_node(t_pb_graph_node* pb_graph_n */ e_lb_rr_type output_pin_rr_type = LB_INTERMEDIATE; if (true == is_primitive_pb_type(pb_type)) { - output_pin_rr_type = LB_SOURCE; + output_pin_rr_type = LB_SOURCE; } /* alloc and load input pins that connect to sinks */ @@ -88,36 +87,40 @@ void rec_build_physical_lb_rr_node_for_pb_graph_node(t_pb_graph_node* pb_graph_n } if (true == is_primitive_pb_type(pb_type)) { - return; + return; } - /* For non-primitive node: - * This pb_graph_node is a logic block or subcluster - * Go recusrively + /* For non-primitive node: + * This pb_graph_node is a logic block or subcluster + * Go recusrively */ t_mode* physical_mode = device_annotation.physical_mode(pb_type); - for (int ipb_type = 0; ipb_type < physical_mode->num_pb_type_children; ipb_type++) { - for (int ipb = 0; ipb < physical_mode->pb_type_children[ipb_type].num_pb; ipb++) { - rec_build_physical_lb_rr_node_for_pb_graph_node(&(pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb_type][ipb]), lb_rr_graph, device_annotation); + for (int ipb_type = 0; ipb_type < physical_mode->num_pb_type_children; + ipb_type++) { + for (int ipb = 0; ipb < physical_mode->pb_type_children[ipb_type].num_pb; + ipb++) { + rec_build_physical_lb_rr_node_for_pb_graph_node( + &(pb_graph_node + ->child_pb_graph_nodes[physical_mode->index][ipb_type][ipb]), + lb_rr_graph, device_annotation); } } } /*************************************************************************************** * Build the edge for an input/clock pb_graph_pin for a primitive pb_graph node - * This function will identify if the port equivalence should be considered + * This function will identify if the port equivalence should be considered ***************************************************************************************/ -static -void build_lb_rr_edge_primitive_pb_graph_input_pin(LbRRGraph& lb_rr_graph, - t_pb_graph_pin* pb_pin, - LbRRNodeId& sink_node) { +static void build_lb_rr_edge_primitive_pb_graph_input_pin( + LbRRGraph& lb_rr_graph, t_pb_graph_pin* pb_pin, LbRRNodeId& sink_node) { /* Find the node that we have already created */ LbRRNodeId node = lb_rr_graph.find_node(LB_INTERMEDIATE, pb_pin); VTR_ASSERT(true == lb_rr_graph.valid_node_id(node)); PortEquivalence port_equivalent = pb_pin->port->equivalent; - if (port_equivalent == PortEquivalence::NONE || sink_node == LbRRNodeId::INVALID()) { + if (port_equivalent == PortEquivalence::NONE || + sink_node == LbRRNodeId::INVALID()) { /* Create new sink for input to primitive */ LbRRNodeId new_sink = lb_rr_graph.create_node(LB_SINK); if (port_equivalent != PortEquivalence::NONE) { @@ -127,26 +130,26 @@ void build_lb_rr_edge_primitive_pb_graph_input_pin(LbRRGraph& lb_rr_graph, } sink_node = new_sink; } - - /* Connect the nodes denoting the input pins to sink, since this is a primtive node, we do not have any mode */ + + /* Connect the nodes denoting the input pins to sink, since this is a primtive + * node, we do not have any mode */ LbRREdgeId edge = lb_rr_graph.create_edge(node, sink_node, nullptr); /* TODO: Double check if this is the case */ - lb_rr_graph.set_edge_intrinsic_cost(edge, 1.); + lb_rr_graph.set_edge_intrinsic_cost(edge, 1.); } /*************************************************************************************** * Build the edge for a pb_graph_pin for a non-primitive pb_graph node - * Note: - * - this function is NOT applicable to - * - any input pin of primitive pb_graph_node + * Note: + * - this function is NOT applicable to + * - any input pin of primitive pb_graph_node * - any output pin of root pb_graph_node! ***************************************************************************************/ -static -void build_lb_rr_edge_pb_graph_pin(LbRRGraph& lb_rr_graph, - t_pb_graph_pin* pb_pin, - const e_lb_rr_type& pin_rr_type, - t_mode* physical_mode) { +static void build_lb_rr_edge_pb_graph_pin(LbRRGraph& lb_rr_graph, + t_pb_graph_pin* pb_pin, + const e_lb_rr_type& pin_rr_type, + t_mode* physical_mode) { /* Find the node that we have already created */ LbRRNodeId from_node = lb_rr_graph.find_node(pin_rr_type, pb_pin); VTR_ASSERT(true == lb_rr_graph.valid_node_id(from_node)); @@ -154,16 +157,19 @@ void build_lb_rr_edge_pb_graph_pin(LbRRGraph& lb_rr_graph, /* Load edges only for physical mode! */ for (int iedge = 0; iedge < pb_pin->num_output_edges; iedge++) { VTR_ASSERT(1 == pb_pin->output_edges[iedge]->num_output_pins); - if (physical_mode != pb_pin->output_edges[iedge]->interconnect->parent_mode) { + if (physical_mode != + pb_pin->output_edges[iedge]->interconnect->parent_mode) { continue; } /* Find the node that we have already created */ - LbRRNodeId to_node = lb_rr_graph.find_node(LB_INTERMEDIATE, pb_pin->output_edges[iedge]->output_pins[0]); + LbRRNodeId to_node = lb_rr_graph.find_node( + LB_INTERMEDIATE, pb_pin->output_edges[iedge]->output_pins[0]); VTR_ASSERT(true == lb_rr_graph.valid_node_id(to_node)); - LbRREdgeId edge = lb_rr_graph.create_edge(from_node, to_node, physical_mode); + LbRREdgeId edge = + lb_rr_graph.create_edge(from_node, to_node, physical_mode); /* TODO: Double check if this is the case */ - lb_rr_graph.set_edge_intrinsic_cost(edge, 1.); + lb_rr_graph.set_edge_intrinsic_cost(edge, 1.); } } @@ -171,11 +177,10 @@ void build_lb_rr_edge_pb_graph_pin(LbRRGraph& lb_rr_graph, * Build the edge for an output pb_graph_pin for a root pb_graph node * These node should be connected to a command external lb_rr_node ***************************************************************************************/ -static -void build_lb_rr_edge_root_pb_graph_pin(LbRRGraph& lb_rr_graph, - t_pb_graph_pin* pb_pin, - const e_lb_rr_type& pin_rr_type, - const LbRRNodeId& ext_rr_index) { +static void build_lb_rr_edge_root_pb_graph_pin(LbRRGraph& lb_rr_graph, + t_pb_graph_pin* pb_pin, + const e_lb_rr_type& pin_rr_type, + const LbRRNodeId& ext_rr_index) { /* Find the node that we have already created */ LbRRNodeId from_node = lb_rr_graph.find_node(pin_rr_type, pb_pin); VTR_ASSERT(true == lb_rr_graph.valid_node_id(from_node)); @@ -183,24 +188,24 @@ void build_lb_rr_edge_root_pb_graph_pin(LbRRGraph& lb_rr_graph, LbRREdgeId edge = lb_rr_graph.create_edge(from_node, ext_rr_index, nullptr); /* TODO: Double check if this is the case */ - lb_rr_graph.set_edge_intrinsic_cost(edge, 1.); + lb_rr_graph.set_edge_intrinsic_cost(edge, 1.); } /*************************************************************************************** - * Create all the edges and special nodes (SOURCE/SINK) for lb_rr_graph for each pb_graph_node. - * Different from the lb_rr_graph builder in VPR packer, this function only consider - * the pb_graph_node under physical modes + * Create all the edges and special nodes (SOURCE/SINK) for lb_rr_graph for each + *pb_graph_node. Different from the lb_rr_graph builder in VPR packer, this + *function only consider the pb_graph_node under physical modes ***************************************************************************************/ -static -void rec_build_physical_lb_rr_edge_for_pb_graph_node(t_pb_graph_node* pb_graph_node, - LbRRGraph& lb_rr_graph, - const LbRRNodeId& ext_rr_index, - const VprDeviceAnnotation& device_annotation) { +static void rec_build_physical_lb_rr_edge_for_pb_graph_node( + t_pb_graph_node* pb_graph_node, LbRRGraph& lb_rr_graph, + const LbRRNodeId& ext_rr_index, + const VprDeviceAnnotation& device_annotation) { t_pb_type* pb_type = pb_graph_node->pb_type; t_pb_graph_node* parent_node = pb_graph_node->parent_pb_graph_node; - /* TODO: think if we need to consider wire mode of LUT when creating the lb_rr_graph here! - * Should we create edges through the LUT input and output nodes? + /* TODO: think if we need to consider wire mode of LUT when creating the + * lb_rr_graph here! Should we create edges through the LUT input and output + * nodes? */ /* The only difference between primitive node and intermediate nodes is @@ -216,10 +221,12 @@ void rec_build_physical_lb_rr_edge_for_pb_graph_node(t_pb_graph_node* pb_graph_n t_mode* physical_mode = device_annotation.physical_mode(pb_type); if (true == is_primitive_pb_type(pb_type)) { - build_lb_rr_edge_primitive_pb_graph_input_pin(lb_rr_graph, pb_pin, sink_node); + build_lb_rr_edge_primitive_pb_graph_input_pin(lb_rr_graph, pb_pin, + sink_node); } else { VTR_ASSERT(false == is_primitive_pb_type(pb_type)); - build_lb_rr_edge_pb_graph_pin(lb_rr_graph, pb_pin, LB_INTERMEDIATE, physical_mode); + build_lb_rr_edge_pb_graph_pin(lb_rr_graph, pb_pin, LB_INTERMEDIATE, + physical_mode); } } } @@ -232,10 +239,12 @@ void rec_build_physical_lb_rr_edge_for_pb_graph_node(t_pb_graph_node* pb_graph_n t_mode* physical_mode = device_annotation.physical_mode(pb_type); if (true == is_primitive_pb_type(pb_type)) { - build_lb_rr_edge_primitive_pb_graph_input_pin(lb_rr_graph, pb_pin, sink_node); + build_lb_rr_edge_primitive_pb_graph_input_pin(lb_rr_graph, pb_pin, + sink_node); } else { VTR_ASSERT(false == is_primitive_pb_type(pb_type)); - build_lb_rr_edge_pb_graph_pin(lb_rr_graph, pb_pin, LB_INTERMEDIATE, physical_mode); + build_lb_rr_edge_pb_graph_pin(lb_rr_graph, pb_pin, LB_INTERMEDIATE, + physical_mode); } } } @@ -252,52 +261,65 @@ void rec_build_physical_lb_rr_edge_for_pb_graph_node(t_pb_graph_node* pb_graph_n t_pb_graph_pin* pb_pin = &pb_graph_node->output_pins[iport][ipin]; if (true == pb_graph_node->is_root()) { - build_lb_rr_edge_root_pb_graph_pin(lb_rr_graph, pb_pin, output_pin_rr_type, ext_rr_index); + build_lb_rr_edge_root_pb_graph_pin(lb_rr_graph, pb_pin, + output_pin_rr_type, ext_rr_index); } else { VTR_ASSERT(false == pb_graph_node->is_root()); - t_mode* physical_mode = device_annotation.physical_mode(parent_node->pb_type); - build_lb_rr_edge_pb_graph_pin(lb_rr_graph, pb_pin, output_pin_rr_type, physical_mode); + t_mode* physical_mode = + device_annotation.physical_mode(parent_node->pb_type); + build_lb_rr_edge_pb_graph_pin(lb_rr_graph, pb_pin, output_pin_rr_type, + physical_mode); } } } if (true == is_primitive_pb_type(pb_type)) { - return; + return; } - /* For non-primitive node: - * This pb_graph_node is a logic block or subcluster - * Go recusrively + /* For non-primitive node: + * This pb_graph_node is a logic block or subcluster + * Go recusrively */ - t_mode* physical_mode = device_annotation.physical_mode(pb_graph_node->pb_type); - for (int ipb_type = 0; ipb_type < physical_mode->num_pb_type_children; ipb_type++) { - for (int ipb = 0; ipb < physical_mode->pb_type_children[ipb_type].num_pb; ipb++) { - rec_build_physical_lb_rr_edge_for_pb_graph_node(&(pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb_type][ipb]), lb_rr_graph, ext_rr_index, device_annotation); + t_mode* physical_mode = + device_annotation.physical_mode(pb_graph_node->pb_type); + for (int ipb_type = 0; ipb_type < physical_mode->num_pb_type_children; + ipb_type++) { + for (int ipb = 0; ipb < physical_mode->pb_type_children[ipb_type].num_pb; + ipb++) { + rec_build_physical_lb_rr_edge_for_pb_graph_node( + &(pb_graph_node + ->child_pb_graph_nodes[physical_mode->index][ipb_type][ipb]), + lb_rr_graph, ext_rr_index, device_annotation); } } } /*************************************************************************************** - * This functio will create a physical lb_rr_graph for a pb_graph considering physical modes only + * This functio will create a physical lb_rr_graph for a pb_graph considering + *physical modes only ***************************************************************************************/ -static -LbRRGraph build_lb_type_physical_lb_rr_graph(t_pb_graph_node* pb_graph_head, - const VprDeviceAnnotation& device_annotation, - const bool& verbose) { +static LbRRGraph build_lb_type_physical_lb_rr_graph( + t_pb_graph_node* pb_graph_head, const VprDeviceAnnotation& device_annotation, + const bool& verbose) { LbRRGraph lb_rr_graph; /* TODO: ensure we have an empty lb_rr_graph */ - /* Define the external source, sink, and external interconnect for the routing resource graph of the logic block type */ - LbRRNodeId ext_source_index = lb_rr_graph.create_node(LB_SOURCE); - LbRRNodeId ext_sink_index = lb_rr_graph.create_node(LB_SINK); - LbRRNodeId ext_rr_index = lb_rr_graph.create_node(LB_INTERMEDIATE); + /* Define the external source, sink, and external interconnect for the routing + * resource graph of the logic block type */ + LbRRNodeId ext_source_index = lb_rr_graph.create_node(LB_SOURCE); + LbRRNodeId ext_sink_index = lb_rr_graph.create_node(LB_SINK); + LbRRNodeId ext_rr_index = lb_rr_graph.create_node(LB_INTERMEDIATE); - /* Build the main body of lb rr_graph by walking through the pb_graph recursively */ + /* Build the main body of lb rr_graph by walking through the pb_graph + * recursively */ /* Build all the regular nodes first */ - rec_build_physical_lb_rr_node_for_pb_graph_node(pb_graph_head, lb_rr_graph, device_annotation); + rec_build_physical_lb_rr_node_for_pb_graph_node(pb_graph_head, lb_rr_graph, + device_annotation); /* Build all the edges and special node (SOURCE/SINK) */ - rec_build_physical_lb_rr_edge_for_pb_graph_node(pb_graph_head, lb_rr_graph, ext_rr_index, device_annotation); + rec_build_physical_lb_rr_edge_for_pb_graph_node( + pb_graph_head, lb_rr_graph, ext_rr_index, device_annotation); /******************************************************************************* * Build logic block source node @@ -305,22 +327,27 @@ LbRRGraph build_lb_type_physical_lb_rr_graph(t_pb_graph_node* pb_graph_head, t_pb_type* pb_type = pb_graph_head->pb_type; /* External source node drives all inputs going into logic block type */ - lb_rr_graph.set_node_capacity(ext_source_index, pb_type->num_input_pins + pb_type->num_clock_pins); + lb_rr_graph.set_node_capacity( + ext_source_index, pb_type->num_input_pins + pb_type->num_clock_pins); for (int iport = 0; iport < pb_graph_head->num_input_ports; iport++) { for (int ipin = 0; ipin < pb_graph_head->num_input_pins[iport]; ipin++) { - LbRRNodeId to_node = lb_rr_graph.find_node(LB_INTERMEDIATE, &(pb_graph_head->input_pins[iport][ipin])); + LbRRNodeId to_node = lb_rr_graph.find_node( + LB_INTERMEDIATE, &(pb_graph_head->input_pins[iport][ipin])); VTR_ASSERT(true == lb_rr_graph.valid_node_id(to_node)); - LbRREdgeId edge = lb_rr_graph.create_edge(ext_source_index, to_node, nullptr); + LbRREdgeId edge = + lb_rr_graph.create_edge(ext_source_index, to_node, nullptr); lb_rr_graph.set_edge_intrinsic_cost(edge, 1.); } } for (int iport = 0; iport < pb_graph_head->num_clock_ports; iport++) { for (int ipin = 0; ipin < pb_graph_head->num_clock_pins[iport]; ipin++) { - LbRRNodeId to_node = lb_rr_graph.find_node(LB_INTERMEDIATE, &(pb_graph_head->clock_pins[iport][ipin])); + LbRRNodeId to_node = lb_rr_graph.find_node( + LB_INTERMEDIATE, &(pb_graph_head->clock_pins[iport][ipin])); VTR_ASSERT(true == lb_rr_graph.valid_node_id(to_node)); - LbRREdgeId edge = lb_rr_graph.create_edge(ext_source_index, to_node, nullptr); + LbRREdgeId edge = + lb_rr_graph.create_edge(ext_source_index, to_node, nullptr); lb_rr_graph.set_edge_intrinsic_cost(edge, 1.); } } @@ -336,19 +363,23 @@ LbRRGraph build_lb_type_physical_lb_rr_graph(t_pb_graph_node* pb_graph_head, * Build node that approximates external interconnect *******************************************************************************/ - /* External rr node that drives all existing logic block input pins and is driven by all outputs exiting logic block type */ + /* External rr node that drives all existing logic block input pins and is + * driven by all outputs exiting logic block type */ lb_rr_graph.set_node_capacity(ext_rr_index, pb_type->num_output_pins); /* Connect opin of logic block to sink */ { - LbRREdgeId edge = lb_rr_graph.create_edge(ext_rr_index, ext_sink_index, nullptr); + LbRREdgeId edge = + lb_rr_graph.create_edge(ext_rr_index, ext_sink_index, nullptr); lb_rr_graph.set_edge_intrinsic_cost(edge, 1.); } - /* Connect opin of logic block to all input and clock pins of logic block type */ + /* Connect opin of logic block to all input and clock pins of logic block type + */ for (int iport = 0; iport < pb_graph_head->num_input_ports; iport++) { for (int ipin = 0; ipin < pb_graph_head->num_input_pins[iport]; ipin++) { - LbRRNodeId to_node = lb_rr_graph.find_node(LB_INTERMEDIATE, &(pb_graph_head->input_pins[iport][ipin])); + LbRRNodeId to_node = lb_rr_graph.find_node( + LB_INTERMEDIATE, &(pb_graph_head->input_pins[iport][ipin])); VTR_ASSERT(true == lb_rr_graph.valid_node_id(to_node)); LbRREdgeId edge = lb_rr_graph.create_edge(ext_rr_index, to_node, nullptr); /* set cost high to avoid using external interconnect unless necessary */ @@ -357,7 +388,8 @@ LbRRGraph build_lb_type_physical_lb_rr_graph(t_pb_graph_node* pb_graph_head, } for (int iport = 0; iport < pb_graph_head->num_clock_ports; iport++) { for (int ipin = 0; ipin < pb_graph_head->num_clock_pins[iport]; ipin++) { - LbRRNodeId to_node = lb_rr_graph.find_node(LB_INTERMEDIATE, &(pb_graph_head->clock_pins[iport][ipin])); + LbRRNodeId to_node = lb_rr_graph.find_node( + LB_INTERMEDIATE, &(pb_graph_head->clock_pins[iport][ipin])); VTR_ASSERT(true == lb_rr_graph.valid_node_id(to_node)); LbRREdgeId edge = lb_rr_graph.create_edge(ext_rr_index, to_node, nullptr); /* set cost high to avoid using external interconnect unless necessary */ @@ -365,25 +397,23 @@ LbRRGraph build_lb_type_physical_lb_rr_graph(t_pb_graph_node* pb_graph_head, } } - VTR_LOGV(verbose, - "\n\tNumber of nodes: %lu\n", - lb_rr_graph.nodes().size()); + VTR_LOGV(verbose, "\n\tNumber of nodes: %lu\n", lb_rr_graph.nodes().size()); - VTR_LOGV(verbose, - "\tNumber of edges: %lu\n", - lb_rr_graph.edges().size()); + VTR_LOGV(verbose, "\tNumber of edges: %lu\n", lb_rr_graph.edges().size()); return lb_rr_graph; } /*************************************************************************************** - * This functio will create physical lb_rr_graph for each pb_graph considering physical modes only - * the lb_rr_graph willbe added to device annotation + * This functio will create physical lb_rr_graph for each pb_graph considering + *physical modes only the lb_rr_graph willbe added to device annotation ***************************************************************************************/ void build_physical_lb_rr_graphs(const DeviceContext& device_ctx, VprDeviceAnnotation& device_annotation, const bool& verbose) { - vtr::ScopedStartFinishTimer timer("Build routing resource graph for the physical implementation of logical tile"); + vtr::ScopedStartFinishTimer timer( + "Build routing resource graph for the physical implementation of logical " + "tile"); for (const t_logical_block_type& lb_type : device_ctx.logical_block_types) { /* By pass nullptr for pb_graph head */ @@ -395,7 +425,9 @@ void build_physical_lb_rr_graphs(const DeviceContext& device_ctx, "Building routing resource graph for logical tile '%s'...", lb_type.pb_graph_head->pb_type->name); - const LbRRGraph& lb_rr_graph = build_lb_type_physical_lb_rr_graph(lb_type.pb_graph_head, const_cast(device_annotation), verbose); + const LbRRGraph& lb_rr_graph = build_lb_type_physical_lb_rr_graph( + lb_type.pb_graph_head, + const_cast(device_annotation), verbose); /* Check the rr_graph */ if (false == lb_rr_graph.validate()) { exit(1); @@ -403,10 +435,10 @@ void build_physical_lb_rr_graphs(const DeviceContext& device_ctx, if (false == check_lb_rr_graph(lb_rr_graph)) { exit(1); } - VTR_LOGV(verbose, - "Check routing resource graph for logical tile passed\n"); + VTR_LOGV(verbose, "Check routing resource graph for logical tile passed\n"); - device_annotation.add_physical_lb_rr_graph(lb_type.pb_graph_head, lb_rr_graph); + device_annotation.add_physical_lb_rr_graph(lb_type.pb_graph_head, + lb_rr_graph); } VTR_LOGV(verbose, "Done\n"); diff --git a/openfpga/src/repack/build_physical_truth_table.cpp b/openfpga/src/repack/build_physical_truth_table.cpp index 4876c66dd..86a2c7aa4 100644 --- a/openfpga/src/repack/build_physical_truth_table.cpp +++ b/openfpga/src/repack/build_physical_truth_table.cpp @@ -4,16 +4,15 @@ ***************************************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" -#include "vtr_assert.h" -#include "vtr_time.h" - -#include "openfpga_naming.h" +#include "build_physical_truth_table.h" #include "lut_utils.h" +#include "openfpga_naming.h" #include "pb_type_utils.h" #include "physical_pb.h" -#include "build_physical_truth_table.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" /* begin namespace openfpga */ namespace openfpga { @@ -21,42 +20,50 @@ namespace openfpga { /*************************************************************************************** * Create pin rotation map for a LUT ***************************************************************************************/ -static -std::vector generate_lut_rotated_input_pin_map(const std::vector& input_nets, - const AtomContext& atom_ctx, - const AtomBlockId& atom_blk, - const VprDeviceAnnotation& device_annotation, - const CircuitLibrary& circuit_lib, - const t_pb_graph_node* pb_graph_node) { +static std::vector generate_lut_rotated_input_pin_map( + const std::vector& input_nets, const AtomContext& atom_ctx, + const AtomBlockId& atom_blk, const VprDeviceAnnotation& device_annotation, + const CircuitLibrary& circuit_lib, const t_pb_graph_node* pb_graph_node) { /* Find the pin rotation status and record it , - * Note that some LUT inputs may not be used, we set them to be open by default + * Note that some LUT inputs may not be used, we set them to be open by + * default */ std::vector rotated_pin_map(input_nets.size(), -1); for (int iport = 0; iport < pb_graph_node->num_input_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) { /* Skip the input pin that do not drive by LUT MUXes */ - CircuitPortId circuit_port = device_annotation.pb_circuit_port(pb_graph_node->input_pins[iport][ipin].port); + CircuitPortId circuit_port = device_annotation.pb_circuit_port( + pb_graph_node->input_pins[iport][ipin].port); if (true == circuit_lib.port_is_harden_lut_port(circuit_port)) { continue; } - /* The lut pb_graph_node may not be the primitive node + /* The lut pb_graph_node may not be the primitive node * because VPR adds two default modes to its LUT pb_type * If so, we will use the LUT mode of the pb_graph node */ - t_port* lut_pb_type_in_port = pb_graph_node->input_pins[iport][ipin].port; + t_port* lut_pb_type_in_port = pb_graph_node->input_pins[iport][ipin].port; if (0 != pb_graph_node->pb_type->num_modes) { VTR_ASSERT(2 == pb_graph_node->pb_type->num_modes); - VTR_ASSERT(1 == pb_graph_node->pb_type->modes[VPR_PB_TYPE_LUT_MODE].num_pb_type_children); - lut_pb_type_in_port = &(pb_graph_node->pb_type->modes[VPR_PB_TYPE_LUT_MODE].pb_type_children[0].ports[iport]); - VTR_ASSERT(std::string(lut_pb_type_in_port->name) == std::string(pb_graph_node->input_pins[iport][ipin].port->name)); - VTR_ASSERT(lut_pb_type_in_port->num_pins == pb_graph_node->input_pins[iport][ipin].port->num_pins); + VTR_ASSERT(1 == pb_graph_node->pb_type->modes[VPR_PB_TYPE_LUT_MODE] + .num_pb_type_children); + lut_pb_type_in_port = + &(pb_graph_node->pb_type->modes[VPR_PB_TYPE_LUT_MODE] + .pb_type_children[0] + .ports[iport]); + VTR_ASSERT( + std::string(lut_pb_type_in_port->name) == + std::string(pb_graph_node->input_pins[iport][ipin].port->name)); + VTR_ASSERT(lut_pb_type_in_port->num_pins == + pb_graph_node->input_pins[iport][ipin].port->num_pins); } - /* Port exists (some LUTs may have no input and hence no port in the atom netlist) */ - AtomPortId atom_port = atom_ctx.nlist.find_atom_port(atom_blk, lut_pb_type_in_port->model_port); - if (!atom_port) { + /* Port exists (some LUTs may have no input and hence no port in the atom + * netlist) */ + AtomPortId atom_port = atom_ctx.nlist.find_atom_port( + atom_blk, lut_pb_type_in_port->model_port); + if (!atom_port) { continue; } @@ -73,21 +80,19 @@ std::vector generate_lut_rotated_input_pin_map(const std::vector } /*************************************************************************************** - * This function will iterate over all the inputs and outputs of the LUT pb + * This function will iterate over all the inputs and outputs of the LUT pb * and find truth tables that are mapped to each output pins * Note that a physical LUT may have multiple truth tables to be considered * as they may be fracturable ***************************************************************************************/ -static -void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb, - const PhysicalPbId& lut_pb_id, - const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, - const CircuitLibrary& circuit_lib, - const bool& verbose) { +static void build_physical_pb_lut_truth_tables( + PhysicalPb& physical_pb, const PhysicalPbId& lut_pb_id, + const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, + const CircuitLibrary& circuit_lib, const bool& verbose) { const t_pb_graph_node* pb_graph_node = physical_pb.pb_graph_node(lut_pb_id); - CircuitModelId lut_model = device_annotation.pb_type_circuit_model(physical_pb.pb_graph_node(lut_pb_id)->pb_type); + CircuitModelId lut_model = device_annotation.pb_type_circuit_model( + physical_pb.pb_graph_node(lut_pb_id)->pb_type); VTR_ASSERT(CIRCUIT_MODEL_LUT == circuit_lib.model_type(lut_model)); /* Find all the nets mapped to each inputs */ @@ -95,25 +100,30 @@ void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb, for (int iport = 0; iport < pb_graph_node->num_input_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) { /* Skip the input pin that do not drive by LUT MUXes */ - CircuitPortId circuit_port = device_annotation.pb_circuit_port(pb_graph_node->input_pins[iport][ipin].port); + CircuitPortId circuit_port = device_annotation.pb_circuit_port( + pb_graph_node->input_pins[iport][ipin].port); if (true == circuit_lib.port_is_harden_lut_port(circuit_port)) { continue; } - input_nets.push_back(physical_pb.pb_graph_pin_atom_net(lut_pb_id, &(pb_graph_node->input_pins[iport][ipin]))); + input_nets.push_back(physical_pb.pb_graph_pin_atom_net( + lut_pb_id, &(pb_graph_node->input_pins[iport][ipin]))); } } /* Find all the nets mapped to each outputs */ for (int iport = 0; iport < pb_graph_node->num_output_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ++ipin) { - const t_pb_graph_pin* output_pin = &(pb_graph_node->output_pins[iport][ipin]); + const t_pb_graph_pin* output_pin = + &(pb_graph_node->output_pins[iport][ipin]); /* Skip the output ports that are not driven by LUT MUXes */ - CircuitPortId circuit_port = device_annotation.pb_circuit_port(output_pin->port); + CircuitPortId circuit_port = + device_annotation.pb_circuit_port(output_pin->port); if (true == circuit_lib.port_is_harden_lut_port(circuit_port)) { continue; } - AtomNetId output_net = physical_pb.pb_graph_pin_atom_net(lut_pb_id, output_pin); + AtomNetId output_net = + physical_pb.pb_graph_pin_atom_net(lut_pb_id, output_pin); /* Bypass unmapped pins */ if (AtomNetId::INVALID() == output_net) { continue; @@ -121,45 +131,61 @@ void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb, /* Check if this is a LUT used as wiring */ AtomNetlist::TruthTable adapt_tt; if (true == physical_pb.is_wire_lut_output(lut_pb_id, output_pin)) { - /* Double check: ensure that the output nets appear in the input net !!! */ + /* Double check: ensure that the output nets appear in the input net !!! + */ if (!is_wired_lut(input_nets, output_net)) { VTR_LOGV(verbose, "Pb id: \'%lu\', output pin: \'%s\'\n", - size_t(lut_pb_id), - output_pin->to_string().c_str()); - VTR_LOGV(verbose, "Input nets:\n"); + size_t(lut_pb_id), output_pin->to_string().c_str()); + VTR_LOGV(verbose, "Input nets:\n"); for (auto input_net : input_nets) { - VTR_LOGV(verbose, "\t%s\n", atom_ctx.nlist.net_name(input_net).c_str()); + VTR_LOGV(verbose, "\t%s\n", + atom_ctx.nlist.net_name(input_net).c_str()); } - VTR_LOGV(verbose, "Output nets:\n"); - VTR_LOGV(verbose, "\t%s\n", atom_ctx.nlist.net_name(output_net).c_str()); + VTR_LOGV(verbose, "Output nets:\n"); + VTR_LOGV(verbose, "\t%s\n", + atom_ctx.nlist.net_name(output_net).c_str()); } VTR_ASSERT(true == is_wired_lut(input_nets, output_net)); - adapt_tt = build_wired_lut_truth_table(input_nets.size(), std::find(input_nets.begin(), input_nets.end(), output_net) - input_nets.begin()); + adapt_tt = build_wired_lut_truth_table( + input_nets.size(), + std::find(input_nets.begin(), input_nets.end(), output_net) - + input_nets.begin()); } else { /* Find the truth table from atom block which drives the atom net */ - const AtomBlockId& atom_blk = atom_ctx.nlist.net_driver_block(output_net); + const AtomBlockId& atom_blk = + atom_ctx.nlist.net_driver_block(output_net); VTR_ASSERT(true == atom_ctx.nlist.valid_block_id(atom_blk)); - const AtomNetlist::TruthTable& orig_tt = atom_ctx.nlist.block_truth_table(atom_blk); + const AtomNetlist::TruthTable& orig_tt = + atom_ctx.nlist.block_truth_table(atom_blk); - std::vector rotated_pin_map = generate_lut_rotated_input_pin_map(input_nets, atom_ctx, atom_blk, device_annotation, circuit_lib, pb_graph_node); + std::vector rotated_pin_map = generate_lut_rotated_input_pin_map( + input_nets, atom_ctx, atom_blk, device_annotation, circuit_lib, + pb_graph_node); adapt_tt = lut_truth_table_adaption(orig_tt, rotated_pin_map); VTR_LOGV(verbose, "Driver atom block: '%ld'\n", size_t(atom_blk)); VTR_LOGV(verbose, "Pb atom blocks:"); - for (const AtomBlockId& pb_atom_blk : physical_pb.atom_blocks(lut_pb_id)) { + for (const AtomBlockId& pb_atom_blk : + physical_pb.atom_blocks(lut_pb_id)) { VTR_LOGV(verbose, "'%ld', ", size_t(pb_atom_blk)); } VTR_LOGV(verbose, "\n"); } - /* Adapt the truth table for fracturable lut implementation and add to physical pb */ - CircuitPortId lut_model_output_port = device_annotation.pb_circuit_port(output_pin->port); - size_t lut_frac_level = circuit_lib.port_lut_frac_level(lut_model_output_port); + /* Adapt the truth table for fracturable lut implementation and add to + * physical pb */ + CircuitPortId lut_model_output_port = + device_annotation.pb_circuit_port(output_pin->port); + size_t lut_frac_level = + circuit_lib.port_lut_frac_level(lut_model_output_port); if (size_t(-1) == lut_frac_level) { lut_frac_level = input_nets.size(); } - size_t lut_output_mask = circuit_lib.port_lut_output_mask(lut_model_output_port)[output_pin->pin_number]; - const AtomNetlist::TruthTable& frac_lut_tt = adapt_truth_table_for_frac_lut(lut_frac_level, lut_output_mask, adapt_tt); + size_t lut_output_mask = circuit_lib.port_lut_output_mask( + lut_model_output_port)[output_pin->pin_number]; + const AtomNetlist::TruthTable& frac_lut_tt = + adapt_truth_table_for_frac_lut(lut_frac_level, lut_output_mask, + adapt_tt); physical_pb.set_truth_table(lut_pb_id, output_pin, frac_lut_tt); /* Print debug information */ @@ -175,16 +201,15 @@ void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb, VTR_LOGV(verbose, "\n"); VTR_ASSERT(AtomNetId::INVALID() != output_net); - VTR_LOGV(verbose, "Output net: %s\n", atom_ctx.nlist.net_name(output_net).c_str()); + VTR_LOGV(verbose, "Output net: %s\n", + atom_ctx.nlist.net_name(output_net).c_str()); - VTR_LOGV(verbose, - "Truth table before adaption to fracturable LUT'\n"); + VTR_LOGV(verbose, "Truth table before adaption to fracturable LUT'\n"); for (const std::string& tt_line : truth_table_to_string(adapt_tt)) { VTR_LOGV(verbose, "\t%s\n", tt_line.c_str()); } - VTR_LOGV(verbose, - "Add following truth table to pb_graph_pin '%s[%d]'\n", + VTR_LOGV(verbose, "Add following truth table to pb_graph_pin '%s[%d]'\n", output_pin->port->name, output_pin->pin_number); for (const std::string& tt_line : truth_table_to_string(frac_lut_tt)) { VTR_LOGV(verbose, "\t%s\n", tt_line.c_str()); @@ -202,26 +227,29 @@ void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb, * netlists in VPR context. We consider fracturable LUT features * and LUTs operating as wires ***************************************************************************************/ -void build_physical_lut_truth_tables(VprClusteringAnnotation& cluster_annotation, - const AtomContext& atom_ctx, - const ClusteringContext& cluster_ctx, - const VprDeviceAnnotation& device_annotation, - const CircuitLibrary& circuit_lib, - const bool& verbose) { +void build_physical_lut_truth_tables( + VprClusteringAnnotation& cluster_annotation, const AtomContext& atom_ctx, + const ClusteringContext& cluster_ctx, + const VprDeviceAnnotation& device_annotation, + const CircuitLibrary& circuit_lib, const bool& verbose) { vtr::ScopedStartFinishTimer timer("Build truth tables for physical LUTs"); for (auto blk_id : cluster_ctx.clb_nlist.blocks()) { PhysicalPb& physical_pb = cluster_annotation.mutable_physical_pb(blk_id); /* Find the LUT physical pb id */ for (const PhysicalPbId& primitive_pb : physical_pb.primitive_pbs()) { - CircuitModelId circuit_model = device_annotation.pb_type_circuit_model(physical_pb.pb_graph_node(primitive_pb)->pb_type); + CircuitModelId circuit_model = device_annotation.pb_type_circuit_model( + physical_pb.pb_graph_node(primitive_pb)->pb_type); VTR_ASSERT(true == circuit_lib.valid_model_id(circuit_model)); if (CIRCUIT_MODEL_LUT != circuit_lib.model_type(circuit_model)) { continue; } - - /* Reach here, we have a LUT to deal with. Find the truth tables that mapped to the LUT */ - build_physical_pb_lut_truth_tables(physical_pb, primitive_pb, atom_ctx, device_annotation, circuit_lib, verbose); + + /* Reach here, we have a LUT to deal with. Find the truth tables that + * mapped to the LUT */ + build_physical_pb_lut_truth_tables(physical_pb, primitive_pb, atom_ctx, + device_annotation, circuit_lib, + verbose); } } } diff --git a/openfpga/src/repack/build_physical_truth_table.h b/openfpga/src/repack/build_physical_truth_table.h index ecd4daad5..09883a55d 100644 --- a/openfpga/src/repack/build_physical_truth_table.h +++ b/openfpga/src/repack/build_physical_truth_table.h @@ -4,11 +4,11 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ +#include "circuit_library.h" +#include "vpr_bitstream_annotation.h" +#include "vpr_clustering_annotation.h" #include "vpr_context.h" #include "vpr_device_annotation.h" -#include "vpr_clustering_annotation.h" -#include "vpr_bitstream_annotation.h" -#include "circuit_library.h" /******************************************************************** * Function declaration @@ -17,12 +17,11 @@ /* begin namespace openfpga */ namespace openfpga { -void build_physical_lut_truth_tables(VprClusteringAnnotation& cluster_annotation, - const AtomContext& atom_ctx, - const ClusteringContext& cluster_ctx, - const VprDeviceAnnotation& device_annotation, - const CircuitLibrary& circuit_lib, - const bool& verbose); +void build_physical_lut_truth_tables( + VprClusteringAnnotation& cluster_annotation, const AtomContext& atom_ctx, + const ClusteringContext& cluster_ctx, + const VprDeviceAnnotation& device_annotation, + const CircuitLibrary& circuit_lib, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/repack/check_lb_rr_graph.cpp b/openfpga/src/repack/check_lb_rr_graph.cpp index 1f8a7e9c8..058f24fc3 100644 --- a/openfpga/src/repack/check_lb_rr_graph.cpp +++ b/openfpga/src/repack/check_lb_rr_graph.cpp @@ -1,20 +1,21 @@ +#include "check_lb_rr_graph.h" + #include -#include "vtr_log.h" - #include "lb_rr_graph_utils.h" -#include "check_lb_rr_graph.h" +#include "vtr_log.h" /* begin namespace openfpga */ namespace openfpga { -/*********************************************************************** - * This function aims at checking any duplicated edges (with same EdgeId) - * of a given node. - * We will walkthrough the input edges of a node and see if there is any duplication +/*********************************************************************** + * This function aims at checking any duplicated edges (with same EdgeId) + * of a given node. + * We will walkthrough the input edges of a node and see if there is any + *duplication **********************************************************************/ -static bool check_lb_rr_graph_node_duplicated_edges(const LbRRGraph& lb_rr_graph, - const LbRRNodeId& node) { +static bool check_lb_rr_graph_node_duplicated_edges( + const LbRRGraph& lb_rr_graph, const LbRRNodeId& node) { bool no_duplication = true; /* Create a map for each input edge */ @@ -25,7 +26,8 @@ static bool check_lb_rr_graph_node_duplicated_edges(const LbRRGraph& lb_rr_graph if (nullptr == lb_rr_graph.edge_mode(edge)) { continue; } - auto result = edge_counter[lb_rr_graph.edge_mode(edge)].insert(std::pair(edge, 1)); + auto result = edge_counter[lb_rr_graph.edge_mode(edge)].insert( + std::pair(edge, 1)); if (false == result.second) { result.first->second++; } @@ -34,10 +36,11 @@ static bool check_lb_rr_graph_node_duplicated_edges(const LbRRGraph& lb_rr_graph for (auto& edge_mode : edge_counter) { for (auto& elem : edge_mode.second) { if (elem.second > 1) { - /* Reach here it means we find some duplicated edges and report errors */ + /* Reach here it means we find some duplicated edges and report errors + */ /* Print a warning! */ VTR_LOG_WARN("Node %d has duplicated input edges (id = %d)!\n", - size_t(node), size_t(elem.first)); + size_t(node), size_t(elem.first)); print_lb_rr_node(lb_rr_graph, node); no_duplication = false; } @@ -47,14 +50,14 @@ static bool check_lb_rr_graph_node_duplicated_edges(const LbRRGraph& lb_rr_graph return no_duplication; } -/*********************************************************************** - * Check the whole Routing Resource Graph - * identify and report any duplicated edges between two nodes +/*********************************************************************** + * Check the whole Routing Resource Graph + * identify and report any duplicated edges between two nodes **********************************************************************/ static bool check_lb_rr_graph_duplicated_edges(const LbRRGraph& lb_rr_graph) { bool no_duplication = true; /* For each node: - * Search input edges, see there are two edges with same id or address + * Search input edges, see there are two edges with same id or address */ for (const auto& node : lb_rr_graph.nodes()) { if (false == check_lb_rr_graph_node_duplicated_edges(lb_rr_graph, node)) { @@ -65,23 +68,23 @@ static bool check_lb_rr_graph_duplicated_edges(const LbRRGraph& lb_rr_graph) { return no_duplication; } -/*********************************************************************** +/*********************************************************************** * Identify and report any dangling node (nodes without any fan-in or fan-out) * in the LbRRGraph **********************************************************************/ static bool check_lb_rr_graph_dangling_nodes(const LbRRGraph& lb_rr_graph) { bool no_dangling = true; - /* For each node: + /* For each node: * check if the number of input edges and output edges are both 0 - * If so, this is a dangling nodes and report + * If so, this is a dangling nodes and report */ for (auto node : lb_rr_graph.nodes()) { /* Bypass 0-capacity node; They can be dangling */ if (0 == lb_rr_graph.node_capacity(node)) { continue; } - if ((0 == lb_rr_graph.node_in_edges(node).size()) - && (0 == lb_rr_graph.node_out_edges(node).size())) { + if ((0 == lb_rr_graph.node_in_edges(node).size()) && + (0 == lb_rr_graph.node_out_edges(node).size())) { /* Print a warning! */ VTR_LOG_WARN("Node %lu is dangling (zero fan-in and zero fan-out)!\n", size_t(node)); @@ -94,15 +97,15 @@ static bool check_lb_rr_graph_dangling_nodes(const LbRRGraph& lb_rr_graph) { return no_dangling; } -/*********************************************************************** +/*********************************************************************** * check if all the source nodes are in the right condition: * 1. zero fan-in and non-zero fanout **********************************************************************/ static bool check_lb_rr_graph_source_nodes(const LbRRGraph& lb_rr_graph) { bool invalid_sources = false; - /* For each node: + /* For each node: * check if the number of input edges and output edges are both 0 - * If so, this is a dangling nodes and report + * If so, this is a dangling nodes and report */ for (auto node : lb_rr_graph.nodes()) { /* Pass nodes whose types are not LB_SOURCE */ @@ -113,11 +116,13 @@ static bool check_lb_rr_graph_source_nodes(const LbRRGraph& lb_rr_graph) { if (0 == lb_rr_graph.node_capacity(node)) { continue; } - if ((0 != lb_rr_graph.node_in_edges(node).size()) - || (0 == lb_rr_graph.node_out_edges(node).size())) { + if ((0 != lb_rr_graph.node_in_edges(node).size()) || + (0 == lb_rr_graph.node_out_edges(node).size())) { /* Print a warning! */ - VTR_LOG_WARN("Source node %d is invalid (should have zero fan-in and non-zero fan-out)!\n", - size_t(node)); + VTR_LOG_WARN( + "Source node %d is invalid (should have zero fan-in and non-zero " + "fan-out)!\n", + size_t(node)); VTR_LOG_WARN("Node details for debugging:\n"); print_lb_rr_node(lb_rr_graph, node); invalid_sources = true; @@ -127,15 +132,15 @@ static bool check_lb_rr_graph_source_nodes(const LbRRGraph& lb_rr_graph) { return !invalid_sources; } -/*********************************************************************** +/*********************************************************************** * check if all the sink nodes are in the right condition: * 1. non-zero fan-in and zero fanout **********************************************************************/ static bool check_lb_rr_graph_sink_nodes(const LbRRGraph& lb_rr_graph) { bool invalid_sinks = false; - /* For each node: + /* For each node: * check if the number of input edges and output edges are both 0 - * If so, this is a dangling nodes and report + * If so, this is a dangling nodes and report */ for (auto node : lb_rr_graph.nodes()) { /* Pass nodes whose types are not LB_SINK */ @@ -146,11 +151,13 @@ static bool check_lb_rr_graph_sink_nodes(const LbRRGraph& lb_rr_graph) { if (0 == lb_rr_graph.node_capacity(node)) { continue; } - if ((0 == lb_rr_graph.node_in_edges(node).size()) - || (0 != lb_rr_graph.node_out_edges(node).size())) { + if ((0 == lb_rr_graph.node_in_edges(node).size()) || + (0 != lb_rr_graph.node_out_edges(node).size())) { /* Print a warning! */ - VTR_LOG_WARN("Sink node %s is invalid (should have non-zero fan-in and zero fan-out)!\n", - node); + VTR_LOG_WARN( + "Sink node %s is invalid (should have non-zero fan-in and zero " + "fan-out)!\n", + node); VTR_LOG_WARN("Node details for debugging:\n"); print_lb_rr_node(lb_rr_graph, node); invalid_sinks = true; @@ -160,16 +167,16 @@ static bool check_lb_rr_graph_sink_nodes(const LbRRGraph& lb_rr_graph) { return !invalid_sinks; } -/*********************************************************************** +/*********************************************************************** * This is an advanced checker for LbRRGraph object - * Note that the checker try to report as many problems as it can. + * Note that the checker try to report as many problems as it can. * The problems may cause routing efficiency or even failures, depending * on routing algorithms. * It is strongly suggested to run this sanitizer before conducting * routing algorithms - * + * * For those who will develop customized lb_rr_graphs and routers: - * On the other hand, it is suggested that developers to create their + * On the other hand, it is suggested that developers to create their * own checking function for the lb_rr_graph, to guarantee their routers * will work properly. **********************************************************************/ @@ -198,8 +205,9 @@ bool check_lb_rr_graph(const LbRRGraph& lb_rr_graph) { /* Error out if there is any fatal errors found */ if (0 < num_err) { - VTR_LOG_WARN("Checked Logical tile Routing Resource graph with %d errors !\n", - num_err); + VTR_LOG_WARN( + "Checked Logical tile Routing Resource graph with %d errors !\n", + num_err); } return (0 == num_err); diff --git a/openfpga/src/repack/check_lb_rr_graph.h b/openfpga/src/repack/check_lb_rr_graph.h index 232fa597c..e1b84d7fa 100644 --- a/openfpga/src/repack/check_lb_rr_graph.h +++ b/openfpga/src/repack/check_lb_rr_graph.h @@ -6,7 +6,6 @@ *******************************************************************/ #include "lb_rr_graph.h" - /******************************************************************** * Function declaration *******************************************************************/ diff --git a/openfpga/src/repack/lb_router.cpp b/openfpga/src/repack/lb_router.cpp index f7be853b1..d2b16af0f 100644 --- a/openfpga/src/repack/lb_router.cpp +++ b/openfpga/src/repack/lb_router.cpp @@ -1,24 +1,24 @@ /****************************************************************************** * Memember functions for data structure LbRouter ******************************************************************************/ +#include "lb_router.h" + +#include "lb_rr_graph_utils.h" +#include "pb_type_graph.h" +#include "pb_type_utils.h" +#include "physical_types.h" +#include "vpr_error.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "physical_types.h" -#include "pb_type_graph.h" -#include "vpr_error.h" - -#include "pb_type_utils.h" -#include "lb_rr_graph_utils.h" -#include "lb_router.h" - /* begin namespace openfpga */ namespace openfpga { /************************************************** * Public Constructors *************************************************/ -LbRouter::LbRouter(const LbRRGraph& lb_rr_graph, t_logical_block_type_ptr lb_type) { +LbRouter::LbRouter(const LbRRGraph& lb_rr_graph, + t_logical_block_type_ptr lb_type) { routing_status_.resize(lb_rr_graph.nodes().size()); explored_node_tb_.resize(lb_rr_graph.nodes().size()); explore_id_index_ = 1; @@ -32,12 +32,12 @@ LbRouter::LbRouter(const LbRRGraph& lb_rr_graph, t_logical_block_type_ptr lb_typ params_.hist_fac = 0.3; is_routed_ = false; - + pres_con_fac_ = 1; } /************************************************** - * Public Accessors + * Public Accessors *************************************************/ LbRouter::net_range LbRouter::nets() const { return vtr::make_range(lb_net_ids_.begin(), lb_net_ids_.end()); @@ -45,10 +45,11 @@ LbRouter::net_range LbRouter::nets() const { AtomNetId LbRouter::net_atom_net_id(const NetId& net) const { VTR_ASSERT(true == valid_net_id(net)); - return lb_net_atom_net_ids_[net]; + return lb_net_atom_net_ids_[net]; } -std::vector LbRouter::find_congested_rr_nodes(const LbRRGraph& lb_rr_graph) const { +std::vector LbRouter::find_congested_rr_nodes( + const LbRRGraph& lb_rr_graph) const { /* Validate if the rr_graph is the one we used to initialize the router */ VTR_ASSERT(true == matched_lb_rr_graph(lb_rr_graph)); @@ -63,9 +64,7 @@ std::vector LbRouter::find_congested_rr_nodes(const LbRRGraph& lb_rr return congested_rr_nodes; } -bool LbRouter::is_routed() const { - return is_routed_; -} +bool LbRouter::is_routed() const { return is_routed_; } std::vector LbRouter::net_routed_nodes(const NetId& net) const { VTR_ASSERT(true == is_routed()); @@ -73,16 +72,16 @@ std::vector LbRouter::net_routed_nodes(const NetId& net) const { std::vector routed_nodes; - for (size_t isrc = 0; isrc < lb_net_sources_[net].size(); ++isrc) { + for (size_t isrc = 0; isrc < lb_net_sources_[net].size(); ++isrc) { t_trace* rt_tree = lb_net_rt_trees_[net][isrc]; if (nullptr == rt_tree) { return routed_nodes; } /* Walk through the routing tree of the net */ - rec_collect_trace_nodes(rt_tree, routed_nodes); + rec_collect_trace_nodes(rt_tree, routed_nodes); } - return routed_nodes; + return routed_nodes; } /************************************************** @@ -95,10 +94,10 @@ bool LbRouter::is_route_success(const LbRRGraph& lb_rr_graph) const { for (const LbRRNodeId& inode : lb_rr_graph.nodes()) { if (routing_status_[inode].occ > lb_rr_graph.node_capacity(inode)) { VTR_LOGV(lb_rr_graph.node_pb_graph_pin(inode), - "Route failed due to overuse pin '%s': occupancy '%ld' > capacity '%ld'!\n", + "Route failed due to overuse pin '%s': occupancy '%ld' > " + "capacity '%ld'!\n", lb_rr_graph.node_pb_graph_pin(inode)->to_string().c_str(), - routing_status_[inode].occ, - lb_rr_graph.node_capacity(inode)); + routing_status_[inode].occ, lb_rr_graph.node_capacity(inode)); return false; } } @@ -106,7 +105,8 @@ bool LbRouter::is_route_success(const LbRRGraph& lb_rr_graph) const { return true; } -LbRouter::t_trace* LbRouter::find_node_in_rt(t_trace* rt, const LbRRNodeId& rt_index) { +LbRouter::t_trace* LbRouter::find_node_in_rt(t_trace* rt, + const LbRRNodeId& rt_index) { t_trace* cur; if (rt->current_node == rt_index) { return rt; @@ -121,10 +121,12 @@ LbRouter::t_trace* LbRouter::find_node_in_rt(t_trace* rt, const LbRRNodeId& rt_i return nullptr; } -bool LbRouter::route_has_conflict(const LbRRGraph& lb_rr_graph, t_trace* rt) const { +bool LbRouter::route_has_conflict(const LbRRGraph& lb_rr_graph, + t_trace* rt) const { t_mode* cur_mode = nullptr; for (unsigned int i = 0; i < rt->next_nodes.size(); i++) { - std::vector edges = lb_rr_graph.find_edge(rt->current_node, rt->next_nodes[i].current_node); + std::vector edges = + lb_rr_graph.find_edge(rt->current_node, rt->next_nodes[i].current_node); VTR_ASSERT(1 == edges.size()); t_mode* new_mode = lb_rr_graph.edge_mode(edges[0]); if (cur_mode != nullptr && cur_mode != new_mode) { @@ -139,8 +141,10 @@ bool LbRouter::route_has_conflict(const LbRRGraph& lb_rr_graph, t_trace* rt) con return false; } -void LbRouter::rec_collect_trace_nodes(const t_trace* trace, std::vector& routed_nodes) const { - if (routed_nodes.end() == std::find(routed_nodes.begin(), routed_nodes.end(), trace->current_node)) { +void LbRouter::rec_collect_trace_nodes( + const t_trace* trace, std::vector& routed_nodes) const { + if (routed_nodes.end() == std::find(routed_nodes.begin(), routed_nodes.end(), + trace->current_node)) { routed_nodes.push_back(trace->current_node); } @@ -152,8 +156,9 @@ void LbRouter::rec_collect_trace_nodes(const t_trace* trace, std::vector& sources, - const std::vector& terminals) { +LbRouter::NetId LbRouter::create_net_to_route( + const std::vector& sources, + const std::vector& terminals) { /* Create an new id */ NetId net = NetId(lb_net_ids_.size()); lb_net_ids_.push_back(net); @@ -162,7 +167,7 @@ LbRouter::NetId LbRouter::create_net_to_route(const std::vector& sou lb_net_atom_net_ids_.push_back(AtomNetId::INVALID()); lb_net_atom_source_pins_.emplace_back(); lb_net_atom_sink_pins_.emplace_back(); - + lb_net_sources_.push_back(sources); lb_net_sinks_.push_back(terminals); lb_net_rt_trees_.push_back(std::vector(sources.size(), nullptr)); @@ -170,23 +175,26 @@ LbRouter::NetId LbRouter::create_net_to_route(const std::vector& sou return net; } -void LbRouter::add_net_atom_net_id(const NetId& net, const AtomNetId& atom_net) { +void LbRouter::add_net_atom_net_id(const NetId& net, + const AtomNetId& atom_net) { VTR_ASSERT(true == valid_net_id(net)); lb_net_atom_net_ids_[net] = atom_net; } -void LbRouter::add_net_atom_pins(const NetId& net, const AtomPinId& src_pin, const std::vector& terminal_pins) { +void LbRouter::add_net_atom_pins(const NetId& net, const AtomPinId& src_pin, + const std::vector& terminal_pins) { VTR_ASSERT(true == valid_net_id(net)); lb_net_atom_sink_pins_[net] = terminal_pins; lb_net_atom_source_pins_[net] = std::vector(1, src_pin); } -void LbRouter::set_physical_pb_modes(const LbRRGraph& lb_rr_graph, - const VprDeviceAnnotation& device_annotation) { +void LbRouter::set_physical_pb_modes( + const LbRRGraph& lb_rr_graph, const VprDeviceAnnotation& device_annotation) { /* Go through each node in the routing resource graph * Find the physical mode of each pb_graph_pin that is binded to the node * For input pins, the physical mode is a mode of its parent pb_type - * For output pins, the physical mode is a mode of the parent pb_type of its parent + * For output pins, the physical mode is a mode of the parent pb_type of its + * parent */ for (const LbRRNodeId& node : lb_rr_graph.nodes()) { t_pb_graph_pin* pb_pin = lb_rr_graph.node_pb_graph_pin(node); @@ -194,14 +202,16 @@ void LbRouter::set_physical_pb_modes(const LbRRGraph& lb_rr_graph, routing_status_[node].mode = nullptr; } else { if (IN_PORT == pb_pin->port->type) { - routing_status_[node].mode = device_annotation.physical_mode(pb_pin->parent_node->pb_type); + routing_status_[node].mode = + device_annotation.physical_mode(pb_pin->parent_node->pb_type); } else { VTR_ASSERT(OUT_PORT == pb_pin->port->type); /* For top-level pb_graph node, the physical mode is nullptr */ if (true == pb_pin->parent_node->is_root()) { routing_status_[node].mode = nullptr; - } else { - routing_status_[node].mode = device_annotation.physical_mode(pb_pin->parent_node->parent_pb_graph_node->pb_type); + } else { + routing_status_[node].mode = device_annotation.physical_mode( + pb_pin->parent_node->parent_pb_graph_node->pb_type); /* TODO: need to think about how to handle INOUT ports !!! */ } } @@ -209,17 +219,16 @@ void LbRouter::set_physical_pb_modes(const LbRRGraph& lb_rr_graph, } } -bool LbRouter::try_route_net(const LbRRGraph& lb_rr_graph, - const AtomNetlist& atom_nlist, - const NetId& net_idx, - t_expansion_node& exp_node, - std::unordered_map& mode_map, - const bool& verbosity) { - +bool LbRouter::try_route_net( + const LbRRGraph& lb_rr_graph, const AtomNetlist& atom_nlist, + const NetId& net_idx, t_expansion_node& exp_node, + std::unordered_map& mode_map, + const bool& verbosity) { /* Quick check: if all the net can be skipped, we return route succeed */ bool skip_route = true; for (size_t isrc = 0; isrc < lb_net_sources_[net_idx].size(); ++isrc) { - if (false == is_skip_route_net(lb_rr_graph, lb_net_rt_trees_[net_idx][isrc])) { + if (false == + is_skip_route_net(lb_rr_graph, lb_net_rt_trees_[net_idx][isrc])) { skip_route = false; break; } @@ -231,19 +240,19 @@ bool LbRouter::try_route_net(const LbRRGraph& lb_rr_graph, std::vector sink_routed(lb_net_sinks_[net_idx].size(), false); for (size_t isrc = 0; isrc < lb_net_sources_[net_idx].size(); ++isrc) { - - if (true == is_skip_route_net(lb_rr_graph, lb_net_rt_trees_[net_idx][isrc])) { + if (true == + is_skip_route_net(lb_rr_graph, lb_net_rt_trees_[net_idx][isrc])) { continue; } - commit_remove_rt(lb_rr_graph, lb_net_rt_trees_[net_idx][isrc], RT_REMOVE, mode_map); + commit_remove_rt(lb_rr_graph, lb_net_rt_trees_[net_idx][isrc], RT_REMOVE, + mode_map); free_net_rt(lb_net_rt_trees_[net_idx][isrc]); lb_net_rt_trees_[net_idx][isrc] = nullptr; add_source_to_rt(net_idx, isrc); /* Route each sink of net */ for (size_t isink = 0; isink < lb_net_sinks_[net_idx].size(); ++isink) { - /* Skip routed nets */ if (true == sink_routed[isink]) { continue; @@ -251,47 +260,57 @@ bool LbRouter::try_route_net(const LbRRGraph& lb_rr_graph, pq_.clear(); - /* Get lowest cost next node, repeat until a path is found or if it is impossible to route */ + /* Get lowest cost next node, repeat until a path is found or if it is + * impossible to route */ expand_rt(net_idx, net_idx, isrc); - /* If we managed to expand the nodes to the sink, routing for this sink is done. - * If not, we failed in routing. - * Therefore, the output of try_expand_nodes() is inverted + /* If we managed to expand the nodes to the sink, routing for this sink is + * done. If not, we failed in routing. Therefore, the output of + * try_expand_nodes() is inverted */ - sink_routed[isink] = !try_expand_nodes(atom_nlist, lb_rr_graph, net_idx, exp_node, isrc, isink, mode_status_.expand_all_modes, verbosity); + sink_routed[isink] = + !try_expand_nodes(atom_nlist, lb_rr_graph, net_idx, exp_node, isrc, + isink, mode_status_.expand_all_modes, verbosity); /* TODO: Debug codes, to be removed if (true == sink_routed[isink]) { VTR_LOGV(verbosity, - "Succeed to expand routing tree from source pin '%s' to sink pin '%s'!\n", + "Succeed to expand routing tree from source pin '%s' to sink + pin '%s'!\n", lb_rr_graph.node_pb_graph_pin(lb_net_sources_[net_idx][isrc])->to_string().c_str(), lb_rr_graph.node_pb_graph_pin(lb_net_sinks_[net_idx][isink])->to_string().c_str()); } */ /* IMPORTANT: We do not need expand all the modes for physical repack - if (false == sink_routed[isink] && false == mode_status_.expand_all_modes) { - mode_status_.try_expand_all_modes = true; - mode_status_.expand_all_modes = true; - continue; + if (false == sink_routed[isink] && false == mode_status_.expand_all_modes) + { mode_status_.try_expand_all_modes = true; mode_status_.expand_all_modes + = true; continue; } */ if (exp_node.node_index == lb_net_sinks_[net_idx][isink]) { - /* Net terminal is routed, add this to the route tree, clear data structures, and keep going */ - sink_routed[isink] = !add_to_rt(lb_net_rt_trees_[net_idx][isrc], exp_node.node_index, net_idx); + /* Net terminal is routed, add this to the route tree, clear data + * structures, and keep going */ + sink_routed[isink] = !add_to_rt(lb_net_rt_trees_[net_idx][isrc], + exp_node.node_index, net_idx); } if (false == sink_routed[isink]) { - VTR_LOGV(verbosity, - "Routing was impossible from source pin '%s' to sink pin '%s'!\n", - lb_rr_graph.node_pb_graph_pin(lb_net_sources_[net_idx][isrc])->to_string().c_str(), - lb_rr_graph.node_pb_graph_pin(lb_net_sinks_[net_idx][isink])->to_string().c_str()); + VTR_LOGV( + verbosity, + "Routing was impossible from source pin '%s' to sink pin '%s'!\n", + lb_rr_graph.node_pb_graph_pin(lb_net_sources_[net_idx][isrc]) + ->to_string() + .c_str(), + lb_rr_graph.node_pb_graph_pin(lb_net_sinks_[net_idx][isink]) + ->to_string() + .c_str()); } else if (mode_status_.expand_all_modes) { - sink_routed[isink] = !route_has_conflict(lb_rr_graph, lb_net_rt_trees_[net_idx][isrc]); + sink_routed[isink] = + !route_has_conflict(lb_rr_graph, lb_net_rt_trees_[net_idx][isrc]); if (false == sink_routed[isink]) { - VTR_LOGV(verbosity, - "Routing was impossible due to modes!\n"); + VTR_LOGV(verbosity, "Routing was impossible due to modes!\n"); } } @@ -326,9 +345,8 @@ bool LbRouter::try_route_net(const LbRRGraph& lb_rr_graph, } } - /* If any sinks are managed to be routed, we will try to save(commit) results - * to route tree. - * During this process, we will check if there is any + /* If any sinks are managed to be routed, we will try to save(commit) + * results to route tree. During this process, we will check if there is any * nodes using different modes under the same pb_type * If so, we have conflicts and routing is considered to be failure */ @@ -340,10 +358,12 @@ bool LbRouter::try_route_net(const LbRRGraph& lb_rr_graph, } } if (true == any_sink_routed) { - commit_remove_rt(lb_rr_graph, lb_net_rt_trees_[net_idx][isrc], RT_COMMIT, mode_map); + commit_remove_rt(lb_rr_graph, lb_net_rt_trees_[net_idx][isrc], RT_COMMIT, + mode_map); if (true == mode_status_.is_mode_conflict) { VTR_LOGV(verbosity, - "Route fail due to mode conflicts when commiting the routing tree!\n"); + "Route fail due to mode conflicts when commiting the routing " + "tree!\n"); for (size_t isink = 0; isink < sink_routed.size(); ++isink) { /* Change routed sinks to failure */ if (true == sink_routed[isink]) { @@ -359,9 +379,10 @@ bool LbRouter::try_route_net(const LbRRGraph& lb_rr_graph, for (size_t isink = 0; isink < sink_routed.size(); ++isink) { if (false == sink_routed[isink]) { route_succeed = false; - VTR_LOGV(verbosity, - "Routing failed for sink pin '%s'!\n", - lb_rr_graph.node_pb_graph_pin(lb_net_sinks_[net_idx][isink])->to_string().c_str()); + VTR_LOGV(verbosity, "Routing failed for sink pin '%s'!\n", + lb_rr_graph.node_pb_graph_pin(lb_net_sinks_[net_idx][isink]) + ->to_string() + .c_str()); break; } } @@ -370,8 +391,7 @@ bool LbRouter::try_route_net(const LbRRGraph& lb_rr_graph, } bool LbRouter::try_route(const LbRRGraph& lb_rr_graph, - const AtomNetlist& atom_nlist, - const bool& verbosity) { + const AtomNetlist& atom_nlist, const bool& verbosity) { /* Validate if the rr_graph is the one we used to initialize the router */ VTR_ASSERT(true == matched_lb_rr_graph(lb_rr_graph)); @@ -398,15 +418,18 @@ bool LbRouter::try_route(const LbRRGraph& lb_rr_graph, std::unordered_map mode_map; /* Iteratively remove congestion until a successful route is found. - * Cap the total number of iterations tried so that if a solution does not exist, then the router won't run indefinitely */ + * Cap the total number of iterations tried so that if a solution does not + * exist, then the router won't run indefinitely */ pres_con_fac_ = params_.pres_fac; - for (int iter = 0; iter < params_.max_iterations && !is_routed_ && !is_impossible; iter++) { + for (int iter = 0; + iter < params_.max_iterations && !is_routed_ && !is_impossible; iter++) { unsigned int inet; /* Iterate across all nets internal to logic block */ for (inet = 0; inet < lb_net_ids_.size() && !is_impossible; inet++) { NetId net_idx = NetId(inet); - if (false == try_route_net(lb_rr_graph, atom_nlist, net_idx, exp_node, mode_map, verbosity)) { + if (false == try_route_net(lb_rr_graph, atom_nlist, net_idx, exp_node, + mode_map, verbosity)) { is_impossible = true; } } @@ -415,32 +438,40 @@ bool LbRouter::try_route(const LbRRGraph& lb_rr_graph, is_routed_ = is_route_success(lb_rr_graph); } else { --inet; - VTR_LOG("Net %lu '%s' is impossible to route within proposed %s cluster\n", - inet, - atom_nlist.net_name(lb_net_atom_net_ids_[NetId(inet)]).c_str(), - lb_type_->name); - VTR_LOG("\tNet source pin:\n"); - for (size_t isrc = 0; isrc < lb_net_sources_[NetId(inet)].size(); ++isrc) { - VTR_LOG("\t\t%s\n", - lb_rr_graph.node_pb_graph_pin(lb_net_sources_[NetId(inet)][isrc])->to_string().c_str()); + VTR_LOG( + "Net %lu '%s' is impossible to route within proposed %s cluster\n", + inet, atom_nlist.net_name(lb_net_atom_net_ids_[NetId(inet)]).c_str(), + lb_type_->name); + VTR_LOG("\tNet source pin:\n"); + for (size_t isrc = 0; isrc < lb_net_sources_[NetId(inet)].size(); + ++isrc) { + VTR_LOG( + "\t\t%s\n", + lb_rr_graph.node_pb_graph_pin(lb_net_sources_[NetId(inet)][isrc]) + ->to_string() + .c_str()); } VTR_LOG("\tNet sink pins:\n"); - for (size_t isink = 0; isink < lb_net_sinks_[NetId(inet)].size(); ++isink) { - VTR_LOG("\t\t%s\n", - lb_rr_graph.node_pb_graph_pin(lb_net_sinks_[NetId(inet)][isink])->to_string().c_str()); + for (size_t isink = 0; isink < lb_net_sinks_[NetId(inet)].size(); + ++isink) { + VTR_LOG( + "\t\t%s\n", + lb_rr_graph.node_pb_graph_pin(lb_net_sinks_[NetId(inet)][isink]) + ->to_string() + .c_str()); } VTR_LOG("Please check your architecture XML to see if it is routable\n"); - + is_routed_ = false; } pres_con_fac_ *= params_.pres_fac_mult; } - /* TODO: - * Let user to decide to how proceed upon the routing results: + /* TODO: + * Let user to decide to how proceed upon the routing results: * - route success: save the results through public accessors to lb_nets_ * print the route results to files - * - route fail: report all the congestion nodes + * - route fail: report all the congestion nodes */ return is_routed_; } @@ -451,7 +482,7 @@ bool LbRouter::try_route(const LbRRGraph& lb_rr_graph, void LbRouter::fix_duplicate_equivalent_pins(const AtomContext& atom_ctx, const LbRRGraph& lb_rr_graph) { for (const NetId& ilb_net : lb_net_ids_) { - //Collect all the sink terminals indicies which target a particular node + // Collect all the sink terminals indicies which target a particular node std::map> duplicate_terminals; for (size_t iterm = 0; iterm < lb_net_sinks_[ilb_net].size(); ++iterm) { LbRRNodeId node = lb_net_sinks_[ilb_net][iterm]; @@ -460,38 +491,52 @@ void LbRouter::fix_duplicate_equivalent_pins(const AtomContext& atom_ctx, } for (auto kv : duplicate_terminals) { - if (kv.second.size() < 2) continue; //Only process duplicates + if (kv.second.size() < 2) continue; // Only process duplicates - //Remap all the duplicate terminals so they target the pin instead of the sink + // Remap all the duplicate terminals so they target the pin instead of the + // sink for (size_t idup_term = 0; idup_term < kv.second.size(); ++idup_term) { - int iterm = kv.second[idup_term]; //The index in terminals which is duplicated + int iterm = + kv.second[idup_term]; // The index in terminals which is duplicated - VTR_ASSERT(lb_net_atom_sink_pins_[ilb_net].size() == lb_net_sinks_[ilb_net].size()); + VTR_ASSERT(lb_net_atom_sink_pins_[ilb_net].size() == + lb_net_sinks_[ilb_net].size()); AtomPinId atom_pin = lb_net_atom_sink_pins_[ilb_net][iterm]; VTR_ASSERT(atom_pin); - const t_pb_graph_pin* pb_graph_pin = find_pb_graph_pin(atom_ctx.nlist, atom_ctx.lookup, atom_pin); + const t_pb_graph_pin* pb_graph_pin = + find_pb_graph_pin(atom_ctx.nlist, atom_ctx.lookup, atom_pin); VTR_ASSERT(pb_graph_pin); - if (pb_graph_pin->port->equivalent == PortEquivalence::NONE) continue; //Only need to remap equivalent ports + if (pb_graph_pin->port->equivalent == PortEquivalence::NONE) + continue; // Only need to remap equivalent ports - //Remap this terminal to an explicit pin instead of the common sink - LbRRNodeId pin_index = lb_rr_graph.find_node(LB_INTERMEDIATE, pb_graph_pin); + // Remap this terminal to an explicit pin instead of the common sink + LbRRNodeId pin_index = + lb_rr_graph.find_node(LB_INTERMEDIATE, pb_graph_pin); VTR_ASSERT(true == lb_rr_graph.valid_node_id(pin_index)); VTR_LOG_WARN( - "Found duplicate nets connected to logically equivalent pins. " - "Remapping intra lb net %d (atom net %zu '%s') from common sink " - "pb_route %d to fixed pin pb_route %d\n", - size_t(ilb_net), size_t(lb_net_atom_net_ids_[ilb_net]), atom_ctx.nlist.net_name(lb_net_atom_net_ids_[ilb_net]).c_str(), - kv.first, size_t(pin_index)); + "Found duplicate nets connected to logically equivalent pins. " + "Remapping intra lb net %d (atom net %zu '%s') from common sink " + "pb_route %d to fixed pin pb_route %d\n", + size_t(ilb_net), size_t(lb_net_atom_net_ids_[ilb_net]), + atom_ctx.nlist.net_name(lb_net_atom_net_ids_[ilb_net]).c_str(), + kv.first, size_t(pin_index)); - VTR_ASSERT(1 == lb_rr_graph.node_out_edges(pin_index, &(pb_graph_pin->parent_node->pb_type->modes[0])).size()); - LbRRNodeId sink_index = lb_rr_graph.edge_sink_node(lb_rr_graph.node_out_edges(pin_index, &(pb_graph_pin->parent_node->pb_type->modes[0]))[0]); + VTR_ASSERT( + 1 == lb_rr_graph + .node_out_edges( + pin_index, &(pb_graph_pin->parent_node->pb_type->modes[0])) + .size()); + LbRRNodeId sink_index = + lb_rr_graph.edge_sink_node(lb_rr_graph.node_out_edges( + pin_index, &(pb_graph_pin->parent_node->pb_type->modes[0]))[0]); VTR_ASSERT(LB_SINK == lb_rr_graph.node_type(sink_index)); - VTR_ASSERT_MSG(sink_index == lb_net_sinks_[ilb_net][iterm], "Remapped pin must be connected to original sink"); + VTR_ASSERT_MSG(sink_index == lb_net_sinks_[ilb_net][iterm], + "Remapped pin must be connected to original sink"); - //Change the target + // Change the target lb_net_sinks_[ilb_net][iterm] = pin_index; } } @@ -499,9 +544,9 @@ void LbRouter::fix_duplicate_equivalent_pins(const AtomContext& atom_ctx, } // Check one edge for mode conflict. -bool LbRouter::check_edge_for_route_conflicts(std::unordered_map& mode_map, - const t_pb_graph_pin* driver_pin, - const t_pb_graph_pin* pin) { +bool LbRouter::check_edge_for_route_conflicts( + std::unordered_map& mode_map, + const t_pb_graph_pin* driver_pin, const t_pb_graph_pin* pin) { if (driver_pin == nullptr) { return false; } @@ -524,24 +569,33 @@ bool LbRouter::check_edge_for_route_conflicts(std::unordered_mapsecond != mode) { - VTR_LOG("Differing modes for block. Got %s mode, while previously was %s for interconnect %s.\n", - mode->name, result.first->second->name, - edge->interconnect->name); - // The illegal mode is added to the pb_graph_node as it resulted in a conflict during atom-to-atom routing. This mode cannot be used in the consequent cluster - // generation try. + VTR_LOG( + "Differing modes for block. Got %s mode, while previously was %s for " + "interconnect %s.\n", + mode->name, result.first->second->name, edge->interconnect->name); + // The illegal mode is added to the pb_graph_node as it resulted in a + // conflict during atom-to-atom routing. This mode cannot be used in the + // consequent cluster generation try. auto it = illegal_modes_.find(pb_graph_node); if (it == illegal_modes_.end()) { illegal_modes_[pb_graph_node].push_back(result.first->second); } else { - if (std::find(illegal_modes_.at(pb_graph_node).begin(), illegal_modes_.at(pb_graph_node).end(), result.first->second) == illegal_modes_.at(pb_graph_node).end()) { + if (std::find(illegal_modes_.at(pb_graph_node).begin(), + illegal_modes_.at(pb_graph_node).end(), + result.first->second) == + illegal_modes_.at(pb_graph_node).end()) { it->second.push_back(result.first->second); } } - // If the number of illegal modes equals the number of available mode for a specific pb_graph_node it means that no cluster can be generated. This resuts - // in a fatal error. - if ((int)illegal_modes_.at(pb_graph_node).size() >= pb_graph_node->pb_type->num_modes) { - VPR_FATAL_ERROR(VPR_ERROR_PACK, "There are no more available modes to be used. Routing Failed!"); + // If the number of illegal modes equals the number of available mode for + // a specific pb_graph_node it means that no cluster can be generated. + // This resuts in a fatal error. + if ((int)illegal_modes_.at(pb_graph_node).size() >= + pb_graph_node->pb_type->num_modes) { + VPR_FATAL_ERROR( + VPR_ERROR_PACK, + "There are no more available modes to be used. Routing Failed!"); } return true; @@ -551,10 +605,9 @@ bool LbRouter::check_edge_for_route_conflicts(std::unordered_map& mode_map) { +void LbRouter::commit_remove_rt( + const LbRRGraph& lb_rr_graph, t_trace* rt, const e_commit_remove& op, + std::unordered_map& mode_map) { int incr; if (nullptr == rt) { @@ -567,7 +620,9 @@ void LbRouter::commit_remove_rt(const LbRRGraph& lb_rr_graph, if (op == RT_COMMIT) { incr = 1; if (routing_status_[inode].occ >= lb_rr_graph.node_capacity(inode)) { - routing_status_[inode].historical_usage += (routing_status_[inode].occ - lb_rr_graph.node_capacity(inode) + 1); /* store historical overuse */ + routing_status_[inode].historical_usage += + (routing_status_[inode].occ - lb_rr_graph.node_capacity(inode) + + 1); /* store historical overuse */ } } else { incr = -1; @@ -582,8 +637,8 @@ void LbRouter::commit_remove_rt(const LbRRGraph& lb_rr_graph, /* Recursively update route tree */ for (unsigned int i = 0; i < rt->next_nodes.size(); i++) { // Check to see if there is no mode conflict between previous nets. - // A conflict is present if there are differing modes between a pb_graph_node - // and its children. + // A conflict is present if there are differing modes between a + // pb_graph_node and its children. if (op == RT_COMMIT && mode_status_.try_expand_all_modes) { const LbRRNodeId& node = rt->next_nodes[i].current_node; t_pb_graph_pin* pin = lb_rr_graph.node_pb_graph_pin(node); @@ -597,8 +652,7 @@ void LbRouter::commit_remove_rt(const LbRRGraph& lb_rr_graph, } } -bool LbRouter::is_skip_route_net(const LbRRGraph& lb_rr_graph, - t_trace* rt) { +bool LbRouter::is_skip_route_net(const LbRRGraph& lb_rr_graph, t_trace* rt) { /* Validate if the rr_graph is the one we used to initialize the router */ VTR_ASSERT(true == matched_lb_rr_graph(lb_rr_graph)); @@ -625,7 +679,8 @@ bool LbRouter::is_skip_route_net(const LbRRGraph& lb_rr_graph, return true; } -bool LbRouter::add_to_rt(t_trace* rt, const LbRRNodeId& node_index, const NetId& irt_net) { +bool LbRouter::add_to_rt(t_trace* rt, const LbRRNodeId& node_index, + const NetId& irt_net) { std::vector trace_forward; t_trace* link_node; t_trace curr_node; @@ -665,8 +720,7 @@ void LbRouter::add_source_to_rt(const NetId& inet, const size_t& isrc) { lb_net_rt_trees_[inet][isrc]->current_node = lb_net_sources_[inet][isrc]; } -void LbRouter::expand_rt_rec(t_trace* rt, - const LbRRNodeId& prev_index, +void LbRouter::expand_rt_rec(t_trace* rt, const LbRRNodeId& prev_index, const NetId& irt_net, const int& explore_id_index) { t_expansion_node enode; @@ -683,22 +737,21 @@ void LbRouter::expand_rt_rec(t_trace* rt, explored_node_tb_[enode.node_index].prev_index = prev_index; for (unsigned int i = 0; i < rt->next_nodes.size(); i++) { - expand_rt_rec(&rt->next_nodes[i], rt->current_node, irt_net, explore_id_index); + expand_rt_rec(&rt->next_nodes[i], rt->current_node, irt_net, + explore_id_index); } } -void LbRouter::expand_rt(const NetId& inet, - const NetId& irt_net, +void LbRouter::expand_rt(const NetId& inet, const NetId& irt_net, const size_t& isrc) { VTR_ASSERT(pq_.empty()); - expand_rt_rec(lb_net_rt_trees_[inet][isrc], LbRRNodeId::INVALID(), irt_net, explore_id_index_); + expand_rt_rec(lb_net_rt_trees_[inet][isrc], LbRRNodeId::INVALID(), irt_net, + explore_id_index_); } -void LbRouter::expand_edges(const LbRRGraph& lb_rr_graph, - t_mode* mode, - const LbRRNodeId& cur_inode, - float cur_cost, +void LbRouter::expand_edges(const LbRRGraph& lb_rr_graph, t_mode* mode, + const LbRRNodeId& cur_inode, float cur_cost, int net_fanout) { /* Validate if the rr_graph is the one we used to initialize the router */ VTR_ASSERT(true == matched_lb_rr_graph(lb_rr_graph)); @@ -714,27 +767,34 @@ void LbRouter::expand_edges(const LbRRGraph& lb_rr_graph, enode.cost = cur_cost; /* Determine incremental cost of using expansion node */ - usage = routing_status_[enode.node_index].occ + 1 - lb_rr_graph.node_capacity(enode.node_index); + usage = routing_status_[enode.node_index].occ + 1 - + lb_rr_graph.node_capacity(enode.node_index); incr_cost = lb_rr_graph.node_intrinsic_cost(enode.node_index); incr_cost += lb_rr_graph.edge_intrinsic_cost(iedge); - incr_cost += params_.hist_fac * routing_status_[enode.node_index].historical_usage; + incr_cost += + params_.hist_fac * routing_status_[enode.node_index].historical_usage; if (usage > 0) { incr_cost *= (usage * pres_con_fac_); } - /* Adjust cost so that higher fanout nets prefer higher fanout routing nodes while lower fanout nets prefer lower fanout routing nodes */ + /* Adjust cost so that higher fanout nets prefer higher fanout routing nodes + * while lower fanout nets prefer lower fanout routing nodes */ float fanout_factor = 1.0; t_mode* next_mode = routing_status_[enode.node_index].mode; /* Assume first mode if a mode hasn't been forced. */ if (nullptr == next_mode) { - /* If the node is mapped to a nullptr pb_graph_pin, this is a special SINK. Use nullptr mode */ + /* If the node is mapped to a nullptr pb_graph_pin, this is a special + * SINK. Use nullptr mode */ if (nullptr == lb_rr_graph.node_pb_graph_pin(enode.node_index)) { next_mode = nullptr; - } else if (true == is_primitive_pb_type(lb_rr_graph.node_pb_graph_pin(enode.node_index)->parent_node->pb_type)) { - /* For primitive node, we give nullptr as default */ + } else if (true == is_primitive_pb_type( + lb_rr_graph.node_pb_graph_pin(enode.node_index) + ->parent_node->pb_type)) { + /* For primitive node, we give nullptr as default */ next_mode = nullptr; } else { - next_mode = &(lb_rr_graph.node_pb_graph_pin(enode.node_index)->parent_node->pb_type->modes[0]); + next_mode = &(lb_rr_graph.node_pb_graph_pin(enode.node_index) + ->parent_node->pb_type->modes[0]); } } if (lb_rr_graph.node_out_edges(enode.node_index, next_mode).size() > 1) { @@ -785,10 +845,13 @@ void LbRouter::expand_node(const LbRRGraph& lb_rr_graph, if (nullptr == mode) { if (nullptr == lb_rr_graph.node_pb_graph_pin(cur_node)) { mode = nullptr; - } else if (true == is_primitive_pb_type(lb_rr_graph.node_pb_graph_pin(cur_node)->parent_node->pb_type)) { + } else if (true == + is_primitive_pb_type(lb_rr_graph.node_pb_graph_pin(cur_node) + ->parent_node->pb_type)) { mode = nullptr; } else { - mode = &(lb_rr_graph.node_pb_graph_pin(cur_node)->parent_node->pb_type->modes[0]); + mode = &(lb_rr_graph.node_pb_graph_pin(cur_node) + ->parent_node->pb_type->modes[0]); } } @@ -816,12 +879,14 @@ void LbRouter::expand_node_all_modes(const LbRRGraph& lb_rr_graph, for (const LbRREdgeId& edge : lb_rr_graph.node_out_edges(cur_inode)) { t_mode* mode = lb_rr_graph.edge_mode(edge); - /* If a mode has been forced, only add edges from that mode, otherwise add edges from all modes. */ + /* If a mode has been forced, only add edges from that mode, otherwise add + * edges from all modes. */ if (cur_mode != nullptr && mode != cur_mode) { continue; } - /* Check whether a mode is illegal. If it is then the node will not be expanded */ + /* Check whether a mode is illegal. If it is then the node will not be + * expanded */ bool is_illegal = false; if (pin != nullptr) { auto* pb_graph_node = pin->parent_node; @@ -845,10 +910,8 @@ void LbRouter::expand_node_all_modes(const LbRRGraph& lb_rr_graph, bool LbRouter::try_expand_nodes(const AtomNetlist& atom_nlist, const LbRRGraph& lb_rr_graph, - const NetId& lb_net, - t_expansion_node& exp_node, - const int& isrc, - const int& itarget, + const NetId& lb_net, t_expansion_node& exp_node, + const int& isrc, const int& itarget, const bool& try_other_modes, const bool& verbosity) { bool is_impossible = false; @@ -859,19 +922,22 @@ bool LbRouter::try_expand_nodes(const AtomNetlist& atom_nlist, is_impossible = true; if (true == verbosity) { - //Print detailed debug info + // Print detailed debug info AtomNetId net_id = lb_net_atom_net_ids_[lb_net]; AtomPinId driver_pin = lb_net_atom_source_pins_[lb_net][isrc]; AtomPinId sink_pin = lb_net_atom_sink_pins_[lb_net][itarget]; LbRRNodeId driver_rr_node = lb_net_sources_[lb_net][isrc]; LbRRNodeId sink_rr_node = lb_net_sinks_[lb_net][itarget]; - VTR_LOG("\t\t\tNo possible routing path from %s to %s: needed for net '%s' from net pin '%s'", - describe_lb_rr_node(lb_rr_graph, driver_rr_node).c_str(), - describe_lb_rr_node(lb_rr_graph, sink_rr_node).c_str(), - atom_nlist.net_name(net_id).c_str(), - atom_nlist.pin_name(driver_pin).c_str()); - VTR_LOGV(sink_pin, " to net pin '%s'", atom_nlist.pin_name(sink_pin).c_str()); + VTR_LOG( + "\t\t\tNo possible routing path from %s to %s: needed for net '%s' " + "from net pin '%s'", + describe_lb_rr_node(lb_rr_graph, driver_rr_node).c_str(), + describe_lb_rr_node(lb_rr_graph, sink_rr_node).c_str(), + atom_nlist.net_name(net_id).c_str(), + atom_nlist.pin_name(driver_pin).c_str()); + VTR_LOGV(sink_pin, " to net pin '%s'", + atom_nlist.pin_name(sink_pin).c_str()); VTR_LOG("\n"); } } else { @@ -880,9 +946,9 @@ bool LbRouter::try_expand_nodes(const AtomNetlist& atom_nlist, LbRRNodeId exp_inode = exp_node.node_index; if (explored_node_tb_[exp_inode].explored_id != explore_id_index_) { - /* First time node is popped implies path to this node is the lowest cost. - * If the node is popped a second time, then the path to that node is higher - * than this path so ignore. + /* First time node is popped implies path to this node is the lowest + * cost. If the node is popped a second time, then the path to that node + * is higher than this path so ignore. */ explored_node_tb_[exp_inode].explored_id = explore_id_index_; explored_node_tb_[exp_inode].prev_index = exp_node.prev_index; @@ -890,12 +956,14 @@ bool LbRouter::try_expand_nodes(const AtomNetlist& atom_nlist, if (!try_other_modes) { expand_node(lb_rr_graph, exp_node, lb_net_sinks_[lb_net].size()); } else { - expand_node_all_modes(lb_rr_graph, exp_node, lb_net_sinks_[lb_net].size()); + expand_node_all_modes(lb_rr_graph, exp_node, + lb_net_sinks_[lb_net].size()); } } } } - } while (exp_node.node_index != lb_net_sinks_[lb_net][itarget] && !is_impossible); + } while (exp_node.node_index != lb_net_sinks_[lb_net][itarget] && + !is_impossible); return is_impossible; } @@ -904,12 +972,13 @@ bool LbRouter::try_expand_nodes(const AtomNetlist& atom_nlist, * Private validators *************************************************/ bool LbRouter::matched_lb_rr_graph(const LbRRGraph& lb_rr_graph) const { - return ( (routing_status_.size() == lb_rr_graph.nodes().size()) - && (explored_node_tb_.size() == lb_rr_graph.nodes().size()) ); + return ((routing_status_.size() == lb_rr_graph.nodes().size()) && + (explored_node_tb_.size() == lb_rr_graph.nodes().size())); } bool LbRouter::valid_net_id(const NetId& net_id) const { - return ( size_t(net_id) < lb_net_ids_.size() ) && ( net_id == lb_net_ids_[net_id] ); + return (size_t(net_id) < lb_net_ids_.size()) && + (net_id == lb_net_ids_[net_id]); } bool LbRouter::check_net(const LbRRGraph& lb_rr_graph, @@ -926,18 +995,16 @@ bool LbRouter::check_net(const LbRRGraph& lb_rr_graph, } /* We must have 1 source and >1 terminal */ if (1 > lb_net_sources_[net].size()) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Net '%lu' has only %lu sources.\n", + VTR_LOGF_ERROR(__FILE__, __LINE__, "Net '%lu' has only %lu sources.\n", size_t(net), lb_net_sources_[net].size()); return false; - } + } if (1 > lb_net_sinks_[net].size()) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Net '%lu' has only %lu sinks.\n", + VTR_LOGF_ERROR(__FILE__, __LINE__, "Net '%lu' has only %lu sinks.\n", size_t(net), lb_net_sinks_[net].size()); return false; - } + } /* Each node must be valid */ for (const LbRRNodeId& node : lb_net_sources_[net]) { if (false == lb_rr_graph.valid_node_id(node)) { @@ -960,21 +1027,18 @@ bool LbRouter::check_net(const LbRRGraph& lb_rr_graph, for (const AtomPinId& pin : lb_net_atom_source_pins_[net]) { if (false == atom_nlist.valid_pin_id(pin)) { VTR_LOGF_ERROR(__FILE__, __LINE__, - "Net '%lu' has invalid source atom pin.\n", - size_t(net)); + "Net '%lu' has invalid source atom pin.\n", size_t(net)); return false; } } for (const AtomPinId& pin : lb_net_atom_sink_pins_[net]) { if (false == atom_nlist.valid_pin_id(pin)) { VTR_LOGF_ERROR(__FILE__, __LINE__, - "Net '%lu' has invalid sink_ atom pin.\n", - size_t(net)); + "Net '%lu' has invalid sink_ atom pin.\n", size_t(net)); return false; } } - return true; } @@ -1039,9 +1103,6 @@ void LbRouter::free_lb_trace(t_trace* lb_trace) { } } -void LbRouter::reset_illegal_modes() { - illegal_modes_.clear(); -} - +void LbRouter::reset_illegal_modes() { illegal_modes_.clear(); } } /* end namespace openfpga */ diff --git a/openfpga/src/repack/lb_router.h b/openfpga/src/repack/lb_router.h index 71020d1b4..c563ba8c5 100644 --- a/openfpga/src/repack/lb_router.h +++ b/openfpga/src/repack/lb_router.h @@ -5,18 +5,16 @@ * Include header files that are required by function declaration *******************************************************************/ #include +#include #include #include -#include - -#include "vtr_vector.h" -#include "vtr_strong_id.h" +#include "lb_rr_graph.h" #include "physical_types.h" #include "vpr_context.h" - #include "vpr_device_annotation.h" -#include "lb_rr_graph.h" +#include "vtr_strong_id.h" +#include "vtr_vector.h" /******************************************************************** * Function declaration @@ -30,7 +28,7 @@ namespace openfpga { * The router supports routing multiple nets on a LbRRGraph object * which models the routing resources in a programmable logic block * - * Note: + * Note: * - This router will not build/allocate a LbRRGraph object * Users must do it OUTSIDE this object!!! * - This router supports multiple sources for single net @@ -38,375 +36,383 @@ namespace openfpga { * * How to use the router: * - * // Create your own routing resource graph + * // Create your own routing resource graph * LbRRGraph lb_rr_graph = (); * * // Create a router object * LbRouter lb_router(lb_rr_graph); * - * // Add nets to be routed - * std::vector source_nodes = (); - * std::vector sink_nodes = (); - * LbNetId net = lb_router.create_net_to_route(source_nodes, sink_nodes); + * // Add nets to be routed + * std::vector source_nodes = + *(); std::vector + *sink_nodes = (); LbNetId net = + *lb_router.create_net_to_route(source_nodes, sink_nodes); * // Add more nets * * // Initialize the modes to expand routing - * // This is a must-do before running the router in the purpose of repacking!!! - * lb_router.set_physical_pb_modes(lb_rr_graph, device_annotation); + * // This is a must-do before running the router in the purpose of + *repacking!!! lb_router.set_physical_pb_modes(lb_rr_graph, device_annotation); * - * // Run the router - * bool route_success = lb_router.try_route(lb_rr_graph, atom_ctx.nlist, verbose); + * // Run the router + * bool route_success = lb_router.try_route(lb_rr_graph, atom_ctx.nlist, + *verbose); * - * // Check routing status + * // Check routing status * if (true == route_success) { * // Succeed * } * * // Read out routing results - * // Here is an example to check which nodes are mapped to the 'net' created before - * std::vector routed_nodes = lb_router.net_routed_nodes(net); + * // Here is an example to check which nodes are mapped to the 'net' created + *before std::vector routed_nodes = lb_router.net_routed_nodes(net); * *******************************************************************/ - class LbRouter { - public: /* Strong ids */ - struct net_id_tag; - typedef vtr::StrongId NetId; - public: /* Types and ranges */ - typedef vtr::vector::const_iterator net_iterator; - typedef vtr::Range net_range; - public: /* Intra-Logic Block Routing Data Structures (by instance) */ - /************************************************************************** - * Describes the status of a logic cluster_ctx.blocks routing resource node - * for a given logic cluster_ctx.blocks instance - ***************************************************************************/ - struct t_routing_status { - int occ; /* Number of nets currently using this lb_rr_node */ - t_mode* mode; /* Mode that this rr_node is set to */ - - int historical_usage; /* Historical usage of using this node */ - - t_routing_status() { - occ = 0; - mode = nullptr; - historical_usage = 0; + public: /* Strong ids */ + struct net_id_tag; + typedef vtr::StrongId NetId; + + public: /* Types and ranges */ + typedef vtr::vector::const_iterator net_iterator; + typedef vtr::Range net_range; + + public: /* Intra-Logic Block Routing Data Structures (by instance) */ + /************************************************************************** + * Describes the status of a logic cluster_ctx.blocks routing resource node + * for a given logic cluster_ctx.blocks instance + ***************************************************************************/ + struct t_routing_status { + int occ; /* Number of nets currently using this lb_rr_node */ + t_mode* mode; /* Mode that this rr_node is set to */ + + int historical_usage; /* Historical usage of using this node */ + + t_routing_status() { + occ = 0; + mode = nullptr; + historical_usage = 0; + } + }; + + /************************************************************************** + * Data structure forming the route tree of a net within one logic + *cluster_ctx.blocks. A net is implemented using routing resource nodes. The + *t_lb_trace data structure records one of the nodes used by the net and the + *connections to other nodes + ***************************************************************************/ + struct t_trace { + LbRRNodeId current_node; /* current t_lb_type_rr_node used by net */ + std::vector + next_nodes; /* index of previous edge that drives current node */ + }; + + /************************************************************************** + * Stores tuning parameters used by intra-logic cluster_ctx.blocks router + ***************************************************************************/ + struct t_option { + int max_iterations; + float pres_fac; + float pres_fac_mult; + float hist_fac; + }; + + /************************************************************************** + * Node expanded by router + ***************************************************************************/ + struct t_expansion_node { + LbRRNodeId node_index; /* Index of logic cluster_ctx.blocks rr node this + expansion node represents */ + LbRRNodeId prev_index; /* Index of logic cluster_ctx.blocks rr node that + drives this expansion node */ + float cost; + + t_expansion_node() { + node_index = LbRRNodeId::INVALID(); + prev_index = LbRRNodeId::INVALID(); + cost = 0; + } + }; + + class compare_expansion_node { + public: + /* Returns true if t1 is earlier than t2 */ + bool operator()(t_expansion_node& e1, t_expansion_node& e2) { + if (e1.cost > e2.cost) { + return true; } - }; + return false; + } + }; - /************************************************************************** - * Data structure forming the route tree of a net within one logic cluster_ctx.blocks. - * A net is implemented using routing resource nodes. - * The t_lb_trace data structure records one of the nodes used by the net and the connections - * to other nodes - ***************************************************************************/ - struct t_trace { - LbRRNodeId current_node; /* current t_lb_type_rr_node used by net */ - std::vector next_nodes; /* index of previous edge that drives current node */ - }; + /************************************************************************** + * Stores explored nodes by router + ***************************************************************************/ + struct t_explored_node_stats { + LbRRNodeId prev_index; /* Prevous node that drives this one */ + int explored_id; /* ID used to determine if this node has been explored */ + NetId inet; /* net index of route tree */ + int enqueue_id; /* ID used ot determine if this node has been pushed on + exploration priority queue */ + float enqueue_cost; /* cost of node pused on exploration priority queue */ - /************************************************************************** - * Stores tuning parameters used by intra-logic cluster_ctx.blocks router - ***************************************************************************/ - struct t_option { - int max_iterations; - float pres_fac; - float pres_fac_mult; - float hist_fac; - }; + t_explored_node_stats() { + prev_index = LbRRNodeId::INVALID(); + explored_id = OPEN; + enqueue_id = OPEN; + inet = NetId::INVALID(); + enqueue_cost = 0; + } + }; - /************************************************************************** - * Node expanded by router - ***************************************************************************/ - struct t_expansion_node { - LbRRNodeId node_index; /* Index of logic cluster_ctx.blocks rr node this expansion node represents */ - LbRRNodeId prev_index; /* Index of logic cluster_ctx.blocks rr node that drives this expansion node */ - float cost; - - t_expansion_node() { - node_index = LbRRNodeId::INVALID(); - prev_index = LbRRNodeId::INVALID(); - cost = 0; - } - }; + /************************************************************************** + * Stores status of mode selection during clustering + ***************************************************************************/ + struct t_mode_selection_status { + bool is_mode_conflict = false; + bool try_expand_all_modes = false; + bool expand_all_modes = false; - class compare_expansion_node { - public: - /* Returns true if t1 is earlier than t2 */ - bool operator()(t_expansion_node& e1, t_expansion_node& e2) { - if (e1.cost > e2.cost) { - return true; - } - return false; - } - }; + bool is_mode_issue() { return is_mode_conflict || try_expand_all_modes; } + }; - /************************************************************************** - * Stores explored nodes by router - ***************************************************************************/ - struct t_explored_node_stats { - LbRRNodeId prev_index; /* Prevous node that drives this one */ - int explored_id; /* ID used to determine if this node has been explored */ - NetId inet; /* net index of route tree */ - int enqueue_id; /* ID used ot determine if this node has been pushed on exploration priority queue */ - float enqueue_cost; /* cost of node pused on exploration priority queue */ - - t_explored_node_stats() { - prev_index = LbRRNodeId::INVALID(); - explored_id = OPEN; - enqueue_id = OPEN; - inet = NetId::INVALID(); - enqueue_cost = 0; - } - }; + // TODO: check if this hacky class memory reserve thing is still necessary, if + // not, then delete + /* Packing uses a priority queue that requires a large number of elements. + * This backdoor + * allows me to use a priority queue where I can pre-allocate the # of + * elements in the underlying container for efficiency reasons. Note: Must + * use vector with this + */ + template + class reservable_pq : public std::priority_queue { + public: + typedef typename std::priority_queue::size_type size_type; + reservable_pq(size_type capacity = 0) { + reserve(capacity); + cur_cap = capacity; + } + void reserve(size_type capacity) { + this->c.reserve(capacity); + cur_cap = capacity; + } + void clear() { + this->c.clear(); + this->c.reserve(cur_cap); + } - /************************************************************************** - * Stores status of mode selection during clustering - ***************************************************************************/ - struct t_mode_selection_status { - bool is_mode_conflict = false; - bool try_expand_all_modes = false; - bool expand_all_modes = false; - - bool is_mode_issue() { - return is_mode_conflict || try_expand_all_modes; - } - }; + private: + size_type cur_cap; + }; - // TODO: check if this hacky class memory reserve thing is still necessary, if not, then delete - /* Packing uses a priority queue that requires a large number of elements. - * This backdoor - * allows me to use a priority queue where I can pre-allocate the # of elements - * in the underlying container - * for efficiency reasons. Note: Must use vector with this - */ - template - class reservable_pq : public std::priority_queue { - public: - typedef typename std::priority_queue::size_type size_type; - reservable_pq(size_type capacity = 0) { - reserve(capacity); - cur_cap = capacity; - } - void reserve(size_type capacity) { - this->c.reserve(capacity); - cur_cap = capacity; - } - void clear() { - this->c.clear(); - this->c.reserve(cur_cap); - } + enum e_commit_remove { RT_COMMIT, RT_REMOVE }; - private: - size_type cur_cap; - }; - - enum e_commit_remove { - RT_COMMIT, - RT_REMOVE - }; + public: /* Public constructors */ + LbRouter(const LbRRGraph& lb_rr_graph, t_logical_block_type_ptr lb_type); - public : /* Public constructors */ - LbRouter(const LbRRGraph& lb_rr_graph, t_logical_block_type_ptr lb_type); - - public : /* Public accessors */ - /* Return the ids for all the nets to be routed */ - net_range nets() const; + public: /* Public accessors */ + /* Return the ids for all the nets to be routed */ + net_range nets() const; - /* Return the atom net id for a net to be routed */ - AtomNetId net_atom_net_id(const NetId& net) const; + /* Return the atom net id for a net to be routed */ + AtomNetId net_atom_net_id(const NetId& net) const; - /** - * Find all the routing resource nodes that are over-used, which they are used more than their capacity - * This function is call to collect the nodes and router can reroute these net - */ - std::vector find_congested_rr_nodes(const LbRRGraph& lb_rr_graph) const; + /** + * Find all the routing resource nodes that are over-used, which they are used + * more than their capacity This function is call to collect the nodes and + * router can reroute these net + */ + std::vector find_congested_rr_nodes( + const LbRRGraph& lb_rr_graph) const; - /* Show if a valid routing solution has been founded or not */ - bool is_routed() const; + /* Show if a valid routing solution has been founded or not */ + bool is_routed() const; - /** - * Get the routing results for a Net - */ - std::vector net_routed_nodes(const NetId& net) const; + /** + * Get the routing results for a Net + */ + std::vector net_routed_nodes(const NetId& net) const; - public : /* Public mutators */ - /** - * Add net to be routed - */ - NetId create_net_to_route(const std::vector& sources, - const std::vector& terminals); - void add_net_atom_net_id(const NetId& net, const AtomNetId& atom_net); - void add_net_atom_pins(const NetId& net, const AtomPinId& src_pin, const std::vector& terminal_pins); + public: /* Public mutators */ + /** + * Add net to be routed + */ + NetId create_net_to_route(const std::vector& sources, + const std::vector& terminals); + void add_net_atom_net_id(const NetId& net, const AtomNetId& atom_net); + void add_net_atom_pins(const NetId& net, const AtomPinId& src_pin, + const std::vector& terminal_pins); - /* TODO: Initialize all the modes in routing status with the mode set in pb - * This is function used for general purpose packing - */ + /* TODO: Initialize all the modes in routing status with the mode set in pb + * This is function used for general purpose packing + */ - /* Set all the modes in routing status with the physical mode defined in device annotation - * This method is used only in repacking for physical logical blocks - * Do NOT use it during the general purpose packing - */ - void set_physical_pb_modes(const LbRRGraph& lb_rr_graph, - const VprDeviceAnnotation& device_annotation); + /* Set all the modes in routing status with the physical mode defined in + * device annotation This method is used only in repacking for physical + * logical blocks Do NOT use it during the general purpose packing + */ + void set_physical_pb_modes(const LbRRGraph& lb_rr_graph, + const VprDeviceAnnotation& device_annotation); - /** - * Perform routing algorithm on a given logical tile routing resource graph - * Note: the lb_rr_graph must be the same as you initilized the router!!! - */ - bool try_route(const LbRRGraph& lb_rr_graph, - const AtomNetlist& atom_nlist, - const bool& verbosity); + /** + * Perform routing algorithm on a given logical tile routing resource graph + * Note: the lb_rr_graph must be the same as you initilized the router!!! + */ + bool try_route(const LbRRGraph& lb_rr_graph, const AtomNetlist& atom_nlist, + const bool& verbosity); - private : /* Private accessors */ - /** - * Report if the routing is successfully done on a logical block routing resource graph - */ - bool is_route_success(const LbRRGraph& lb_rr_graph) const; + private: /* Private accessors */ + /** + * Report if the routing is successfully done on a logical block routing + * resource graph + */ + bool is_route_success(const LbRRGraph& lb_rr_graph) const; - /** - * Try to find a node in the routing traces recursively - * If not found, will return an empty pointer - */ - t_trace* find_node_in_rt(t_trace* rt, const LbRRNodeId& rt_index); + /** + * Try to find a node in the routing traces recursively + * If not found, will return an empty pointer + */ + t_trace* find_node_in_rt(t_trace* rt, const LbRRNodeId& rt_index); - bool route_has_conflict(const LbRRGraph& lb_rr_graph, t_trace* rt) const; + bool route_has_conflict(const LbRRGraph& lb_rr_graph, t_trace* rt) const; - /* Recursively find all the nodes in the trace */ - void rec_collect_trace_nodes(const t_trace* trace, std::vector& routed_nodes) const; + /* Recursively find all the nodes in the trace */ + void rec_collect_trace_nodes(const t_trace* trace, + std::vector& routed_nodes) const; - private : /* Private mutators */ - /*It is possible that a net may connect multiple times to a logically equivalent set of primitive pins. - *The cluster router will only route one connection for a particular net to the common sink of the - *equivalent pins. - * - *To work around this, we fix all but one of these duplicate connections to route to specific pins, - *(instead of the common sink). This ensures a legal routing is produced and that the duplicate pins - *are not 'missing' in the clustered netlist. - */ - void fix_duplicate_equivalent_pins(const AtomContext& atom_ctx, - const LbRRGraph& lb_rr_graph); - bool check_edge_for_route_conflicts(std::unordered_map& mode_map, - const t_pb_graph_pin* driver_pin, - const t_pb_graph_pin* pin); - void commit_remove_rt(const LbRRGraph& lb_rr_graph, - t_trace* rt, - const e_commit_remove& op, - std::unordered_map& mode_map); - bool is_skip_route_net(const LbRRGraph& lb_rr_graph, t_trace* rt); - bool add_to_rt(t_trace* rt, const LbRRNodeId& node_index, const NetId& irt_net); - void add_source_to_rt(const NetId& inet, const size_t& isrc); - void expand_rt_rec(t_trace* rt, - const LbRRNodeId& prev_index, - const NetId& irt_net, - const int& explore_id_index); - void expand_rt(const NetId& inet, - const NetId& irt_net, - const size_t& isrc); - void expand_edges(const LbRRGraph& lb_rr_graph, - t_mode* mode, - const LbRRNodeId& cur_inode, - float cur_cost, - int net_fanout); - void expand_node(const LbRRGraph& lb_rr_graph, - const t_expansion_node& exp_node, - const int& net_fanout); - void expand_node_all_modes(const LbRRGraph& lb_rr_graph, - const t_expansion_node& exp_node, - const int& net_fanout); - bool try_expand_nodes(const AtomNetlist& atom_nlist, - const LbRRGraph& lb_rr_graph, - const NetId& lb_net, - t_expansion_node& exp_node, - const int& isrc, - const int& itarget, - const bool& try_other_modes, - const bool& verbosity); + private: /* Private mutators */ + /*It is possible that a net may connect multiple times to a logically + *equivalent set of primitive pins. The cluster router will only route one + *connection for a particular net to the common sink of the equivalent pins. + * + *To work around this, we fix all but one of these duplicate connections to + *route to specific pins, (instead of the common sink). This ensures a legal + *routing is produced and that the duplicate pins are not 'missing' in the + *clustered netlist. + */ + void fix_duplicate_equivalent_pins(const AtomContext& atom_ctx, + const LbRRGraph& lb_rr_graph); + bool check_edge_for_route_conflicts( + std::unordered_map& mode_map, + const t_pb_graph_pin* driver_pin, const t_pb_graph_pin* pin); + void commit_remove_rt( + const LbRRGraph& lb_rr_graph, t_trace* rt, const e_commit_remove& op, + std::unordered_map& mode_map); + bool is_skip_route_net(const LbRRGraph& lb_rr_graph, t_trace* rt); + bool add_to_rt(t_trace* rt, const LbRRNodeId& node_index, + const NetId& irt_net); + void add_source_to_rt(const NetId& inet, const size_t& isrc); + void expand_rt_rec(t_trace* rt, const LbRRNodeId& prev_index, + const NetId& irt_net, const int& explore_id_index); + void expand_rt(const NetId& inet, const NetId& irt_net, const size_t& isrc); + void expand_edges(const LbRRGraph& lb_rr_graph, t_mode* mode, + const LbRRNodeId& cur_inode, float cur_cost, + int net_fanout); + void expand_node(const LbRRGraph& lb_rr_graph, + const t_expansion_node& exp_node, const int& net_fanout); + void expand_node_all_modes(const LbRRGraph& lb_rr_graph, + const t_expansion_node& exp_node, + const int& net_fanout); + bool try_expand_nodes(const AtomNetlist& atom_nlist, + const LbRRGraph& lb_rr_graph, const NetId& lb_net, + t_expansion_node& exp_node, const int& isrc, + const int& itarget, const bool& try_other_modes, + const bool& verbosity); - bool try_route_net(const LbRRGraph& lb_rr_graph, - const AtomNetlist& atom_nlist, - const NetId& net_idx, - t_expansion_node& exp_node, - std::unordered_map& mode_map, - const bool& verbosity); + bool try_route_net( + const LbRRGraph& lb_rr_graph, const AtomNetlist& atom_nlist, + const NetId& net_idx, t_expansion_node& exp_node, + std::unordered_map& mode_map, + const bool& verbosity); - private : /* Private validators */ - /** - * Validate if the rr_graph is the one we used to initialize the router - */ - bool matched_lb_rr_graph(const LbRRGraph& lb_rr_graph) const; + private: /* Private validators */ + /** + * Validate if the rr_graph is the one we used to initialize the router + */ + bool matched_lb_rr_graph(const LbRRGraph& lb_rr_graph) const; - bool valid_net_id(const NetId& net_id) const; + bool valid_net_id(const NetId& net_id) const; - /* Validate that all the nets have - * - valid source, terminal nodes in lb routing resource graph - * - valid atom net and pin ids in atom netlist - */ - bool check_net(const LbRRGraph& lb_rr_graph, - const AtomNetlist& atom_nlist, - const NetId& net) const; + /* Validate that all the nets have + * - valid source, terminal nodes in lb routing resource graph + * - valid atom net and pin ids in atom netlist + */ + bool check_net(const LbRRGraph& lb_rr_graph, const AtomNetlist& atom_nlist, + const NetId& net) const; - private : /* Private initializer and cleaner */ - void reset_explored_node_tb(); - void reset_net_rt(); - void reset_routing_status(); - void reset_illegal_modes(); + private: /* Private initializer and cleaner */ + void reset_explored_node_tb(); + void reset_net_rt(); + void reset_routing_status(); + void reset_illegal_modes(); - void clear_nets(); - void free_net_rt(t_trace* lb_trace); - void free_lb_trace(t_trace* lb_trace); + void clear_nets(); + void free_net_rt(t_trace* lb_trace); + void free_lb_trace(t_trace* lb_trace); - private : /* Stores all data needed by intra-logic cluster_ctx.blocks router */ - /* Logical Netlist Info */ - /* Pointer to vector of intra logic cluster_ctx.blocks nets and their connections */ - vtr::vector lb_net_ids_; + private: /* Stores all data needed by intra-logic cluster_ctx.blocks router */ + /* Logical Netlist Info */ + /* Pointer to vector of intra logic cluster_ctx.blocks nets and their + * connections */ + vtr::vector lb_net_ids_; - /* index of atom net this intra_lb_net represents */ - vtr::vector lb_net_atom_net_ids_; + /* index of atom net this intra_lb_net represents */ + vtr::vector lb_net_atom_net_ids_; - /* AtomPin's associated with each source nodes */ - vtr::vector> lb_net_atom_source_pins_; + /* AtomPin's associated with each source nodes */ + vtr::vector> lb_net_atom_source_pins_; - /* AtomPin's associated with each sink nodes */ - vtr::vector> lb_net_atom_sink_pins_; + /* AtomPin's associated with each sink nodes */ + vtr::vector> lb_net_atom_sink_pins_; - /* starting points of the intra_lb_net */ - vtr::vector> lb_net_sources_; + /* starting points of the intra_lb_net */ + vtr::vector> lb_net_sources_; - /* end points of the intra_lb_net */ - vtr::vector> lb_net_sinks_; + /* end points of the intra_lb_net */ + vtr::vector> lb_net_sinks_; - /* Route tree head for each source of each net */ - vtr::vector> lb_net_rt_trees_; + /* Route tree head for each source of each net */ + vtr::vector> lb_net_rt_trees_; - /* Logical-to-physical mapping info */ - vtr::vector routing_status_; /* [0..lb_type_graph->size()-1] Stats for each logic cluster_ctx.blocks rr node instance */ + /* Logical-to-physical mapping info */ + vtr::vector + routing_status_; /* [0..lb_type_graph->size()-1] Stats for each logic + cluster_ctx.blocks rr node instance */ - /* Stores state info during Pathfinder iterative routing */ - vtr::vector explored_node_tb_; /* [0..lb_type_graph->size()-1] Stores mode exploration and traceback info for nodes */ + /* Stores state info during Pathfinder iterative routing */ + vtr::vector + explored_node_tb_; /* [0..lb_type_graph->size()-1] Stores mode exploration + and traceback info for nodes */ - int explore_id_index_; /* used in conjunction with node_traceback to determine whether or not a location has been explored. By using a unique identifier every route, I don't have to clear the previous route exploration */ + int explore_id_index_; /* used in conjunction with node_traceback to determine + whether or not a location has been explored. By + using a unique identifier every route, I don't have + to clear the previous route exploration */ - /* Current type */ - t_logical_block_type_ptr lb_type_; + /* Current type */ + t_logical_block_type_ptr lb_type_; - /* Parameters used by router */ - t_option params_; + /* Parameters used by router */ + t_option params_; - /* Stores whether or not the current logical-to-physical mapping has a routed solution */ - bool is_routed_; + /* Stores whether or not the current logical-to-physical mapping has a routed + * solution */ + bool is_routed_; - /* Stores the mode selection status when expanding the edges */ - t_mode_selection_status mode_status_; + /* Stores the mode selection status when expanding the edges */ + t_mode_selection_status mode_status_; - /* Stores state info of the priority queue in expanding edges during route */ - reservable_pq, compare_expansion_node> pq_; + /* Stores state info of the priority queue in expanding edges during route */ + reservable_pq, + compare_expansion_node> + pq_; - /* Store the illegal modes for each pb_graph_node that is involved in the routing resource graph */ - std::map> illegal_modes_; + /* Store the illegal modes for each pb_graph_node that is involved in the + * routing resource graph */ + std::map> illegal_modes_; - /* current congestion factor */ - float pres_con_fac_; + /* current congestion factor */ + float pres_con_fac_; }; } /* end namespace openfpga */ diff --git a/openfpga/src/repack/lb_router_utils.cpp b/openfpga/src/repack/lb_router_utils.cpp index 787507a77..45b1fce24 100644 --- a/openfpga/src/repack/lb_router_utils.cpp +++ b/openfpga/src/repack/lb_router_utils.cpp @@ -3,10 +3,10 @@ ***************************************************************************************/ /* Headers from vtrutil library */ -#include "vtr_assert.h" - #include "lb_router_utils.h" +#include "vtr_assert.h" + /* begin namespace openfpga */ namespace openfpga { @@ -15,15 +15,15 @@ namespace openfpga { * This function will automatically find the source and sink atom pins * based on the given atom net ***************************************************************************************/ -LbRouter::NetId add_lb_router_net_to_route(LbRouter& lb_router, - const LbRRGraph& lb_rr_graph, - const std::vector& source_nodes, - const std::vector& sink_nodes, - const AtomContext& atom_ctx, - const AtomNetId& atom_net_id) { +LbRouter::NetId add_lb_router_net_to_route( + LbRouter& lb_router, const LbRRGraph& lb_rr_graph, + const std::vector& source_nodes, + const std::vector& sink_nodes, const AtomContext& atom_ctx, + const AtomNetId& atom_net_id) { VTR_ASSERT(0 < sink_nodes.size()); - LbRouter::NetId lb_net = lb_router.create_net_to_route(source_nodes, sink_nodes); + LbRouter::NetId lb_net = + lb_router.create_net_to_route(source_nodes, sink_nodes); VTR_ASSERT(AtomNetId::INVALID() != atom_net_id); lb_router.add_net_atom_net_id(lb_net, atom_net_id); @@ -32,11 +32,12 @@ LbRouter::NetId add_lb_router_net_to_route(LbRouter& lb_router, AtomPinId atom_pin_outside_pb = AtomPinId::INVALID(); for (const LbRRNodeId& sink_node : sink_nodes) { - t_pb_graph_pin* sink_pb_pin = lb_rr_graph.node_pb_graph_pin(sink_node); + t_pb_graph_pin* sink_pb_pin = lb_rr_graph.node_pb_graph_pin(sink_node); bool atom_pin_inside_pb = false; for (const AtomPinId& atom_pin : atom_ctx.nlist.net_sinks(atom_net_id)) { VTR_ASSERT(AtomPinId::INVALID() != atom_pin); - if (sink_pb_pin == find_pb_graph_pin(atom_ctx.nlist, atom_ctx.lookup, atom_pin)) { + if (sink_pb_pin == + find_pb_graph_pin(atom_ctx.nlist, atom_ctx.lookup, atom_pin)) { terminal_pins.push_back(atom_pin); atom_pin_inside_pb = true; break; @@ -53,21 +54,22 @@ LbRouter::NetId add_lb_router_net_to_route(LbRouter& lb_router, } VTR_ASSERT(AtomPinId::INVALID() != atom_ctx.nlist.net_driver(atom_net_id)); if (sink_nodes.size() != terminal_pins.size()) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Net '%s' has %lu sink nodes while has %lu associated atom pins!\n", - atom_ctx.nlist.net_name(atom_net_id).c_str(), - sink_nodes.size(), - terminal_pins.size()); + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Net '%s' has %lu sink nodes while has %lu associated atom pins!\n", + atom_ctx.nlist.net_name(atom_net_id).c_str(), sink_nodes.size(), + terminal_pins.size()); } VTR_ASSERT(sink_nodes.size() == terminal_pins.size()); - lb_router.add_net_atom_pins(lb_net, atom_ctx.nlist.net_driver(atom_net_id), terminal_pins); + lb_router.add_net_atom_pins(lb_net, atom_ctx.nlist.net_driver(atom_net_id), + terminal_pins); return lb_net; } /*************************************************************************************** - * Load the routing results (routing tree) from lb router to + * Load the routing results (routing tree) from lb router to * a physical pb data structure ***************************************************************************************/ void save_lb_router_results_to_physical_pb(PhysicalPb& phy_pb, @@ -90,17 +92,17 @@ void save_lb_router_results_to_physical_pb(PhysicalPb& phy_pb, const AtomNetId& atom_net = lb_router.net_atom_net_id(net); /* Print info to help debug */ - VTR_LOGV(verbose, - "Save net '%s' to physical pb_graph_pin '%s.%s[%d]'\n", + VTR_LOGV(verbose, "Save net '%s' to physical pb_graph_pin '%s.%s[%d]'\n", atom_netlist.net_name(atom_net).c_str(), pb_graph_pin->parent_node->pb_type->name, - pb_graph_pin->port->name, - pb_graph_pin->pin_number); - - if (AtomNetId::INVALID() == phy_pb.pb_graph_pin_atom_net(pb_id, pb_graph_pin)) { + pb_graph_pin->port->name, pb_graph_pin->pin_number); + + if (AtomNetId::INVALID() == + phy_pb.pb_graph_pin_atom_net(pb_id, pb_graph_pin)) { phy_pb.set_pb_graph_pin_atom_net(pb_id, pb_graph_pin, atom_net); } else { - VTR_ASSERT(atom_net == phy_pb.pb_graph_pin_atom_net(pb_id, pb_graph_pin)); + VTR_ASSERT(atom_net == + phy_pb.pb_graph_pin_atom_net(pb_id, pb_graph_pin)); } } } diff --git a/openfpga/src/repack/lb_router_utils.h b/openfpga/src/repack/lb_router_utils.h index 4dbc2c695..979a01fd5 100644 --- a/openfpga/src/repack/lb_router_utils.h +++ b/openfpga/src/repack/lb_router_utils.h @@ -5,8 +5,8 @@ * Include header files that are required by function declaration *******************************************************************/ #include "atom_netlist.h" -#include "lb_rr_graph.h" #include "lb_router.h" +#include "lb_rr_graph.h" #include "physical_pb.h" /******************************************************************** @@ -16,12 +16,11 @@ /* begin namespace openfpga */ namespace openfpga { -LbRouter::NetId add_lb_router_net_to_route(LbRouter& lb_router, - const LbRRGraph& lb_rr_graph, - const std::vector& source_node, - const std::vector& sink_nodes, - const AtomContext& atom_ctx, - const AtomNetId& atom_net_id); +LbRouter::NetId add_lb_router_net_to_route( + LbRouter& lb_router, const LbRRGraph& lb_rr_graph, + const std::vector& source_node, + const std::vector& sink_nodes, const AtomContext& atom_ctx, + const AtomNetId& atom_net_id); void save_lb_router_results_to_physical_pb(PhysicalPb& phy_pb, const LbRouter& lb_router, diff --git a/openfpga/src/repack/lb_rr_graph.cpp b/openfpga/src/repack/lb_rr_graph.cpp index 137b4a105..d7746d9dd 100644 --- a/openfpga/src/repack/lb_rr_graph.cpp +++ b/openfpga/src/repack/lb_rr_graph.cpp @@ -1,10 +1,11 @@ /************************************************************************ * Member Functions of LbRRGraph - * include mutators, accessors and utility functions + * include mutators, accessors and utility functions ***********************************************************************/ +#include "lb_rr_graph.h" + #include "vtr_assert.h" #include "vtr_log.h" -#include "lb_rr_graph.h" /* begin namespace openfpga */ namespace openfpga { @@ -18,7 +19,7 @@ LbRRGraph::LbRRGraph() { } /************************************************** - * Public Accessors: Aggregates + * Public Accessors: Aggregates *************************************************/ LbRRGraph::node_range LbRRGraph::nodes() const { return vtr::make_range(node_ids_.begin(), node_ids_.end()); @@ -29,7 +30,7 @@ LbRRGraph::edge_range LbRRGraph::edges() const { } /************************************************** - * Public Accessors node-level attributes + * Public Accessors node-level attributes *************************************************/ e_lb_rr_type LbRRGraph::node_type(const LbRRNodeId& node) const { VTR_ASSERT(true == valid_node_id(node)); @@ -56,7 +57,8 @@ std::vector LbRRGraph::node_in_edges(const LbRRNodeId& node) const { return node_in_edges_[node]; } -std::vector LbRRGraph::node_in_edges(const LbRRNodeId& node, t_mode* mode) const { +std::vector LbRRGraph::node_in_edges(const LbRRNodeId& node, + t_mode* mode) const { std::vector in_edges; VTR_ASSERT(true == valid_node_id(node)); @@ -69,12 +71,14 @@ std::vector LbRRGraph::node_in_edges(const LbRRNodeId& node, t_mode* return in_edges; } -std::vector LbRRGraph::node_out_edges(const LbRRNodeId& node) const { +std::vector LbRRGraph::node_out_edges( + const LbRRNodeId& node) const { VTR_ASSERT(true == valid_node_id(node)); return node_out_edges_[node]; } -std::vector LbRRGraph::node_out_edges(const LbRRNodeId& node, t_mode* mode) const { +std::vector LbRRGraph::node_out_edges(const LbRRNodeId& node, + t_mode* mode) const { std::vector out_edges; VTR_ASSERT(true == valid_node_id(node)); @@ -87,7 +91,8 @@ std::vector LbRRGraph::node_out_edges(const LbRRNodeId& node, t_mode return out_edges; } -LbRRNodeId LbRRGraph::find_node(const e_lb_rr_type& type, const t_pb_graph_pin* pb_graph_pin) const { +LbRRNodeId LbRRGraph::find_node(const e_lb_rr_type& type, + const t_pb_graph_pin* pb_graph_pin) const { if (size_t(type) >= node_lookup_.size()) { return LbRRNodeId::INVALID(); } @@ -95,19 +100,16 @@ LbRRNodeId LbRRGraph::find_node(const e_lb_rr_type& type, const t_pb_graph_pin* if (0 == node_lookup_[size_t(type)].count(pb_graph_pin)) { return LbRRNodeId::INVALID(); } - + return node_lookup_[size_t(type)].at(pb_graph_pin); } -LbRRNodeId LbRRGraph::ext_source_node() const { - return ext_source_node_; -} +LbRRNodeId LbRRGraph::ext_source_node() const { return ext_source_node_; } -LbRRNodeId LbRRGraph::ext_sink_node() const { - return ext_sink_node_; -} +LbRRNodeId LbRRGraph::ext_sink_node() const { return ext_sink_node_; } -std::vector LbRRGraph::find_edge(const LbRRNodeId& src_node, const LbRRNodeId& sink_node) const { +std::vector LbRRGraph::find_edge( + const LbRRNodeId& src_node, const LbRRNodeId& sink_node) const { std::vector edges; for (const LbRREdgeId& edge : node_out_edges_[src_node]) { if (sink_node == edge_sink_node(edge)) { @@ -178,30 +180,33 @@ LbRRNodeId LbRRGraph::create_node(const e_lb_rr_type& type) { } LbRRNodeId LbRRGraph::create_ext_source_node(const e_lb_rr_type& type) { - LbRRNodeId ext_source_node = create_node(type); + LbRRNodeId ext_source_node = create_node(type); ext_source_node_ = ext_source_node; return ext_source_node; } LbRRNodeId LbRRGraph::create_ext_sink_node(const e_lb_rr_type& type) { - LbRRNodeId ext_sink_node = create_node(type); + LbRRNodeId ext_sink_node = create_node(type); ext_sink_node_ = ext_sink_node; return ext_sink_node; } -void LbRRGraph::set_node_type(const LbRRNodeId& node, const e_lb_rr_type& type) { +void LbRRGraph::set_node_type(const LbRRNodeId& node, + const e_lb_rr_type& type) { VTR_ASSERT(true == valid_node_id(node)); node_types_[node] = type; } -void LbRRGraph::set_node_capacity(const LbRRNodeId& node, const short& capacity) { +void LbRRGraph::set_node_capacity(const LbRRNodeId& node, + const short& capacity) { VTR_ASSERT(true == valid_node_id(node)); node_capacities_[node] = capacity; } -void LbRRGraph::set_node_pb_graph_pin(const LbRRNodeId& node, t_pb_graph_pin* pb_graph_pin) { +void LbRRGraph::set_node_pb_graph_pin(const LbRRNodeId& node, + t_pb_graph_pin* pb_graph_pin) { VTR_ASSERT(true == valid_node_id(node)); node_pb_graph_pins_[node] = pb_graph_pin; @@ -211,22 +216,23 @@ void LbRRGraph::set_node_pb_graph_pin(const LbRRNodeId& node, t_pb_graph_pin* pb } if (0 < node_lookup_[node_type(node)].count(pb_graph_pin)) { - VTR_LOG_WARN("Detect pb_graph_pin '%s[%lu]' is mapped to LbRRGraph nodes (exist: %lu) and (to be mapped: %lu). Overwrite is done\n", - pb_graph_pin->port->name, pb_graph_pin->pin_number, - size_t(node_lookup_[node_type(node)].at(pb_graph_pin)), - size_t(node)); + VTR_LOG_WARN( + "Detect pb_graph_pin '%s[%lu]' is mapped to LbRRGraph nodes (exist: %lu) " + "and (to be mapped: %lu). Overwrite is done\n", + pb_graph_pin->port->name, pb_graph_pin->pin_number, + size_t(node_lookup_[node_type(node)].at(pb_graph_pin)), size_t(node)); } node_lookup_[node_type(node)][pb_graph_pin] = node; } -void LbRRGraph::set_node_intrinsic_cost(const LbRRNodeId& node, const float& cost) { +void LbRRGraph::set_node_intrinsic_cost(const LbRRNodeId& node, + const float& cost) { VTR_ASSERT(true == valid_node_id(node)); node_intrinsic_costs_[node] = cost; } LbRREdgeId LbRRGraph::create_edge(const LbRRNodeId& source, - const LbRRNodeId& sink, - t_mode* mode) { + const LbRRNodeId& sink, t_mode* mode) { VTR_ASSERT(true == valid_node_id(source)); VTR_ASSERT(true == valid_node_id(sink)); @@ -246,7 +252,8 @@ LbRREdgeId LbRRGraph::create_edge(const LbRRNodeId& source, return edge; } -void LbRRGraph::set_edge_intrinsic_cost(const LbRREdgeId& edge, const float& cost) { +void LbRRGraph::set_edge_intrinsic_cost(const LbRREdgeId& edge, + const float& cost) { VTR_ASSERT(true == valid_edge_id(edge)); edge_intrinsic_costs_[edge] = cost; } @@ -255,21 +262,23 @@ void LbRRGraph::set_edge_intrinsic_cost(const LbRREdgeId& edge, const float& cos * Public validators/invalidators ******************************************************************************/ bool LbRRGraph::valid_node_id(const LbRRNodeId& node_id) const { - return ( size_t(node_id) < node_ids_.size() ) && ( node_id == node_ids_[node_id] ); + return (size_t(node_id) < node_ids_.size()) && + (node_id == node_ids_[node_id]); } bool LbRRGraph::valid_edge_id(const LbRREdgeId& edge_id) const { - return ( size_t(edge_id) < edge_ids_.size() ) && ( edge_id == edge_ids_[edge_id] ); + return (size_t(edge_id) < edge_ids_.size()) && + (edge_id == edge_ids_[edge_id]); } -/* This function run fundamental checks on internal data +/* This function run fundamental checks on internal data * Errors are thrown if fundamental checking fails */ bool LbRRGraph::validate() const { size_t num_err = 0; - /* Validate the sizes of nodes and node-related vectors - * Validate the sizes of edges and edge-related vectors + /* Validate the sizes of nodes and node-related vectors + * Validate the sizes of edges and edge-related vectors */ if (false == validate_sizes()) { VTR_LOG_WARN("Fail in validating node and edges sizes!\n"); @@ -284,8 +293,10 @@ bool LbRRGraph::validate() const { /* Error out if there is any fatal errors found */ if (0 < num_err) { - VTR_LOG_ERROR("Logical tile Routing Resource graph is not valid due to %d fatal errors !\n", - num_err); + VTR_LOG_ERROR( + "Logical tile Routing Resource graph is not valid due to %d fatal errors " + "!\n", + num_err); } return (0 == num_err); @@ -300,29 +311,29 @@ bool LbRRGraph::empty() const { ******************************************************************************/ bool LbRRGraph::validate_node_sizes() const { size_t num_nodes = node_ids_.size(); - return node_ids_.size() == num_nodes - && node_types_.size() == num_nodes - && node_capacities_.size() == num_nodes - && node_pb_graph_pins_.size() == num_nodes - && node_intrinsic_costs_.size() == num_nodes - && node_in_edges_.size() == num_nodes - && node_out_edges_.size() == num_nodes; + return node_ids_.size() == num_nodes && node_types_.size() == num_nodes && + node_capacities_.size() == num_nodes && + node_pb_graph_pins_.size() == num_nodes && + node_intrinsic_costs_.size() == num_nodes && + node_in_edges_.size() == num_nodes && + node_out_edges_.size() == num_nodes; } bool LbRRGraph::validate_edge_sizes() const { size_t num_edges = edge_ids_.size(); - return edge_src_nodes_.size() == num_edges - && edge_sink_nodes_.size() == num_edges - && edge_intrinsic_costs_.size() == num_edges - && edge_modes_.size() == num_edges; + return edge_src_nodes_.size() == num_edges && + edge_sink_nodes_.size() == num_edges && + edge_intrinsic_costs_.size() == num_edges && + edge_modes_.size() == num_edges; } bool LbRRGraph::validate_sizes() const { - return validate_node_sizes() && validate_edge_sizes(); + return validate_node_sizes() && validate_edge_sizes(); } /* Check if a node is in the list of source_nodes of a edge */ -bool LbRRGraph::validate_node_is_edge_src(const LbRRNodeId& node, const LbRREdgeId& edge) const { +bool LbRRGraph::validate_node_is_edge_src(const LbRRNodeId& node, + const LbRREdgeId& edge) const { /* Assure a valid node id */ VTR_ASSERT_SAFE(valid_node_id(node)); /* assure a valid edge id */ @@ -336,7 +347,8 @@ bool LbRRGraph::validate_node_is_edge_src(const LbRRNodeId& node, const LbRREdge } /* Check if a node is in the list of sink_nodes of a edge */ -bool LbRRGraph::validate_node_is_edge_sink(const LbRRNodeId& node, const LbRREdgeId& edge) const { +bool LbRRGraph::validate_node_is_edge_sink(const LbRRNodeId& node, + const LbRREdgeId& edge) const { /* Assure a valid node id */ VTR_ASSERT_SAFE(valid_node_id(node)); /* assure a valid edge id */ @@ -358,17 +370,19 @@ bool LbRRGraph::validate_node_in_edges(const LbRRNodeId& node) const { VTR_ASSERT_SAFE(valid_node_id(node)); /* Check each edge */ for (auto edge : node_in_edges(node)) { - /* assure a valid edge id */ - VTR_ASSERT_SAFE(valid_edge_id(edge)); - /* check the node is in the list of edge_sink_node */ - if (true == validate_node_is_edge_sink(node, edge)) { - continue; + /* assure a valid edge id */ + VTR_ASSERT_SAFE(valid_edge_id(edge)); + /* check the node is in the list of edge_sink_node */ + if (true == validate_node_is_edge_sink(node, edge)) { + continue; } - /* Reach here, it means there is something wrong! - * Print a warning + /* Reach here, it means there is something wrong! + * Print a warning */ - VTR_LOG_WARN("Edge %d is in the input edge list of node %d while the node is not in edge's sink node list!\n", - size_t(edge), size_t(node)); + VTR_LOG_WARN( + "Edge %d is in the input edge list of node %d while the node is not in " + "edge's sink node list!\n", + size_t(edge), size_t(node)); all_valid = false; } @@ -391,18 +405,19 @@ bool LbRRGraph::validate_node_out_edges(const LbRRNodeId& node) const { if (true == validate_node_is_edge_src(node, edge)) { continue; } - /* Reach here, it means there is something wrong! - * Print a warning + /* Reach here, it means there is something wrong! + * Print a warning */ - VTR_LOG_WARN("Edge %d is in the output edge list of node %d while the node is not in edge's source node list!\n", - size_t(edge), size_t(node)); + VTR_LOG_WARN( + "Edge %d is in the output edge list of node %d while the node is not in " + "edge's source node list!\n", + size_t(edge), size_t(node)); all_valid = false; } return all_valid; } - /* check if all the nodes' input edges are valid */ bool LbRRGraph::validate_nodes_in_edges() const { bool all_valid = true; @@ -415,8 +430,8 @@ bool LbRRGraph::validate_nodes_in_edges() const { if (true == validate_node_in_edges(id)) { continue; } - /* Reach here, it means there is something wrong! - * Print a warning + /* Reach here, it means there is something wrong! + * Print a warning */ all_valid = false; } @@ -435,8 +450,8 @@ bool LbRRGraph::validate_nodes_out_edges() const { if (true == validate_node_out_edges(id)) { continue; } - /* Reach here, it means there is something wrong! - * Print a warning + /* Reach here, it means there is something wrong! + * Print a warning */ all_valid = false; } diff --git a/openfpga/src/repack/lb_rr_graph.h b/openfpga/src/repack/lb_rr_graph.h index 6edc0fbce..a71495379 100644 --- a/openfpga/src/repack/lb_rr_graph.h +++ b/openfpga/src/repack/lb_rr_graph.h @@ -1,44 +1,48 @@ /************************************************************************ - * This file introduces a class to model a Routing Resource Graph (RRGraph or RRG) - * which is used by packer. + * This file introduces a class to model a Routing Resource Graph (RRGraph or + *RRG) which is used by packer. * * Overview * ======== * RRGraph aims to describe in a general way how routing resources are connected - * inside a pb_graph - * - * A Routing Resource Graph (RRGraph or RRG) is a directed graph (has many cycles), - * which consists of a number of nodes and edges. + * inside a pb_graph + * + * A Routing Resource Graph (RRGraph or RRG) is a directed graph (has many + *cycles), which consists of a number of nodes and edges. * * Node * ---- - * Each node represents a routing resource, which could be - * 1. an intermediate node(INTERMEDIATE_NODE), which are input/output pins of non-primitive and non-root pb_graph_nodes. It represents a pb_graph_pin that exists in a pb_graph - * 2. a virtual source (SOURCE), which are inputs of root pb_graph_nodes or outputs of primitive pb_graph_node - * 3. a sink node (SINK), which are outputs of root pb_graph_nodes or inputs or primitive pb_graph_node + * Each node represents a routing resource, which could be + * 1. an intermediate node(INTERMEDIATE_NODE), which are input/output pins of + *non-primitive and non-root pb_graph_nodes. It represents a pb_graph_pin that + *exists in a pb_graph + * 2. a virtual source (SOURCE), which are inputs of root pb_graph_nodes or + *outputs of primitive pb_graph_node + * 3. a sink node (SINK), which are outputs of root pb_graph_nodes or inputs or + *primitive pb_graph_node * * Edge * ---- - * Each edge represents a connection between two pb_graph_pins - * It represents a pb_graph_edge in a pb_graph + * Each edge represents a connection between two pb_graph_pins + * It represents a pb_graph_edge in a pb_graph * - * Guidlines on using the LbRRGraph data structure + * Guidlines on using the LbRRGraph data structure * ============================================= * * For those want to access data from RRGraph * ------------------------------------------ * Some examples for most frequent data query: - * + * * // Strongly suggest to use a read-only lb_rr_graph object * const LbRRGraph& lb_rr_graph; * * // Access type of a node with a given node id - * // Get the unique node id that you may get - * // from other data structures or functions - * LbRRNodeId node_id; + * // Get the unique node id that you may get + * // from other data structures or functions + * LbRRNodeId node_id; * e_lb_rr_type node_type = lb_rr_graph.node_type(node_id); * - * // Access all the fan-out edges from a given node + * // Access all the fan-out edges from a given node * for (const RREdgeId& out_edge_id : rr_graph.node_out_edges(node_id)) { * // Do something with out_edge * } @@ -54,57 +58,61 @@ * We suggest developers to create builders in separated C/C++ source files * outside the rr_graph header and source files * - * After build/modify a RRGraph, please do run a fundamental check, a public accessor. - * to ensure that your RRGraph does not include invalid nodes/edges/switches/segements - * as well as connections. - * The validate() function gurantees the consistency between internal data structures, - * such as the id cross-reference between nodes and edges etc., - * so failing it indicates a fatal bug! - * This is a must-do check! + * After build/modify a RRGraph, please do run a fundamental check, a public + *accessor. to ensure that your RRGraph does not include invalid + *nodes/edges/switches/segements as well as connections. The validate() function + *gurantees the consistency between internal data structures, such as the id + *cross-reference between nodes and edges etc., so failing it indicates a fatal + *bug! This is a must-do check! * - * Example: + * Example: * RRGraph lb_rr_graph; * ... // Building RRGraph - * lb_rr_graph.validate(); + * lb_rr_graph.validate(); * - * Optionally, we strongly recommend developers to run an advance check in check_rr_graph() - * This guarantees legal and routable RRGraph for VPR routers. + * Optionally, we strongly recommend developers to run an advance check in + *check_rr_graph() This guarantees legal and routable RRGraph for VPR routers. * - * This checks for connectivity or other information in the RRGraph that is unexpected - * or unusual in an FPGA, and likely indicates a problem in your graph generation. - * However, if you are intentionally creating an RRGraph with this unusual, - * buts still technically legal, behaviour, you can write your own check_rr_graph() with weaker assumptions. + * This checks for connectivity or other information in the RRGraph that is + *unexpected or unusual in an FPGA, and likely indicates a problem in your graph + *generation. However, if you are intentionally creating an RRGraph with this + *unusual, buts still technically legal, behaviour, you can write your own + *check_rr_graph() with weaker assumptions. * - * Note: Do NOT modify the coordinate system for nodes, they are designed for downstream drawers and routers + * Note: Do NOT modify the coordinate system for nodes, they are designed for + *downstream drawers and routers * * For those want to extend RRGraph data structure * -------------------------------------------------------------------------- * Please avoid modifying any existing public/private accessors/mutators * in order to keep a stable RRGraph object in the framework - * Developers may add more internal data to RRGraph as well as associate accessors/mutators - * Please update and comment on the added features properly to keep this data structure friendly to be extended. + * Developers may add more internal data to RRGraph as well as associate + *accessors/mutators Please update and comment on the added features properly to + *keep this data structure friendly to be extended. + * + * Try to keep your extension within only graph-related internal data to + *RRGraph. In other words, extension is necessary when the new node/edge + *attributes are needed. RRGraph should NOT include other data which are shared + *by other data structures outside. The rr-graph is the single largest data + *structure in VPR, so avoid adding unnecessary information per node or per edge + *to it, as it will impact memory footprint. Instead, using indices to point to + *the outside data source instead of embedding to RRGraph For example: For any + *placement/routing cost related information, try to extend t_rr_indexed_data, + *but not RRGraph For any placement/routing results, try to extend PlaceContext + *and RoutingContext, but not RRGraph * - * Try to keep your extension within only graph-related internal data to RRGraph. - * In other words, extension is necessary when the new node/edge attributes are needed. - * RRGraph should NOT include other data which are shared by other data structures outside. - * The rr-graph is the single largest data structure in VPR, - * so avoid adding unnecessary information per node or per edge to it, as it will impact memory footprint. - * Instead, using indices to point to the outside data source instead of embedding to RRGraph - * For example: - * For any placement/routing cost related information, try to extend t_rr_indexed_data, but not RRGraph - * For any placement/routing results, try to extend PlaceContext and RoutingContext, but not RRGraph - * * For those want to develop placers or routers * -------------------------------------------------------------------------- * The RRGraph is designed to be a read-only database/graph, once created. * Placement and routing should NOT change any attributes of RRGraph. - * Any placement and routing results should be stored in other data structures, such as PlaceContext and RoutingContext. + * Any placement and routing results should be stored in other data structures, + *such as PlaceContext and RoutingContext. * - * Tracing Cross-Reference + * Tracing Cross-Reference * ======================= * RRGraph is designed to a self-contained data structure as much as possible. - * It includes the switch information (rr_switch) and segment_information (rr_segment) - * which are necessary to build-up any external data structures. + * It includes the switch information (rr_switch) and segment_information + *(rr_segment) which are necessary to build-up any external data structures. * * Internal cross-reference * ------------------------ @@ -113,9 +121,9 @@ * | | node_in_edges | | * | | node_out_edges | | * | Node |----------------->| Edge | - * | |<-----------------| | - * | | edge_src_node | | - * +--------+ edge_sink_node +--------+ + * | |<-----------------| | + * | | edge_src_node | | + * +--------+ edge_sink_node +--------+ * * * External cross-reference @@ -123,10 +131,11 @@ * The only cross-reference to outside data structures is the cost_index * corresponding to the data structure t_rr_index_data * Details can be found in the definition of t_rr_index_data - * This allows rapid look up by the router of additional information it needs for this node, using a flyweight pattern. + * This allows rapid look up by the router of additional information it needs + *for this node, using a flyweight pattern. * * +---------+ pb_graph_pin +----------------+ - * | RRGraph |---------------->| Pb_graph_node | + * | RRGraph |---------------->| Pb_graph_node | * +---------+ pb_graph_edge +----------------+ * ***********************************************************************/ @@ -134,8 +143,8 @@ #define LB_RR_GRAPH_OBJ_H /* - * Notes in include header files in a head file - * Only include the neccessary header files + * Notes in include header files in a head file + * Only include the neccessary header files * that is required by the data types in the function/class declarations! */ /* Header files should be included in a sequence */ @@ -151,179 +160,187 @@ #include "physical_types.h" /* Header from vpr library */ -#include "pack_types.h" - #include "lb_rr_graph_fwd.h" +#include "pack_types.h" /* begin namespace openfpga */ namespace openfpga { class LbRRGraph { - public: /* Types */ - /* Iterators used to create iterator-based loop for nodes/edges/switches/segments */ - typedef vtr::vector::const_iterator node_iterator; - typedef vtr::vector::const_iterator edge_iterator; + public: /* Types */ + /* Iterators used to create iterator-based loop for + * nodes/edges/switches/segments */ + typedef vtr::vector::const_iterator node_iterator; + typedef vtr::vector::const_iterator edge_iterator; - /* Ranges used to create range-based loop for nodes/edges/switches/segments */ - typedef vtr::Range node_range; - typedef vtr::Range edge_range; + /* Ranges used to create range-based loop for nodes/edges/switches/segments */ + typedef vtr::Range node_range; + typedef vtr::Range edge_range; - public: /* Constructors */ - LbRRGraph(); + public: /* Constructors */ + LbRRGraph(); - public: /* Accessors */ - /* Aggregates: create range-based loops for nodes/edges/switches/segments - * To iterate over the nodes/edges/switches/segments in a RRGraph, - * using a range-based loop is suggested. - * ----------------------------------------------------------------- - * Example: iterate over all the nodes - * // Strongly suggest to use a read-only rr_graph object - * const LbRRGraph& lb_rr_graph; - * for (const LbRRNodeId& node : lb_rr_graph.nodes()) { - * // Do something with each node - * } - * - * for (const LbRREdgeId& edge : lb_rr_graph.edges()) { - * // Do something with each edge - * } - * - */ - node_range nodes() const; - edge_range edges() const; + public: /* Accessors */ + /* Aggregates: create range-based loops for nodes/edges/switches/segments + * To iterate over the nodes/edges/switches/segments in a RRGraph, + * using a range-based loop is suggested. + * ----------------------------------------------------------------- + * Example: iterate over all the nodes + * // Strongly suggest to use a read-only rr_graph object + * const LbRRGraph& lb_rr_graph; + * for (const LbRRNodeId& node : lb_rr_graph.nodes()) { + * // Do something with each node + * } + * + * for (const LbRREdgeId& edge : lb_rr_graph.edges()) { + * // Do something with each edge + * } + * + */ + node_range nodes() const; + edge_range edges() const; - /* Node-level attributes */ - e_lb_rr_type node_type(const LbRRNodeId& node) const; - short node_capacity(const LbRRNodeId& node) const; - t_pb_graph_pin* node_pb_graph_pin(const LbRRNodeId& node) const; - float node_intrinsic_cost(const LbRRNodeId& node) const; + /* Node-level attributes */ + e_lb_rr_type node_type(const LbRRNodeId& node) const; + short node_capacity(const LbRRNodeId& node) const; + t_pb_graph_pin* node_pb_graph_pin(const LbRRNodeId& node) const; + float node_intrinsic_cost(const LbRRNodeId& node) const; - /* Get a list of edge ids, which are incoming edges to a node */ - std::vector node_in_edges(const LbRRNodeId& node) const; - std::vector node_in_edges(const LbRRNodeId& node, t_mode* mode) const; + /* Get a list of edge ids, which are incoming edges to a node */ + std::vector node_in_edges(const LbRRNodeId& node) const; + std::vector node_in_edges(const LbRRNodeId& node, + t_mode* mode) const; - /* Get a list of edge ids, which are outgoing edges from a node */ - std::vector node_out_edges(const LbRRNodeId& node) const; - std::vector node_out_edges(const LbRRNodeId& node, t_mode* mode) const; + /* Get a list of edge ids, which are outgoing edges from a node */ + std::vector node_out_edges(const LbRRNodeId& node) const; + std::vector node_out_edges(const LbRRNodeId& node, + t_mode* mode) const; - /* General method to look up a node with type and only pb_graph_pin information */ - LbRRNodeId find_node(const e_lb_rr_type& type, const t_pb_graph_pin* pb_graph_pin) const; - /* Method to find special node */ - LbRRNodeId ext_source_node() const; - LbRRNodeId ext_sink_node() const; + /* General method to look up a node with type and only pb_graph_pin + * information */ + LbRRNodeId find_node(const e_lb_rr_type& type, + const t_pb_graph_pin* pb_graph_pin) const; + /* Method to find special node */ + LbRRNodeId ext_source_node() const; + LbRRNodeId ext_sink_node() const; - /* General method to look up a edge with source and sink nodes */ - std::vector find_edge(const LbRRNodeId& src_node, const LbRRNodeId& sink_node) const; - /* Get the source node which drives a edge */ - LbRRNodeId edge_src_node(const LbRREdgeId& edge) const; - /* Get the sink node which a edge ends to */ - LbRRNodeId edge_sink_node(const LbRREdgeId& edge) const; + /* General method to look up a edge with source and sink nodes */ + std::vector find_edge(const LbRRNodeId& src_node, + const LbRRNodeId& sink_node) const; + /* Get the source node which drives a edge */ + LbRRNodeId edge_src_node(const LbRREdgeId& edge) const; + /* Get the sink node which a edge ends to */ + LbRRNodeId edge_sink_node(const LbRREdgeId& edge) const; - float edge_intrinsic_cost(const LbRREdgeId& edge) const; - t_mode* edge_mode(const LbRREdgeId& edge) const; + float edge_intrinsic_cost(const LbRREdgeId& edge) const; + t_mode* edge_mode(const LbRREdgeId& edge) const; - public: /* Mutators */ - /* Reserve the lists of nodes, edges, switches etc. to be memory efficient. - * This function is mainly used to reserve memory space inside RRGraph, - * when adding a large number of nodes/edge/switches/segments, - * in order to avoid memory fragements - * For example: - * LbRRGraph lb_rr_graph; - * // Add 1000 CHANX nodes to the LbRRGraph object - * rr_graph.reserve_nodes(1000); - * for (size_t i = 0; i < 1000; ++i) { - * rr_graph.create_node(CHANX); - * } - */ - void reserve_nodes(const unsigned long& num_nodes); - void reserve_edges(const unsigned long& num_edges); + public: /* Mutators */ + /* Reserve the lists of nodes, edges, switches etc. to be memory efficient. + * This function is mainly used to reserve memory space inside RRGraph, + * when adding a large number of nodes/edge/switches/segments, + * in order to avoid memory fragements + * For example: + * LbRRGraph lb_rr_graph; + * // Add 1000 CHANX nodes to the LbRRGraph object + * rr_graph.reserve_nodes(1000); + * for (size_t i = 0; i < 1000; ++i) { + * rr_graph.create_node(CHANX); + * } + */ + void reserve_nodes(const unsigned long& num_nodes); + void reserve_edges(const unsigned long& num_edges); - /* Add new elements (node, edge, switch, etc.) to RRGraph */ - /* Add a node to the RRGraph with a deposited type - * Detailed node-level information should be added using the set_node_* functions - * For example: - * RRNodeId node = create_node(); - * set_node_xlow(node, 0); - */ - LbRRNodeId create_node(const e_lb_rr_type& type); - - /* Create special nodes */ - LbRRNodeId create_ext_source_node(const e_lb_rr_type& type); - LbRRNodeId create_ext_sink_node(const e_lb_rr_type& type); + /* Add new elements (node, edge, switch, etc.) to RRGraph */ + /* Add a node to the RRGraph with a deposited type + * Detailed node-level information should be added using the set_node_* + * functions For example: RRNodeId node = create_node(); set_node_xlow(node, + * 0); + */ + LbRRNodeId create_node(const e_lb_rr_type& type); - /* Set node-level information */ - void set_node_type(const LbRRNodeId& node, const e_lb_rr_type& type); + /* Create special nodes */ + LbRRNodeId create_ext_source_node(const e_lb_rr_type& type); + LbRRNodeId create_ext_sink_node(const e_lb_rr_type& type); - void set_node_capacity(const LbRRNodeId& node, const short& capacity); + /* Set node-level information */ + void set_node_type(const LbRRNodeId& node, const e_lb_rr_type& type); - void set_node_pb_graph_pin(const LbRRNodeId& node, t_pb_graph_pin* pb_graph_pin); + void set_node_capacity(const LbRRNodeId& node, const short& capacity); - void set_node_intrinsic_cost(const LbRRNodeId& node, const float& cost); + void set_node_pb_graph_pin(const LbRRNodeId& node, + t_pb_graph_pin* pb_graph_pin); - /* Add a edge to the RRGraph, by providing the source and sink node - * This function will automatically create a node and - * configure the nodes and edges in connection - */ - LbRREdgeId create_edge(const LbRRNodeId& source, const LbRRNodeId& sink, t_mode* mode); - void set_edge_intrinsic_cost(const LbRREdgeId& edge, const float& cost); + void set_node_intrinsic_cost(const LbRRNodeId& node, const float& cost); - public: /* Public validators */ - /* Validate is the node id does exist in the RRGraph */ - bool valid_node_id(const LbRRNodeId& node) const; + /* Add a edge to the RRGraph, by providing the source and sink node + * This function will automatically create a node and + * configure the nodes and edges in connection + */ + LbRREdgeId create_edge(const LbRRNodeId& source, const LbRRNodeId& sink, + t_mode* mode); + void set_edge_intrinsic_cost(const LbRREdgeId& edge, const float& cost); - /* Validate is the edge id does exist in the RRGraph */ - bool valid_edge_id(const LbRREdgeId& edge) const; + public: /* Public validators */ + /* Validate is the node id does exist in the RRGraph */ + bool valid_node_id(const LbRRNodeId& node) const; - bool validate() const; + /* Validate is the edge id does exist in the RRGraph */ + bool valid_edge_id(const LbRREdgeId& edge) const; - bool empty() const; + bool validate() const; - private: /* Private Validators */ - bool validate_node_sizes() const; - bool validate_edge_sizes() const; - bool validate_sizes() const; - bool validate_node_is_edge_src(const LbRRNodeId& node, const LbRREdgeId& edge) const; - bool validate_node_is_edge_sink(const LbRRNodeId& node, const LbRREdgeId& edge) const; - bool validate_node_in_edges(const LbRRNodeId& node) const; - bool validate_node_out_edges(const LbRRNodeId& node) const; - bool validate_nodes_in_edges() const; - bool validate_nodes_out_edges() const; - bool validate_nodes_edges() const; + bool empty() const; - private: /* Internal Data */ - /* Node related data */ - vtr::vector node_ids_; + private: /* Private Validators */ + bool validate_node_sizes() const; + bool validate_edge_sizes() const; + bool validate_sizes() const; + bool validate_node_is_edge_src(const LbRRNodeId& node, + const LbRREdgeId& edge) const; + bool validate_node_is_edge_sink(const LbRRNodeId& node, + const LbRREdgeId& edge) const; + bool validate_node_in_edges(const LbRRNodeId& node) const; + bool validate_node_out_edges(const LbRRNodeId& node) const; + bool validate_nodes_in_edges() const; + bool validate_nodes_out_edges() const; + bool validate_nodes_edges() const; - vtr::vector node_types_; + private: /* Internal Data */ + /* Node related data */ + vtr::vector node_ids_; - vtr::vector node_capacities_; + vtr::vector node_types_; - vtr::vector node_pb_graph_pins_; + vtr::vector node_capacities_; - vtr::vector node_intrinsic_costs_; + vtr::vector node_pb_graph_pins_; - /* Edges per node is sorted by modes: [][] */ - vtr::vector> node_in_edges_; - vtr::vector> node_out_edges_; + vtr::vector node_intrinsic_costs_; - /* Edge related data */ - /* Range of edge ids, use the unsigned long as - * the number of edges could be >10 times larger than the number of nodes! - */ - vtr::vector edge_ids_; - vtr::vector edge_src_nodes_; - vtr::vector edge_sink_nodes_; - vtr::vector edge_intrinsic_costs_; - vtr::vector edge_modes_; + /* Edges per node is sorted by modes: [][] */ + vtr::vector> node_in_edges_; + vtr::vector> node_out_edges_; - /* Fast look-up to search a node by its type, coordinator and ptc_num - * Indexing of fast look-up: [0..NUM_TYPES-1][t_pb_graph_pin*] - */ - typedef std::vector> NodeLookup; - mutable NodeLookup node_lookup_; + /* Edge related data */ + /* Range of edge ids, use the unsigned long as + * the number of edges could be >10 times larger than the number of nodes! + */ + vtr::vector edge_ids_; + vtr::vector edge_src_nodes_; + vtr::vector edge_sink_nodes_; + vtr::vector edge_intrinsic_costs_; + vtr::vector edge_modes_; - /* Special node look-up */ - LbRRNodeId ext_source_node_; - LbRRNodeId ext_sink_node_; + /* Fast look-up to search a node by its type, coordinator and ptc_num + * Indexing of fast look-up: [0..NUM_TYPES-1][t_pb_graph_pin*] + */ + typedef std::vector> NodeLookup; + mutable NodeLookup node_lookup_; + + /* Special node look-up */ + LbRRNodeId ext_source_node_; + LbRRNodeId ext_sink_node_; }; } /* end namespace openfpga */ diff --git a/openfpga/src/repack/lb_rr_graph_utils.cpp b/openfpga/src/repack/lb_rr_graph_utils.cpp index 001a2af17..f56dbf96f 100644 --- a/openfpga/src/repack/lb_rr_graph_utils.cpp +++ b/openfpga/src/repack/lb_rr_graph_utils.cpp @@ -3,12 +3,12 @@ ***************************************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" -#include "vtr_assert.h" -#include "vtr_util.h" - #include "lb_rr_graph_utils.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_util.h" + /* begin namespace openfpga */ namespace openfpga { @@ -31,15 +31,17 @@ std::string describe_lb_rr_node(const LbRRGraph& lb_rr_graph, VTR_ASSERT(LB_SINK == lb_rr_graph.node_type(inode)); description = "cluster-external sink (LB_SINK)"; } else if (LB_SINK == lb_rr_graph.node_type(inode)) { - description = "cluster-internal sink (LB_SINK accessible via architecture pins: "; + description = + "cluster-internal sink (LB_SINK accessible via architecture pins: "; - //To account for equivalent pins multiple pins may route to a single sink. - //As a result we need to fin all the nodes which connect to this sink in order - //to give user-friendly pin names + // To account for equivalent pins multiple pins may route to a single sink. + // As a result we need to fin all the nodes which connect to this sink in + // order to give user-friendly pin names std::vector pin_descriptions; for (const LbRREdgeId edge : lb_rr_graph.node_in_edges(inode)) { const LbRRNodeId pin_rr_idx = lb_rr_graph.edge_src_node(edge); - const t_pb_graph_pin* pin_pb_gpin = lb_rr_graph.node_pb_graph_pin(pin_rr_idx); + const t_pb_graph_pin* pin_pb_gpin = + lb_rr_graph.node_pb_graph_pin(pin_rr_idx); pin_descriptions.push_back(pin_pb_gpin->to_string()); } @@ -58,19 +60,19 @@ std::string describe_lb_rr_node(const LbRRGraph& lb_rr_graph, } /* This function aims to print basic information about a node */ -void print_lb_rr_node(const LbRRGraph& lb_rr_graph, - const LbRRNodeId& node) { - VTR_LOG("Node id: %d\n", size_t(node)); - VTR_LOG("Node type: %s\n", lb_rr_type_str[lb_rr_graph.node_type(node)]); - VTR_LOG("Node capacity: %d\n", lb_rr_graph.node_capacity(node)); - /* Some node, e.g., SOURCE, SINK may not have pb_graph_pin, skip outputing in this case */ - if (nullptr != lb_rr_graph.node_pb_graph_pin(node)) { - VTR_LOG("Node pb_graph_pin: %s\n", lb_rr_graph.node_pb_graph_pin(node)->to_string().c_str()); - } - VTR_LOG("Node intrinsic_cost: %f\n", lb_rr_graph.node_intrinsic_cost(node)); - VTR_LOG("Node num in_edges: %ld\n", lb_rr_graph.node_in_edges(node).size()); - VTR_LOG("Node num out_edges: %ld\n", lb_rr_graph.node_out_edges(node).size()); +void print_lb_rr_node(const LbRRGraph& lb_rr_graph, const LbRRNodeId& node) { + VTR_LOG("Node id: %d\n", size_t(node)); + VTR_LOG("Node type: %s\n", lb_rr_type_str[lb_rr_graph.node_type(node)]); + VTR_LOG("Node capacity: %d\n", lb_rr_graph.node_capacity(node)); + /* Some node, e.g., SOURCE, SINK may not have pb_graph_pin, skip outputing in + * this case */ + if (nullptr != lb_rr_graph.node_pb_graph_pin(node)) { + VTR_LOG("Node pb_graph_pin: %s\n", + lb_rr_graph.node_pb_graph_pin(node)->to_string().c_str()); + } + VTR_LOG("Node intrinsic_cost: %f\n", lb_rr_graph.node_intrinsic_cost(node)); + VTR_LOG("Node num in_edges: %ld\n", lb_rr_graph.node_in_edges(node).size()); + VTR_LOG("Node num out_edges: %ld\n", lb_rr_graph.node_out_edges(node).size()); } - } /* end namespace openfpga */ diff --git a/openfpga/src/repack/lb_rr_graph_utils.h b/openfpga/src/repack/lb_rr_graph_utils.h index f493caa4f..71c23ab1d 100644 --- a/openfpga/src/repack/lb_rr_graph_utils.h +++ b/openfpga/src/repack/lb_rr_graph_utils.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "lb_rr_graph.h" /******************************************************************** @@ -17,8 +18,7 @@ namespace openfpga { std::string describe_lb_rr_node(const LbRRGraph& lb_rr_graph, const LbRRNodeId& inode); -void print_lb_rr_node(const LbRRGraph& lb_rr_graph, - const LbRRNodeId& node); +void print_lb_rr_node(const LbRRGraph& lb_rr_graph, const LbRRNodeId& node); } /* end namespace openfpga */ diff --git a/openfpga/src/repack/physical_pb.cpp b/openfpga/src/repack/physical_pb.cpp index 7667a76fe..83e1b021e 100644 --- a/openfpga/src/repack/physical_pb.cpp +++ b/openfpga/src/repack/physical_pb.cpp @@ -1,28 +1,28 @@ /****************************************************************************** * Memember functions for data structure PhysicalPb ******************************************************************************/ +#include "physical_pb.h" + #include "vtr_assert.h" #include "vtr_log.h" -#include "physical_pb.h" - /* begin namespace openfpga */ namespace openfpga { /************************************************** - * Public Accessors + * Public Accessors *************************************************/ PhysicalPb::physical_pb_range PhysicalPb::pbs() const { return vtr::make_range(pb_ids_.begin(), pb_ids_.end()); } std::vector PhysicalPb::primitive_pbs() const { - std::vector results; + std::vector results; /* The primitive pbs are those without any children */ for (auto pb : pbs()) { if (true == child_pbs_[pb].empty()) { results.push_back(pb); - } + } } return results; } @@ -41,7 +41,7 @@ const t_pb_graph_node* PhysicalPb::pb_graph_node(const PhysicalPbId& pb) const { PhysicalPbId PhysicalPb::find_pb(const t_pb_graph_node* pb_graph_node) const { if (type2id_map_.find(pb_graph_node) != type2id_map_.end()) { /* Find it, return the id */ - return type2id_map_.at(pb_graph_node); + return type2id_map_.at(pb_graph_node); } /* Not found, return an invalid id */ return PhysicalPbId::INVALID(); @@ -52,13 +52,12 @@ PhysicalPbId PhysicalPb::parent(const PhysicalPbId& pb) const { return parent_pbs_[pb]; } -PhysicalPbId PhysicalPb::child(const PhysicalPbId& pb, - const t_pb_type* pb_type, +PhysicalPbId PhysicalPb::child(const PhysicalPbId& pb, const t_pb_type* pb_type, const size_t& index) const { VTR_ASSERT(true == valid_pb_id(pb)); if (0 < child_pbs_[pb].count(pb_type)) { if (index < child_pbs_[pb].at(pb_type).size()) { - return child_pbs_[pb].at(pb_type)[index]; + return child_pbs_[pb].at(pb_type)[index]; } } return PhysicalPbId::INVALID(); @@ -66,16 +65,16 @@ PhysicalPbId PhysicalPb::child(const PhysicalPbId& pb, std::vector PhysicalPb::atom_blocks(const PhysicalPbId& pb) const { VTR_ASSERT(true == valid_pb_id(pb)); - + return atom_blocks_[pb]; } -AtomNetId PhysicalPb::pb_graph_pin_atom_net(const PhysicalPbId& pb, - const t_pb_graph_pin* pb_graph_pin) const { +AtomNetId PhysicalPb::pb_graph_pin_atom_net( + const PhysicalPbId& pb, const t_pb_graph_pin* pb_graph_pin) const { VTR_ASSERT(true == valid_pb_id(pb)); if (pin_atom_nets_[pb].find(pb_graph_pin) != pin_atom_nets_[pb].end()) { /* Find it, return the id */ - return pin_atom_nets_[pb].at(pb_graph_pin); + return pin_atom_nets_[pb].at(pb_graph_pin); } /* Not found, return an invalid id */ return AtomNetId::INVALID(); @@ -86,13 +85,14 @@ bool PhysicalPb::is_wire_lut_output(const PhysicalPbId& pb, VTR_ASSERT(true == valid_pb_id(pb)); if (wire_lut_outputs_[pb].find(pb_graph_pin) != wire_lut_outputs_[pb].end()) { /* Find it, return the status */ - return wire_lut_outputs_[pb].at(pb_graph_pin); + return wire_lut_outputs_[pb].at(pb_graph_pin); } /* Not found, return false */ return false; } -std::map PhysicalPb::truth_tables(const PhysicalPbId& pb) const { +std::map +PhysicalPb::truth_tables(const PhysicalPbId& pb) const { VTR_ASSERT(true == valid_pb_id(pb)); return truth_tables_[pb]; } @@ -112,12 +112,14 @@ size_t PhysicalPb::fixed_bitstream_offset(const PhysicalPbId& pb) const { return fixed_bitstream_offsets_[pb]; } -std::string PhysicalPb::fixed_mode_select_bitstream(const PhysicalPbId& pb) const { +std::string PhysicalPb::fixed_mode_select_bitstream( + const PhysicalPbId& pb) const { VTR_ASSERT(true == valid_pb_id(pb)); return fixed_mode_select_bitstreams_[pb]; } -size_t PhysicalPb::fixed_mode_select_bitstream_offset(const PhysicalPbId& pb) const { +size_t PhysicalPb::fixed_mode_select_bitstream_offset( + const PhysicalPbId& pb) const { VTR_ASSERT(true == valid_pb_id(pb)); return fixed_mode_select_bitstream_offsets_[pb]; } @@ -126,8 +128,10 @@ size_t PhysicalPb::fixed_mode_select_bitstream_offset(const PhysicalPbId& pb) co * Private Mutators ******************************************************************************/ PhysicalPbId PhysicalPb::create_pb(const t_pb_graph_node* pb_graph_node) { - /* Find if the name has been used. If used, return an invalid Id and report error! */ - std::map::iterator it = type2id_map_.find(pb_graph_node); + /* Find if the name has been used. If used, return an invalid Id and report + * error! */ + std::map::iterator it = + type2id_map_.find(pb_graph_node); if (it != type2id_map_.end()) { return PhysicalPbId::INVALID(); } @@ -163,17 +167,18 @@ PhysicalPbId PhysicalPb::create_pb(const t_pb_graph_node* pb_graph_node) { void PhysicalPb::add_child(const PhysicalPbId& parent, const PhysicalPbId& child, const t_pb_type* child_type) { - VTR_ASSERT(true == valid_pb_id(parent)); - VTR_ASSERT(true == valid_pb_id(child)); + VTR_ASSERT(true == valid_pb_id(parent)); + VTR_ASSERT(true == valid_pb_id(child)); child_pbs_[parent][child_type].push_back(child); if (PhysicalPbId::INVALID() != parent_pbs_[child]) { - VTR_LOGF_WARN(__FILE__, __LINE__, - "Overwrite parent '%s' for physical pb '%s' with a new one '%s'!\n", - pb_graph_nodes_[parent_pbs_[child]]->hierarchical_type_name().c_str(), - pb_graph_nodes_[child]->hierarchical_type_name().c_str(), - pb_graph_nodes_[parent]->hierarchical_type_name().c_str()); + VTR_LOGF_WARN( + __FILE__, __LINE__, + "Overwrite parent '%s' for physical pb '%s' with a new one '%s'!\n", + pb_graph_nodes_[parent_pbs_[child]]->hierarchical_type_name().c_str(), + pb_graph_nodes_[child]->hierarchical_type_name().c_str(), + pb_graph_nodes_[parent]->hierarchical_type_name().c_str()); } parent_pbs_[child] = parent; } @@ -181,39 +186,38 @@ void PhysicalPb::add_child(const PhysicalPbId& parent, void PhysicalPb::set_truth_table(const PhysicalPbId& pb, const t_pb_graph_pin* pb_graph_pin, const AtomNetlist::TruthTable& truth_table) { - VTR_ASSERT(true == valid_pb_id(pb)); + VTR_ASSERT(true == valid_pb_id(pb)); if (0 < truth_tables_[pb].count(pb_graph_pin)) { VTR_LOG_WARN("Overwrite truth tables mapped to pb_graph_pin '%s[%ld]!\n", - pb_graph_pin->port->name, pb_graph_pin->pin_number); + pb_graph_pin->port->name, pb_graph_pin->pin_number); } - + truth_tables_[pb][pb_graph_pin] = truth_table; } void PhysicalPb::set_mode_bits(const PhysicalPbId& pb, const std::vector& mode_bits) { - VTR_ASSERT(true == valid_pb_id(pb)); - + VTR_ASSERT(true == valid_pb_id(pb)); + mode_bits_[pb] = mode_bits; } void PhysicalPb::add_atom_block(const PhysicalPbId& pb, const AtomBlockId& atom_block) { - VTR_ASSERT(true == valid_pb_id(pb)); - + VTR_ASSERT(true == valid_pb_id(pb)); + atom_blocks_[pb].push_back(atom_block); } void PhysicalPb::set_pb_graph_pin_atom_net(const PhysicalPbId& pb, const t_pb_graph_pin* pb_graph_pin, const AtomNetId& atom_net) { - VTR_ASSERT(true == valid_pb_id(pb)); + VTR_ASSERT(true == valid_pb_id(pb)); if (pin_atom_nets_[pb].end() != pin_atom_nets_[pb].find(pb_graph_pin)) { VTR_LOG_WARN("Overwrite pb_graph_pin '%s[%d]' atom net '%lu' with '%lu'\n", pb_graph_pin->port->name, pb_graph_pin->pin_number, - size_t(pin_atom_nets_[pb][pb_graph_pin]), - size_t(atom_net)); + size_t(pin_atom_nets_[pb][pb_graph_pin]), size_t(atom_net)); } pin_atom_nets_[pb][pb_graph_pin] = atom_net; @@ -222,7 +226,7 @@ void PhysicalPb::set_pb_graph_pin_atom_net(const PhysicalPbId& pb, void PhysicalPb::set_wire_lut_output(const PhysicalPbId& pb, const t_pb_graph_pin* pb_graph_pin, const bool& wire_lut_output) { - VTR_ASSERT(true == valid_pb_id(pb)); + VTR_ASSERT(true == valid_pb_id(pb)); if (wire_lut_outputs_[pb].end() != wire_lut_outputs_[pb].find(pb_graph_pin)) { VTR_LOG_WARN("Overwrite pb_graph_pin '%s[%d]' status on wire LUT output\n", pb_graph_pin->port->name, pb_graph_pin->pin_number); @@ -233,25 +237,25 @@ void PhysicalPb::set_wire_lut_output(const PhysicalPbId& pb, void PhysicalPb::set_fixed_bitstream(const PhysicalPbId& pb, const std::string& fixed_bitstream) { - VTR_ASSERT(true == valid_pb_id(pb)); + VTR_ASSERT(true == valid_pb_id(pb)); fixed_bitstreams_[pb] = fixed_bitstream; } void PhysicalPb::set_fixed_bitstream_offset(const PhysicalPbId& pb, const size_t& offset) { - VTR_ASSERT(true == valid_pb_id(pb)); + VTR_ASSERT(true == valid_pb_id(pb)); fixed_bitstream_offsets_[pb] = offset; } -void PhysicalPb::set_fixed_mode_select_bitstream(const PhysicalPbId& pb, - const std::string& fixed_bitstream) { - VTR_ASSERT(true == valid_pb_id(pb)); +void PhysicalPb::set_fixed_mode_select_bitstream( + const PhysicalPbId& pb, const std::string& fixed_bitstream) { + VTR_ASSERT(true == valid_pb_id(pb)); fixed_mode_select_bitstreams_[pb] = fixed_bitstream; } void PhysicalPb::set_fixed_mode_select_bitstream_offset(const PhysicalPbId& pb, const size_t& offset) { - VTR_ASSERT(true == valid_pb_id(pb)); + VTR_ASSERT(true == valid_pb_id(pb)); fixed_mode_select_bitstream_offsets_[pb] = offset; } @@ -259,11 +263,9 @@ void PhysicalPb::set_fixed_mode_select_bitstream_offset(const PhysicalPbId& pb, * Private validators/invalidators ******************************************************************************/ bool PhysicalPb::valid_pb_id(const PhysicalPbId& pb_id) const { - return ( size_t(pb_id) < pb_ids_.size() ) && ( pb_id == pb_ids_[pb_id] ); + return (size_t(pb_id) < pb_ids_.size()) && (pb_id == pb_ids_[pb_id]); } -bool PhysicalPb::empty() const { - return 0 == pb_ids_.size(); -} +bool PhysicalPb::empty() const { return 0 == pb_ids_.size(); } } /* end namespace openfpga */ diff --git a/openfpga/src/repack/physical_pb.h b/openfpga/src/repack/physical_pb.h index 7ce42a3c8..ff9652f92 100644 --- a/openfpga/src/repack/physical_pb.h +++ b/openfpga/src/repack/physical_pb.h @@ -13,107 +13,115 @@ /* Headers from vpr library */ #include "atom_netlist.h" - #include "physical_pb_fwd.h" /* Begin namespace openfpga */ namespace openfpga { /******************************************************************** - * PhysicalPb object aims to store the mapped result for a programmable + * PhysicalPb object aims to store the mapped result for a programmable * logical block like the VPR data structure t_pb does. * Differently, it is tailored for the physical implementation of a - * programmable block. + * programmable block. * - It does not contain multi-mode for each child physical_pb while - * VPR t_pb does have multi-mode. This is because that the hardware + * VPR t_pb does have multi-mode. This is because that the hardware * implementation is unique * - It contains mode-selection bits for each primitive physical_pb * This is used to help bitstream generator to configure a primitive * circuit in the correct mode - * - A primitive LUT can be mapped to various truth tables. + * - A primitive LUT can be mapped to various truth tables. * This is true for any fracturable LUTs. *******************************************************************/ class PhysicalPb { - public: /* Types and ranges */ - typedef vtr::vector::const_iterator physical_pb_iterator; - typedef vtr::Range physical_pb_range; - public: /* Public aggregators */ - physical_pb_range pbs() const; - std::vector primitive_pbs() const; - std::string name(const PhysicalPbId& pb) const; - const t_pb_graph_node* pb_graph_node(const PhysicalPbId& pb) const; - PhysicalPbId find_pb(const t_pb_graph_node* name) const; - PhysicalPbId parent(const PhysicalPbId& pb) const; - PhysicalPbId child(const PhysicalPbId& pb, - const t_pb_type* pb_type, - const size_t& index) const; - std::vector atom_blocks(const PhysicalPbId& pb) const; - AtomNetId pb_graph_pin_atom_net(const PhysicalPbId& pb, - const t_pb_graph_pin* pb_graph_pin) const; - bool is_wire_lut_output(const PhysicalPbId& pb, - const t_pb_graph_pin* pb_graph_pin) const; - std::map truth_tables(const PhysicalPbId& pb) const; - std::vector mode_bits(const PhysicalPbId& pb) const; - std::string fixed_bitstream(const PhysicalPbId& pb) const; - size_t fixed_bitstream_offset(const PhysicalPbId& pb) const; - std::string fixed_mode_select_bitstream(const PhysicalPbId& pb) const; - size_t fixed_mode_select_bitstream_offset(const PhysicalPbId& pb) const; - public: /* Public mutators */ - PhysicalPbId create_pb(const t_pb_graph_node* pb_graph_node); - void add_child(const PhysicalPbId& parent, - const PhysicalPbId& child, - const t_pb_type* child_type); - void add_atom_block(const PhysicalPbId& pb, - const AtomBlockId& atom_block); - void set_truth_table(const PhysicalPbId& pb, - const t_pb_graph_pin* pb_graph_pin, - const AtomNetlist::TruthTable& truth_table); - void set_mode_bits(const PhysicalPbId& pb, - const std::vector& mode_bits); - void set_pb_graph_pin_atom_net(const PhysicalPbId& pb, - const t_pb_graph_pin* pb_graph_pin, - const AtomNetId& atom_net); - void set_wire_lut_output(const PhysicalPbId& pb, - const t_pb_graph_pin* pb_graph_pin, - const bool& wire_lut_output); - void set_fixed_bitstream(const PhysicalPbId& pb, - const std::string& fixed_bitstream); - void set_fixed_bitstream_offset(const PhysicalPbId& pb, - const size_t& offset); - void set_fixed_mode_select_bitstream(const PhysicalPbId& pb, - const std::string& fixed_bitstream); - void set_fixed_mode_select_bitstream_offset(const PhysicalPbId& pb, - const size_t& offset); - public: /* Public validators/invalidators */ - bool valid_pb_id(const PhysicalPbId& pb_id) const; - bool empty() const; - private: /* Internal Data */ - vtr::vector pb_ids_; - vtr::vector pb_graph_nodes_; - vtr::vector names_; - vtr::vector> atom_blocks_; - vtr::vector> pin_atom_nets_; - vtr::vector> wire_lut_outputs_; + public: /* Types and ranges */ + typedef vtr::vector::const_iterator + physical_pb_iterator; + typedef vtr::Range physical_pb_range; - /* Child pbs are organized as [0..num_child_pb_types-1][0..child_pb_type->num_pb-1] */ - vtr::vector>> child_pbs_; - vtr::vector parent_pbs_; + public: /* Public aggregators */ + physical_pb_range pbs() const; + std::vector primitive_pbs() const; + std::string name(const PhysicalPbId& pb) const; + const t_pb_graph_node* pb_graph_node(const PhysicalPbId& pb) const; + PhysicalPbId find_pb(const t_pb_graph_node* name) const; + PhysicalPbId parent(const PhysicalPbId& pb) const; + PhysicalPbId child(const PhysicalPbId& pb, const t_pb_type* pb_type, + const size_t& index) const; + std::vector atom_blocks(const PhysicalPbId& pb) const; + AtomNetId pb_graph_pin_atom_net(const PhysicalPbId& pb, + const t_pb_graph_pin* pb_graph_pin) const; + bool is_wire_lut_output(const PhysicalPbId& pb, + const t_pb_graph_pin* pb_graph_pin) const; + std::map truth_tables( + const PhysicalPbId& pb) const; + std::vector mode_bits(const PhysicalPbId& pb) const; + std::string fixed_bitstream(const PhysicalPbId& pb) const; + size_t fixed_bitstream_offset(const PhysicalPbId& pb) const; + std::string fixed_mode_select_bitstream(const PhysicalPbId& pb) const; + size_t fixed_mode_select_bitstream_offset(const PhysicalPbId& pb) const; - /* configuration bits - * Truth tables and mode selection - */ - vtr::vector> truth_tables_; + public: /* Public mutators */ + PhysicalPbId create_pb(const t_pb_graph_node* pb_graph_node); + void add_child(const PhysicalPbId& parent, const PhysicalPbId& child, + const t_pb_type* child_type); + void add_atom_block(const PhysicalPbId& pb, const AtomBlockId& atom_block); + void set_truth_table(const PhysicalPbId& pb, + const t_pb_graph_pin* pb_graph_pin, + const AtomNetlist::TruthTable& truth_table); + void set_mode_bits(const PhysicalPbId& pb, + const std::vector& mode_bits); + void set_pb_graph_pin_atom_net(const PhysicalPbId& pb, + const t_pb_graph_pin* pb_graph_pin, + const AtomNetId& atom_net); + void set_wire_lut_output(const PhysicalPbId& pb, + const t_pb_graph_pin* pb_graph_pin, + const bool& wire_lut_output); + void set_fixed_bitstream(const PhysicalPbId& pb, + const std::string& fixed_bitstream); + void set_fixed_bitstream_offset(const PhysicalPbId& pb, const size_t& offset); + void set_fixed_mode_select_bitstream(const PhysicalPbId& pb, + const std::string& fixed_bitstream); + void set_fixed_mode_select_bitstream_offset(const PhysicalPbId& pb, + const size_t& offset); - vtr::vector> mode_bits_; + public: /* Public validators/invalidators */ + bool valid_pb_id(const PhysicalPbId& pb_id) const; + bool empty() const; - vtr::vector fixed_bitstreams_; - vtr::vector fixed_bitstream_offsets_; + private: /* Internal Data */ + vtr::vector pb_ids_; + vtr::vector pb_graph_nodes_; + vtr::vector names_; + vtr::vector> atom_blocks_; + vtr::vector> + pin_atom_nets_; + vtr::vector> + wire_lut_outputs_; - vtr::vector fixed_mode_select_bitstreams_; - vtr::vector fixed_mode_select_bitstream_offsets_; + /* Child pbs are organized as + * [0..num_child_pb_types-1][0..child_pb_type->num_pb-1] */ + vtr::vector>> + child_pbs_; + vtr::vector parent_pbs_; - /* Fast lookup */ - std::map type2id_map_; + /* configuration bits + * Truth tables and mode selection + */ + vtr::vector> + truth_tables_; + + vtr::vector> mode_bits_; + + vtr::vector fixed_bitstreams_; + vtr::vector fixed_bitstream_offsets_; + + vtr::vector fixed_mode_select_bitstreams_; + vtr::vector fixed_mode_select_bitstream_offsets_; + + /* Fast lookup */ + std::map type2id_map_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/repack/physical_pb_fwd.h b/openfpga/src/repack/physical_pb_fwd.h index d601ab060..31130dd54 100644 --- a/openfpga/src/repack/physical_pb_fwd.h +++ b/openfpga/src/repack/physical_pb_fwd.h @@ -1,5 +1,5 @@ /************************************************** - * This file includes only declarations for + * This file includes only declarations for * the data structures for PhysicalPb * Please refer to physical_pb.h for more details *************************************************/ @@ -20,4 +20,4 @@ class PhysicalPb; } /* end namespace openfpga */ -#endif +#endif diff --git a/openfpga/src/repack/repack.cpp b/openfpga/src/repack/repack.cpp index fec8bca05..33c27937b 100644 --- a/openfpga/src/repack/repack.cpp +++ b/openfpga/src/repack/repack.cpp @@ -3,19 +3,18 @@ ***************************************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from vpr library */ -#include "vpr_utils.h" - -#include "pb_type_utils.h" #include "build_physical_lb_rr_graph.h" #include "lb_router.h" #include "lb_router_utils.h" +#include "pb_type_utils.h" #include "physical_pb_utils.h" #include "repack.h" +#include "vpr_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -24,17 +23,20 @@ namespace openfpga { * Try to find sink pb graph pins through walking through the fan-out edges from * the source pb graph pin * Only the sink meeting the following requirements can be considered: - * - All the fan-out edges between the source and sink are from direct interconnection + * - All the fan-out edges between the source and sink are from direct + *interconnection * - sink is an input of a primitive pb_type - * - * Note: - * - This function is applicable ONLY to single-mode pb_types!!! Because their routing traces - * are deterministic: there is only 1 valid path from a source pin to a sink pin!!! - * - If there is a fan-out of the current source pb graph pin is not a direct interconnection - * the direct search should stop. + * + * Note: + * - This function is applicable ONLY to single-mode pb_types!!! Because their + *routing traces are deterministic: there is only 1 valid path from a source pin + *to a sink pin!!! + * - If there is a fan-out of the current source pb graph pin is not a direct + *interconnection the direct search should stop. * - This function is designed for pb graph without local routing - * For example: direct connection between root pb graph node to the LUT pb graph node - * + * For example: direct connection between root pb graph node to the LUT pb + *graph node + * * root pb_graph_node * +----------------------------------------- * | Intermediate pb_graph_node @@ -54,28 +56,31 @@ namespace openfpga { * I[0]----->+------>+--- ... ---->+------->+------>O[0] * ***************************************************************************************/ -static -bool rec_direct_search_sink_pb_graph_pins(const t_pb_graph_pin* source_pb_pin, - std::vector& sink_pb_pins) { - +static bool rec_direct_search_sink_pb_graph_pins( + const t_pb_graph_pin* source_pb_pin, + std::vector& sink_pb_pins) { std::vector sink_pb_pins_to_search; /* Only support single-mode pb_type!!! */ - //if (1 != source_pb_pin->parent_node->pb_type->num_modes) { + // if (1 != source_pb_pin->parent_node->pb_type->num_modes) { // return false; //} for (int iedge = 0; iedge < source_pb_pin->num_output_edges; ++iedge) { - if (DIRECT_INTERC != source_pb_pin->output_edges[iedge]->interconnect->type) { + if (DIRECT_INTERC != + source_pb_pin->output_edges[iedge]->interconnect->type) { return false; } - for (int ipin = 0; ipin < source_pb_pin->output_edges[iedge]->num_output_pins; ++ipin) { - t_pb_graph_pin* cand_sink_pb_pin = source_pb_pin->output_edges[iedge]->output_pins[ipin]; - if ( (true == is_primitive_pb_type(cand_sink_pb_pin->parent_node->pb_type)) - && (IN_PORT == cand_sink_pb_pin->port->type)) { + for (int ipin = 0; + ipin < source_pb_pin->output_edges[iedge]->num_output_pins; ++ipin) { + t_pb_graph_pin* cand_sink_pb_pin = + source_pb_pin->output_edges[iedge]->output_pins[ipin]; + if ((true == + is_primitive_pb_type(cand_sink_pb_pin->parent_node->pb_type)) && + (IN_PORT == cand_sink_pb_pin->port->type)) { sink_pb_pins.push_back(cand_sink_pb_pin); - } else if ( (true == cand_sink_pb_pin->parent_node->is_root()) - && (OUT_PORT == cand_sink_pb_pin->port->type)) { + } else if ((true == cand_sink_pb_pin->parent_node->is_root()) && + (OUT_PORT == cand_sink_pb_pin->port->type)) { sink_pb_pins.push_back(cand_sink_pb_pin); } else { sink_pb_pins_to_search.push_back(cand_sink_pb_pin); @@ -84,7 +89,8 @@ bool rec_direct_search_sink_pb_graph_pins(const t_pb_graph_pin* source_pb_pin, } for (t_pb_graph_pin* sink_pb_pin : sink_pb_pins_to_search) { - bool direct_search_status = rec_direct_search_sink_pb_graph_pins(sink_pb_pin, sink_pb_pins); + bool direct_search_status = + rec_direct_search_sink_pb_graph_pins(sink_pb_pin, sink_pb_pins); if (false == direct_search_status) { return false; } @@ -95,66 +101,66 @@ bool rec_direct_search_sink_pb_graph_pins(const t_pb_graph_pin* source_pb_pin, } /*************************************************************************************** - * Try find all the sink pins which is mapped to a routing trace in the context of pb route - * This function uses a recursive walk-through over the pb_route - * We will always start from the pb_route of the source pin - * For each sink, + * Try find all the sink pins which is mapped to a routing trace in the context + *of pb route This function uses a recursive walk-through over the pb_route We + *will always start from the pb_route of the source pin For each sink, * - if it is the end point of a routing tree, we add it to the sink list * - An output of top-level pb_graph_node * - An input of a primitive pb_graph_node - * - if it is not the end point of a routing tree, we visit the pb_route + * - if it is not the end point of a routing tree, we visit the pb_route * corresponds to the sink pin * - * Note: when you call this function at the top-level, please provide an empty vector - * of sink_pb_pins!!! + * Note: when you call this function at the top-level, please provide an empty + *vector of sink_pb_pins!!! ***************************************************************************************/ -static -void rec_find_routed_sink_pb_graph_pins(const t_pb* pb, - const t_pb_graph_pin* source_pb_pin, - const AtomNetId& atom_net_id, - const VprDeviceAnnotation& device_annotation, - const std::map& pb_pin_mapped_nets, - t_pb_graph_pin** pb_graph_pin_lookup_from_index, - std::vector& sink_pb_pins) { - +static void rec_find_routed_sink_pb_graph_pins( + const t_pb* pb, const t_pb_graph_pin* source_pb_pin, + const AtomNetId& atom_net_id, const VprDeviceAnnotation& device_annotation, + const std::map& pb_pin_mapped_nets, + t_pb_graph_pin** pb_graph_pin_lookup_from_index, + std::vector& sink_pb_pins) { /* Bypass unused pins */ if (0 == pb->pb_route.count(source_pb_pin->pin_count_in_cluster)) { return; } /* Get the driver pb pin id, it must be valid */ - if (atom_net_id != pb->pb_route[source_pb_pin->pin_count_in_cluster].atom_net_id) { + if (atom_net_id != + pb->pb_route[source_pb_pin->pin_count_in_cluster].atom_net_id) { return; } - /* Check each sink nodes, if pin belongs to an input of a primitive pb_graph_node, it is what we want */ + /* Check each sink nodes, if pin belongs to an input of a primitive + * pb_graph_node, it is what we want */ std::vector sink_pb_pins_to_search; - for (const int& sink_pb_pin_id : pb->pb_route[source_pb_pin->pin_count_in_cluster].sink_pb_pin_ids) { - t_pb_graph_pin* sink_pb_pin = pb_graph_pin_lookup_from_index[sink_pb_pin_id]; + for (const int& sink_pb_pin_id : + pb->pb_route[source_pb_pin->pin_count_in_cluster].sink_pb_pin_ids) { + t_pb_graph_pin* sink_pb_pin = + pb_graph_pin_lookup_from_index[sink_pb_pin_id]; VTR_ASSERT(nullptr != sink_pb_pin); /* We will update sink node list only * - input pins of primitive nodes - * - output pins of top node - */ - if ( (true == is_primitive_pb_type(sink_pb_pin->parent_node->pb_type)) - && (IN_PORT == sink_pb_pin->port->type)) { + * - output pins of top node + */ + if ((true == is_primitive_pb_type(sink_pb_pin->parent_node->pb_type)) && + (IN_PORT == sink_pb_pin->port->type)) { sink_pb_pins.push_back(sink_pb_pin); continue; } - if ( (true == sink_pb_pin->parent_node->is_root()) - && (OUT_PORT == sink_pb_pin->port->type)) { - /* Be careful!!! There is an inconsistency between pb_route and actual net mapping! - * The sink_pb_pin in the pb_route may not be the one we want - * due to net remapping in the routing stage - * If the net becomes invalid, we search all the fan-out of the source pb_pin - * and find one that is mapped to the net + if ((true == sink_pb_pin->parent_node->is_root()) && + (OUT_PORT == sink_pb_pin->port->type)) { + /* Be careful!!! There is an inconsistency between pb_route and actual net + * mapping! The sink_pb_pin in the pb_route may not be the one we want due + * to net remapping in the routing stage If the net becomes invalid, we + * search all the fan-out of the source pb_pin and find one that is mapped + * to the net */ - AtomNetId remapped_net = AtomNetId::INVALID(); + AtomNetId remapped_net = AtomNetId::INVALID(); auto remapped_result = pb_pin_mapped_nets.find(sink_pb_pin); if (remapped_result != pb_pin_mapped_nets.end()) { - remapped_net = remapped_result->second; + remapped_net = remapped_result->second; } if (atom_net_id == remapped_net) { sink_pb_pins.push_back(sink_pb_pin); @@ -163,21 +169,29 @@ void rec_find_routed_sink_pb_graph_pins(const t_pb* pb, bool found_actual_sink_pb_pin = false; for (int iedge = 0; iedge < source_pb_pin->num_output_edges; ++iedge) { /* Bypass the interconnect that does not belong to a physical mode */ - int parent_mode_index = source_pb_pin->output_edges[iedge]->interconnect->parent_mode_index; - VTR_ASSERT(parent_mode_index < sink_pb_pin->parent_node->pb_type->num_modes); - if (&(sink_pb_pin->parent_node->pb_type->modes[parent_mode_index]) - != device_annotation.physical_mode(sink_pb_pin->parent_node->pb_type)) { + int parent_mode_index = + source_pb_pin->output_edges[iedge]->interconnect->parent_mode_index; + VTR_ASSERT(parent_mode_index < + sink_pb_pin->parent_node->pb_type->num_modes); + if (&(sink_pb_pin->parent_node->pb_type->modes[parent_mode_index]) != + device_annotation.physical_mode( + sink_pb_pin->parent_node->pb_type)) { continue; } - for (int ipin = 0; ipin < source_pb_pin->output_edges[iedge]->num_output_pins; ++ipin) { - const t_pb_graph_pin* cand_sink_pb_pin = source_pb_pin->output_edges[iedge]->output_pins[ipin]; - auto cand_remapped_result = pb_pin_mapped_nets.find(cand_sink_pb_pin); - AtomNetId cand_sink_pb_pin_net = AtomNetId::INVALID(); + for (int ipin = 0; + ipin < source_pb_pin->output_edges[iedge]->num_output_pins; + ++ipin) { + const t_pb_graph_pin* cand_sink_pb_pin = + source_pb_pin->output_edges[iedge]->output_pins[ipin]; + auto cand_remapped_result = + pb_pin_mapped_nets.find(cand_sink_pb_pin); + AtomNetId cand_sink_pb_pin_net = AtomNetId::INVALID(); if (cand_remapped_result != pb_pin_mapped_nets.end()) { - cand_sink_pb_pin_net = cand_remapped_result->second; + cand_sink_pb_pin_net = cand_remapped_result->second; } if (atom_net_id == cand_sink_pb_pin_net) { - sink_pb_pins.push_back(const_cast(cand_sink_pb_pin)); + sink_pb_pins.push_back( + const_cast(cand_sink_pb_pin)); found_actual_sink_pb_pin = true; break; } @@ -196,31 +210,32 @@ void rec_find_routed_sink_pb_graph_pins(const t_pb* pb, } for (t_pb_graph_pin* sink_pb_pin : sink_pb_pins_to_search) { - rec_find_routed_sink_pb_graph_pins(pb, sink_pb_pin, atom_net_id, device_annotation, pb_pin_mapped_nets, pb_graph_pin_lookup_from_index, sink_pb_pins); + rec_find_routed_sink_pb_graph_pins( + pb, sink_pb_pin, atom_net_id, device_annotation, pb_pin_mapped_nets, + pb_graph_pin_lookup_from_index, sink_pb_pins); } } /*************************************************************************************** - * A wrapper for the recursive function rec_find_route_sink_pb_graph_pins(), - * we ensure that we provide a clear sink node lists + * A wrapper for the recursive function rec_find_route_sink_pb_graph_pins(), + * we ensure that we provide a clear sink node lists ***************************************************************************************/ -static -std::vector find_routed_pb_graph_pins_atom_net(const t_pb* pb, - const t_pb_graph_pin* source_pb_pin, - const t_pb_graph_pin* packing_source_pb_pin, - const AtomNetId& atom_net_id, - const VprDeviceAnnotation& device_annotation, - const std::map& pb_pin_mapped_nets, - t_pb_graph_pin** pb_graph_pin_lookup_from_index) { - std::vector sink_pb_pins; +static std::vector find_routed_pb_graph_pins_atom_net( + const t_pb* pb, const t_pb_graph_pin* source_pb_pin, + const t_pb_graph_pin* packing_source_pb_pin, const AtomNetId& atom_net_id, + const VprDeviceAnnotation& device_annotation, + const std::map& pb_pin_mapped_nets, + t_pb_graph_pin** pb_graph_pin_lookup_from_index) { + std::vector sink_pb_pins; /* Try to directly search for sink pb_pins from the source_pb_pin, * which is the actual source pin to be routed from - * Note that the packing source_pb_pin is the source pin considered by - * VPR packer, but may not be the actual source!!! + * Note that the packing source_pb_pin is the source pin considered by + * VPR packer, but may not be the actual source!!! */ if (true == source_pb_pin->parent_node->is_root()) { - bool direct_search_status = rec_direct_search_sink_pb_graph_pins(source_pb_pin, sink_pb_pins); + bool direct_search_status = + rec_direct_search_sink_pb_graph_pins(source_pb_pin, sink_pb_pins); if (true == direct_search_status) { VTR_ASSERT(!sink_pb_pins.empty()); /* We have find through direct searching, return now */ @@ -232,28 +247,30 @@ std::vector find_routed_pb_graph_pins_atom_net(const t_pb* pb, sink_pb_pins.clear(); } - rec_find_routed_sink_pb_graph_pins(pb, packing_source_pb_pin, atom_net_id, device_annotation, pb_pin_mapped_nets, pb_graph_pin_lookup_from_index, sink_pb_pins); + rec_find_routed_sink_pb_graph_pins( + pb, packing_source_pb_pin, atom_net_id, device_annotation, + pb_pin_mapped_nets, pb_graph_pin_lookup_from_index, sink_pb_pins); - return sink_pb_pins; + return sink_pb_pins; } /*************************************************************************************** - * This function will find the actual routing traces of the demanded net + * This function will find the actual routing traces of the demanded net * There is a specific search space applied when searching the routing traces: - * - ONLY applicable to the pb_pin of top-level pb_graph_node + * - ONLY applicable to the pb_pin of top-level pb_graph_node * - candidate can be limited to a set of pb pins ***************************************************************************************/ -static -std::vector find_pb_route_by_atom_net(const t_pb* pb, - const t_pb_graph_pin* source_pb_pin, - const AtomNetId& atom_net_id) { - VTR_ASSERT(true == source_pb_pin->parent_node->is_root()); +static std::vector find_pb_route_by_atom_net( + const t_pb* pb, const t_pb_graph_pin* source_pb_pin, + const AtomNetId& atom_net_id) { + VTR_ASSERT(true == source_pb_pin->parent_node->is_root()); std::vector pb_route_indices; for (int pin = 0; pin < pb->pb_graph_node->total_pb_pins; ++pin) { /* Bypass unused pins */ - if ((0 == pb->pb_route.count(pin)) || (AtomNetId::INVALID() == pb->pb_route.at(pin).atom_net_id)) { + if ((0 == pb->pb_route.count(pin)) || + (AtomNetId::INVALID() == pb->pb_route.at(pin).atom_net_id)) { continue; } /* Get the driver pb pin id, it must be valid */ @@ -270,32 +287,32 @@ std::vector find_pb_route_by_atom_net(const t_pb* pb, } /*************************************************************************************** - * This function will find the actual source_pb_pin that is mapped by packed in the pb route - * As the inputs of clustered block may be renamed during routing, + * This function will find the actual source_pb_pin that is mapped by packed in + *the pb route As the inputs of clustered block may be renamed during routing, * our pb_route results may lose consistency. * It is possible that the source pb_pin may not be mapped during packing but * be mapped during routing * - * Note: this is ONLY applicable to the pb_pin of top-level pb_graph_node + * Note: this is ONLY applicable to the pb_pin of top-level pb_graph_node ***************************************************************************************/ -static -std::vector find_pb_route_remapped_source_pb_pin(const t_pb* pb, - const t_pb_graph_pin* source_pb_pin, - const AtomNetId& atom_net_id) { - VTR_ASSERT(true == source_pb_pin->parent_node->is_root()); +static std::vector find_pb_route_remapped_source_pb_pin( + const t_pb* pb, const t_pb_graph_pin* source_pb_pin, + const AtomNetId& atom_net_id) { + VTR_ASSERT(true == source_pb_pin->parent_node->is_root()); std::vector pb_route_indices; for (int pin = 0; pin < pb->pb_graph_node->total_pb_pins; ++pin) { /* Bypass unused pins */ - if ((0 == pb->pb_route.count(pin)) || (AtomNetId::INVALID() == pb->pb_route.at(pin).atom_net_id)) { + if ((0 == pb->pb_route.count(pin)) || + (AtomNetId::INVALID() == pb->pb_route.at(pin).atom_net_id)) { continue; } /* Get the driver pb pin id, it must be valid */ if (atom_net_id != pb->pb_route.at(pin).atom_net_id) { continue; } - /* Only care the pin has the same parent port as source_pb_pin + /* Only care the pin has the same parent port as source_pb_pin * Due to that the source_pb_pin may be swapped during routing * the pb_route is out-of-date * @@ -309,13 +326,13 @@ std::vector find_pb_route_remapped_source_pb_pin(const t_pb* pb, if (PortEquivalence::FULL == source_pb_pin->port->equivalent) { if (source_pb_pin->port == pb->pb_route.at(pin).pb_graph_pin->port) { pb_route_indices.push_back(pin); - } + } } else { /* NOTE: INSTANCE is NOT supported! We support only NONE equivalent */ - VTR_ASSERT (PortEquivalence::NONE == source_pb_pin->port->equivalent); + VTR_ASSERT(PortEquivalence::NONE == source_pb_pin->port->equivalent); if (source_pb_pin == pb->pb_route.at(pin).pb_graph_pin) { pb_route_indices.push_back(pin); - } + } } } @@ -329,10 +346,9 @@ std::vector find_pb_route_remapped_source_pb_pin(const t_pb* pb, * we will find the associated physical pb_graph_node as well as physical pins * and then spot the nodes in lb_rr_graph ***************************************************************************************/ -static -std::vector find_lb_net_physical_sink_lb_rr_nodes(const LbRRGraph& lb_rr_graph, - const std::vector& sink_pins, - const VprDeviceAnnotation& device_annotation) { +static std::vector find_lb_net_physical_sink_lb_rr_nodes( + const LbRRGraph& lb_rr_graph, const std::vector& sink_pins, + const VprDeviceAnnotation& device_annotation) { std::vector sink_nodes; for (t_pb_graph_pin* sink_pin : sink_pins) { @@ -342,27 +358,30 @@ std::vector find_lb_net_physical_sink_lb_rr_nodes(const LbRRGraph& l physical_sink_pin = sink_pin; } else { physical_sink_pin = device_annotation.physical_pb_graph_pin(sink_pin); - } + } /* if this is the root node, the physical pin is its self */ if (nullptr == physical_sink_pin) { VTR_LOGF_ERROR(__FILE__, __LINE__, "Fail to find a physical pin for operating pin '%s'!\n", sink_pin->to_string().c_str()); - } + } VTR_ASSERT(nullptr != physical_sink_pin); /* Sink nodes should NOT be any output pin of primitive pb_graph_node, * warn that we will not include it in the sink nodes */ - if ( (true == is_primitive_pb_type(physical_sink_pin->parent_node->pb_type)) - && (OUT_PORT == physical_sink_pin->port->type)) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Sink pin '%s' should NOT be an output from a primitive pb_type!\n", - sink_pin->to_string().c_str()); + if ((true == + is_primitive_pb_type(physical_sink_pin->parent_node->pb_type)) && + (OUT_PORT == physical_sink_pin->port->type)) { + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Sink pin '%s' should NOT be an output from a primitive pb_type!\n", + sink_pin->to_string().c_str()); } - LbRRNodeId sink_lb_rr_node = lb_rr_graph.find_node(LB_INTERMEDIATE, physical_sink_pin); + LbRRNodeId sink_lb_rr_node = + lb_rr_graph.find_node(LB_INTERMEDIATE, physical_sink_pin); if (true != lb_rr_graph.valid_node_id(sink_lb_rr_node)) { VTR_LOGF_ERROR(__FILE__, __LINE__, "Fail to find the lb_rr_node for pb_graph_pin '%s'\n", @@ -380,44 +399,46 @@ std::vector find_lb_net_physical_sink_lb_rr_nodes(const LbRRGraph& l * Create nets to be routed, including the source nodes and terminals * And add them to the logical block router ***************************************************************************************/ -static -void add_lb_router_nets(LbRouter& lb_router, - t_logical_block_type_ptr lb_type, - const LbRRGraph& lb_rr_graph, - const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, - const ClusteringContext& clustering_ctx, - const VprClusteringAnnotation& clustering_annotation, - const ClusterBlockId& block_id, - const RepackOption& options) { +static void add_lb_router_nets( + LbRouter& lb_router, t_logical_block_type_ptr lb_type, + const LbRRGraph& lb_rr_graph, const AtomContext& atom_ctx, + const VprDeviceAnnotation& device_annotation, + const ClusteringContext& clustering_ctx, + const VprClusteringAnnotation& clustering_annotation, + const ClusterBlockId& block_id, const RepackOption& options) { size_t net_counter = 0; bool verbose = options.verbose_output(); RepackDesignConstraints design_constraints = options.design_constraints(); /* Two spots to find source nodes for each nets * - nets that appear in the inputs of a clustered block - * Note that these nets may be moved to another input of the same cluster block - * we will locate the final pin and consider its corresponding routing resource node as source + * Note that these nets may be moved to another input of the same cluster + * block we will locate the final pin and consider its corresponding routing + * resource node as source * - nets that appear in the outputs of a primitive pb_graph_node * Note that these primitive pb_graph node are operating pb_graph_node * while we are considering physical pb_graph node - * Therefore, we will find the outputs of physical pb_graph_node corresponding to the operating one - * and then consider the assoicated routing resource node as source + * Therefore, we will find the outputs of physical pb_graph_node + * corresponding to the operating one and then consider the assoicated routing + * resource node as source */ t_pb* pb = clustering_ctx.clb_nlist.block_pb(block_id); VTR_ASSERT(true == pb->pb_graph_node->is_root()); /* Build the fast look-up between pb_pin_id and pb_graph_pin pointer */ - t_pb_graph_pin** pb_graph_pin_lookup_from_index = alloc_and_load_pb_graph_pin_lookup_from_index(lb_type); + t_pb_graph_pin** pb_graph_pin_lookup_from_index = + alloc_and_load_pb_graph_pin_lookup_from_index(lb_type); - /* Build a fast look-up between pb_graph_pin and atom net id which it is mapped to - * Note that, we only care the pb_graph_pin at the root pb_graph_node - * where pb_graph_pin may be remapped to a new net due to routing optimization + /* Build a fast look-up between pb_graph_pin and atom net id which it is + * mapped to Note that, we only care the pb_graph_pin at the root + * pb_graph_node where pb_graph_pin may be remapped to a new net due to + * routing optimization */ std::map pb_pin_mapped_nets; for (int j = 0; j < lb_type->pb_type->num_pins; j++) { /* Find the net mapped to this pin in clustering results*/ - ClusterNetId cluster_net_id = clustering_ctx.clb_nlist.block_net(block_id, j); + ClusterNetId cluster_net_id = + clustering_ctx.clb_nlist.block_net(block_id, j); /* Get the actual net id because it may be renamed during routing */ if (true == clustering_annotation.is_net_renamed(block_id, j)) { cluster_net_id = clustering_annotation.net(block_id, j); @@ -428,8 +449,10 @@ void add_lb_router_nets(LbRouter& lb_router, continue; } - /* Get the source pb_graph pin and find the rr_node in logical block routing resource graph */ - const t_pb_graph_pin* pb_pin = get_pb_graph_node_pin_from_block_pin(block_id, j); + /* Get the source pb_graph pin and find the rr_node in logical block routing + * resource graph */ + const t_pb_graph_pin* pb_pin = + get_pb_graph_node_pin_from_block_pin(block_id, j); VTR_ASSERT(pb_pin->parent_node == pb->pb_graph_node); AtomNetId atom_net_id = atom_ctx.lookup.atom_net(cluster_net_id); @@ -438,12 +461,15 @@ void add_lb_router_nets(LbRouter& lb_router, pb_pin_mapped_nets[pb_pin] = atom_net_id; } - /* Cache the sink nodes/routing traces for the global nets which is specifed to be ignored on given pins */ + /* Cache the sink nodes/routing traces for the global nets which is specifed + * to be ignored on given pins */ std::map> ignored_global_net_sinks; std::map ignored_atom_nets; for (int j = 0; j < lb_type->pb_type->num_pins; j++) { - /* Get the source pb_graph pin and find the rr_node in logical block routing resource graph */ - const t_pb_graph_pin* source_pb_pin = get_pb_graph_node_pin_from_block_pin(block_id, j); + /* Get the source pb_graph pin and find the rr_node in logical block routing + * resource graph */ + const t_pb_graph_pin* source_pb_pin = + get_pb_graph_node_pin_from_block_pin(block_id, j); VTR_ASSERT(source_pb_pin->parent_node == pb->pb_graph_node); /* Bypass output pins */ @@ -452,7 +478,8 @@ void add_lb_router_nets(LbRouter& lb_router, } /* Find the net mapped to this pin in clustering results*/ - ClusterNetId cluster_net_id = clustering_ctx.clb_nlist.block_net(block_id, j); + ClusterNetId cluster_net_id = + clustering_ctx.clb_nlist.block_net(block_id, j); /* Get the actual net id because it may be renamed during routing */ if (true == clustering_annotation.is_net_renamed(block_id, j)) { cluster_net_id = clustering_annotation.net(block_id, j); @@ -464,41 +491,58 @@ void add_lb_router_nets(LbRouter& lb_router, } /* Only for global net which should be ignored, cache the sink nodes */ - BasicPort curr_pin(std::string(source_pb_pin->port->name), source_pb_pin->pin_number, source_pb_pin->pin_number); - if ( (clustering_ctx.clb_nlist.net_is_ignored(cluster_net_id)) - && (clustering_ctx.clb_nlist.net_is_global(cluster_net_id)) - && (options.is_pin_ignore_global_nets(std::string(lb_type->pb_type->name), curr_pin))) { + BasicPort curr_pin(std::string(source_pb_pin->port->name), + source_pb_pin->pin_number, source_pb_pin->pin_number); + if ((clustering_ctx.clb_nlist.net_is_ignored(cluster_net_id)) && + (clustering_ctx.clb_nlist.net_is_global(cluster_net_id)) && + (options.is_pin_ignore_global_nets(std::string(lb_type->pb_type->name), + curr_pin))) { /* Find the net mapped to this pin in clustering results*/ AtomNetId atom_net_id = pb_pin_mapped_nets[source_pb_pin]; - std::vector pb_route_indices = find_pb_route_by_atom_net(pb, source_pb_pin, atom_net_id); + std::vector pb_route_indices = + find_pb_route_by_atom_net(pb, source_pb_pin, atom_net_id); VTR_ASSERT(1 == pb_route_indices.size()); int pb_route_index = pb_route_indices[0]; - t_pb_graph_pin* packing_source_pb_pin = get_pb_graph_node_pin_from_block_pin(block_id, pb_route_index); + t_pb_graph_pin* packing_source_pb_pin = + get_pb_graph_node_pin_from_block_pin(block_id, pb_route_index); VTR_ASSERT(nullptr != packing_source_pb_pin); - /* Find all the sink pins in the pb_route, we walk through the input pins and find the pin */ - std::vector sink_pb_graph_pins = find_routed_pb_graph_pins_atom_net(pb, source_pb_pin, packing_source_pb_pin, atom_net_id, device_annotation, pb_pin_mapped_nets, pb_graph_pin_lookup_from_index); - std::vector sink_lb_rr_nodes = find_lb_net_physical_sink_lb_rr_nodes(lb_rr_graph, sink_pb_graph_pins, device_annotation); + /* Find all the sink pins in the pb_route, we walk through the input pins + * and find the pin */ + std::vector sink_pb_graph_pins = + find_routed_pb_graph_pins_atom_net( + pb, source_pb_pin, packing_source_pb_pin, atom_net_id, + device_annotation, pb_pin_mapped_nets, + pb_graph_pin_lookup_from_index); + std::vector sink_lb_rr_nodes = + find_lb_net_physical_sink_lb_rr_nodes(lb_rr_graph, sink_pb_graph_pins, + device_annotation); VTR_ASSERT(sink_lb_rr_nodes.size() == sink_pb_graph_pins.size()); - ignored_global_net_sinks[atom_net_id].insert(ignored_global_net_sinks[atom_net_id].end(), sink_lb_rr_nodes.begin(), sink_lb_rr_nodes.end()); + ignored_global_net_sinks[atom_net_id].insert( + ignored_global_net_sinks[atom_net_id].end(), sink_lb_rr_nodes.begin(), + sink_lb_rr_nodes.end()); ignored_atom_nets[atom_net_id] = true; } } /* Cache all the source nodes and sinks node for each net - * net_terminal[net][0] is the list of source nodes - * net_terminal[net][1] is the list of sink nodes + * net_terminal[net][0] is the list of source nodes + * net_terminal[net][1] is the list of sink nodes */ std::map, 2>> net_terminals; - /* A list showing that some sinks should be touched by some sources in a multi-source net */ - std::map>> invisible_sinks; + /* A list showing that some sinks should be touched by some sources in a + * multi-source net */ + std::map>> + invisible_sinks; /* Find the source nodes for the nets mapped to inputs of a clustered block */ for (int j = 0; j < lb_type->pb_type->num_pins; j++) { - /* Get the source pb_graph pin and find the rr_node in logical block routing resource graph */ - const t_pb_graph_pin* source_pb_pin = get_pb_graph_node_pin_from_block_pin(block_id, j); + /* Get the source pb_graph pin and find the rr_node in logical block routing + * resource graph */ + const t_pb_graph_pin* source_pb_pin = + get_pb_graph_node_pin_from_block_pin(block_id, j); VTR_ASSERT(source_pb_pin->parent_node == pb->pb_graph_node); /* Bypass output pins */ @@ -509,35 +553,44 @@ void add_lb_router_nets(LbRouter& lb_router, /* Find the net mapped to this pin in clustering results*/ AtomNetId atom_net_id = pb_pin_mapped_nets[source_pb_pin]; - BasicPort curr_pin(std::string(source_pb_pin->port->name), source_pb_pin->pin_number, source_pb_pin->pin_number); - if ( (ignored_atom_nets[atom_net_id]) - && (options.is_pin_ignore_global_nets(std::string(lb_type->pb_type->name), curr_pin))) { + BasicPort curr_pin(std::string(source_pb_pin->port->name), + source_pb_pin->pin_number, source_pb_pin->pin_number); + if ((ignored_atom_nets[atom_net_id]) && + (options.is_pin_ignore_global_nets(std::string(lb_type->pb_type->name), + curr_pin))) { continue; } /* Check if the net information is constrained or not */ - std::string constrained_net_name = design_constraints.find_constrained_pin_net(std::string(lb_type->pb_type->name), BasicPort(std::string(source_pb_pin->port->name), source_pb_pin->pin_number, source_pb_pin->pin_number)); + std::string constrained_net_name = + design_constraints.find_constrained_pin_net( + std::string(lb_type->pb_type->name), + BasicPort(std::string(source_pb_pin->port->name), + source_pb_pin->pin_number, source_pb_pin->pin_number)); /* Find the constrained net mapped to this pin in clustering results */ AtomNetId constrained_atom_net_id = AtomNetId::INVALID(); - /* If the pin is constrained, we need to + /* If the pin is constrained, we need to * - if this is an open net, for invalid net then - * - if this is valid net name, find the net id from atom_netlist + * - if this is valid net name, find the net id from atom_netlist * and overwrite the atom net id to mapped */ - if ( (!design_constraints.unconstrained_net(constrained_net_name)) - && (!design_constraints.unmapped_net(constrained_net_name))) { - constrained_atom_net_id = atom_ctx.nlist.find_net(constrained_net_name); + if ((!design_constraints.unconstrained_net(constrained_net_name)) && + (!design_constraints.unmapped_net(constrained_net_name))) { + constrained_atom_net_id = atom_ctx.nlist.find_net(constrained_net_name); if (false == atom_ctx.nlist.valid_net_id(constrained_atom_net_id)) { - VTR_LOG_WARN("Invalid net '%s' to be constrained! Will drop the constraint in repacking\n", - constrained_net_name.c_str()); + VTR_LOG_WARN( + "Invalid net '%s' to be constrained! Will drop the constraint in " + "repacking\n", + constrained_net_name.c_str()); } else { - VTR_ASSERT_SAFE(false == atom_ctx.nlist.valid_net_id(constrained_atom_net_id)); + VTR_ASSERT_SAFE(false == + atom_ctx.nlist.valid_net_id(constrained_atom_net_id)); VTR_LOGV(verbose, - "Accept net '%s' to be constrained on pin '%s[%d]' during repacking\n", - constrained_net_name.c_str(), - source_pb_pin->port->name, + "Accept net '%s' to be constrained on pin '%s[%d]' during " + "repacking\n", + constrained_net_name.c_str(), source_pb_pin->port->name, source_pb_pin->pin_number); } } else if (design_constraints.unconstrained_net(constrained_net_name)) { @@ -568,83 +621,99 @@ void add_lb_router_nets(LbRouter& lb_router, /* If we have a net to route, it must be the constrained net */ AtomNetId atom_net_id_to_route = constrained_atom_net_id; - /* The outputs of pb_graph_node is INTERMEDIATE node in the routing resource graph, - * they are all connected to a common source node + /* The outputs of pb_graph_node is INTERMEDIATE node in the routing resource + * graph, they are all connected to a common source node */ - LbRRNodeId source_lb_rr_node = lb_rr_graph.find_node(LB_INTERMEDIATE, source_pb_pin); + LbRRNodeId source_lb_rr_node = + lb_rr_graph.find_node(LB_INTERMEDIATE, source_pb_pin); VTR_ASSERT(true == lb_rr_graph.valid_node_id(source_lb_rr_node)); /* Output verbose messages for debugging only */ - VTR_LOGV(verbose, - "Pb route for Net %s:\n", + VTR_LOGV(verbose, "Pb route for Net %s:\n", atom_ctx.nlist.net_name(atom_net_id_to_route).c_str()); /* As the pin remapping is allowed during routing, we should - * - Find the routing traces from packing results which is mapped to the net - * from the same port (as remapping is allowed for pins in the same port only) - * - Find the source pb_graph_pin that drives the routing traces during packing + * - Find the routing traces from packing results which is mapped to the net + * from the same port (as remapping is allowed for pins in the same port + * only) + * - Find the source pb_graph_pin that drives the routing traces during + * packing * - Then we can find the sink nodes * - * When there is a pin constraint applied. The routing trace - * - Find the routing traces from packing results which is mapped to the net + * When there is a pin constraint applied. The routing trace + * - Find the routing traces from packing results which is mapped to the net * with the same port constraints */ std::vector pb_route_indices; if (design_constraints.unconstrained_net(constrained_net_name)) { - pb_route_indices = find_pb_route_remapped_source_pb_pin(pb, source_pb_pin, atom_net_id_to_route); + pb_route_indices = find_pb_route_remapped_source_pb_pin( + pb, source_pb_pin, atom_net_id_to_route); } else { - VTR_ASSERT_SAFE(!design_constraints.unconstrained_net(constrained_net_name)); - pb_route_indices = find_pb_route_by_atom_net(pb, source_pb_pin, atom_net_id_to_route); + VTR_ASSERT_SAFE( + !design_constraints.unconstrained_net(constrained_net_name)); + pb_route_indices = + find_pb_route_by_atom_net(pb, source_pb_pin, atom_net_id_to_route); } - /* It could happen that the constrained net is NOT used in this clb, we just skip it for routing - * For example, a clkB net is never mapped to any ports in the pb that is clocked by clkA net + /* It could happen that the constrained net is NOT used in this clb, we just + * skip it for routing For example, a clkB net is never mapped to any ports + * in the pb that is clocked by clkA net * */ int pb_route_index; if (0 == pb_route_indices.size()) { - VTR_LOGV(verbose, - "Bypass routing due to no routing traces found\n"); + VTR_LOGV(verbose, "Bypass routing due to no routing traces found\n"); continue; } else { VTR_ASSERT(1 == pb_route_indices.size()); pb_route_index = pb_route_indices[0]; } - t_pb_graph_pin* packing_source_pb_pin = get_pb_graph_node_pin_from_block_pin(block_id, pb_route_index); + t_pb_graph_pin* packing_source_pb_pin = + get_pb_graph_node_pin_from_block_pin(block_id, pb_route_index); VTR_ASSERT(nullptr != packing_source_pb_pin); - /* Find all the sink pins in the pb_route, we walk through the input pins and find the pin */ - std::vector sink_pb_graph_pins = find_routed_pb_graph_pins_atom_net(pb, source_pb_pin, packing_source_pb_pin, atom_net_id_to_route, device_annotation, pb_pin_mapped_nets, pb_graph_pin_lookup_from_index); - std::vector sink_lb_rr_nodes = find_lb_net_physical_sink_lb_rr_nodes(lb_rr_graph, sink_pb_graph_pins, device_annotation); + /* Find all the sink pins in the pb_route, we walk through the input pins + * and find the pin */ + std::vector sink_pb_graph_pins = + find_routed_pb_graph_pins_atom_net( + pb, source_pb_pin, packing_source_pb_pin, atom_net_id_to_route, + device_annotation, pb_pin_mapped_nets, pb_graph_pin_lookup_from_index); + std::vector sink_lb_rr_nodes = + find_lb_net_physical_sink_lb_rr_nodes(lb_rr_graph, sink_pb_graph_pins, + device_annotation); VTR_ASSERT(sink_lb_rr_nodes.size() == sink_pb_graph_pins.size()); /* Output verbose messages for debugging only */ - VTR_LOGV(verbose, - "Source node:\n\t%s -> %s\n", + VTR_LOGV(verbose, "Source node:\n\t%s -> %s\n", source_pb_pin->to_string().c_str(), source_pb_pin->to_string().c_str()); VTR_LOGV(verbose, "Sink nodes:\n"); for (t_pb_graph_pin* sink_pb_pin : sink_pb_graph_pins) { - VTR_LOGV(verbose, - "\t%s\n", - sink_pb_pin->to_string().c_str()); + VTR_LOGV(verbose, "\t%s\n", sink_pb_pin->to_string().c_str()); } /* Append sink nodes from ignored global net cache */ - sink_lb_rr_nodes.insert(sink_lb_rr_nodes.end(), ignored_global_net_sinks[atom_net_id_to_route].begin(), ignored_global_net_sinks[atom_net_id_to_route].end()); - VTR_LOGV(verbose, "Append %ld sinks from the routing traces of ignored global nets\n", ignored_global_net_sinks[atom_net_id_to_route].size()); + sink_lb_rr_nodes.insert( + sink_lb_rr_nodes.end(), + ignored_global_net_sinks[atom_net_id_to_route].begin(), + ignored_global_net_sinks[atom_net_id_to_route].end()); + VTR_LOGV( + verbose, + "Append %ld sinks from the routing traces of ignored global nets\n", + ignored_global_net_sinks[atom_net_id_to_route].size()); /* Add the net */ - add_lb_router_net_to_route(lb_router, lb_rr_graph, - std::vector(1, source_lb_rr_node), - sink_lb_rr_nodes, - atom_ctx, atom_net_id_to_route); + add_lb_router_net_to_route( + lb_router, lb_rr_graph, std::vector(1, source_lb_rr_node), + sink_lb_rr_nodes, atom_ctx, atom_net_id_to_route); net_counter++; } - /* Find the source nodes for the nets mapped to outputs of primitive pb_graph_node */ + /* Find the source nodes for the nets mapped to outputs of primitive + * pb_graph_node */ for (int pin = 0; pin < pb->pb_graph_node->total_pb_pins; ++pin) { /* Bypass unused pins */ - if ((0 == pb->pb_route.count(pin)) || (AtomNetId::INVALID() == pb->pb_route[pin].atom_net_id)) { + if ((0 == pb->pb_route.count(pin)) || + (AtomNetId::INVALID() == pb->pb_route[pin].atom_net_id)) { continue; } /* Get the driver pb pin id, it must be valid */ @@ -652,10 +721,13 @@ void add_lb_router_nets(LbRouter& lb_router, if (OPEN == source_pb_pin_id) { continue; } - VTR_ASSERT(OPEN != source_pb_pin_id && source_pb_pin_id < pb->pb_graph_node->total_pb_pins); + VTR_ASSERT(OPEN != source_pb_pin_id && + source_pb_pin_id < pb->pb_graph_node->total_pb_pins); /* Find the corresponding pb_graph_pin and its physical pb_graph_pin */ - t_pb_graph_pin* source_pb_pin = pb_graph_pin_lookup_from_index[source_pb_pin_id]; - /* Skip the pin from top-level pb_graph_node, they have been handled already */ + t_pb_graph_pin* source_pb_pin = + pb_graph_pin_lookup_from_index[source_pb_pin_id]; + /* Skip the pin from top-level pb_graph_node, they have been handled already + */ if (source_pb_pin->parent_node == pb->pb_graph_node) { continue; } @@ -668,78 +740,81 @@ void add_lb_router_nets(LbRouter& lb_router, continue; } - /* The outputs of pb_graph_node is SOURCE node in the routing resource graph */ - t_pb_graph_pin* physical_source_pb_pin = device_annotation.physical_pb_graph_pin(source_pb_pin); - LbRRNodeId source_lb_rr_node = lb_rr_graph.find_node(LB_SOURCE, physical_source_pb_pin); + /* The outputs of pb_graph_node is SOURCE node in the routing resource graph + */ + t_pb_graph_pin* physical_source_pb_pin = + device_annotation.physical_pb_graph_pin(source_pb_pin); + LbRRNodeId source_lb_rr_node = + lb_rr_graph.find_node(LB_SOURCE, physical_source_pb_pin); VTR_ASSERT(true == lb_rr_graph.valid_node_id(source_lb_rr_node)); AtomNetId atom_net_id = pb->pb_route[pin].atom_net_id; VTR_ASSERT(AtomNetId::INVALID() != atom_net_id); /* Find all the sink pins in the pb_route */ - std::vector sink_pb_graph_pins = find_routed_pb_graph_pins_atom_net(pb, physical_source_pb_pin, source_pb_pin, atom_net_id, device_annotation, pb_pin_mapped_nets, pb_graph_pin_lookup_from_index); + std::vector sink_pb_graph_pins = + find_routed_pb_graph_pins_atom_net( + pb, physical_source_pb_pin, source_pb_pin, atom_net_id, + device_annotation, pb_pin_mapped_nets, pb_graph_pin_lookup_from_index); - std::vector sink_lb_rr_nodes = find_lb_net_physical_sink_lb_rr_nodes(lb_rr_graph, sink_pb_graph_pins, device_annotation); + std::vector sink_lb_rr_nodes = + find_lb_net_physical_sink_lb_rr_nodes(lb_rr_graph, sink_pb_graph_pins, + device_annotation); VTR_ASSERT(sink_lb_rr_nodes.size() == sink_pb_graph_pins.size()); /* Printf for debugging only, may be enabled if verbose is enabled */ - VTR_LOGV(verbose, - "Pb route for Net %s:\n", + VTR_LOGV(verbose, "Pb route for Net %s:\n", atom_ctx.nlist.net_name(atom_net_id).c_str()); - VTR_LOGV(verbose, - "Source node:\n\t%s -> %s\n", + VTR_LOGV(verbose, "Source node:\n\t%s -> %s\n", source_pb_pin->to_string().c_str(), physical_source_pb_pin->to_string().c_str()); VTR_LOGV(verbose, "Sink nodes:\n"); for (t_pb_graph_pin* sink_pb_pin : sink_pb_graph_pins) { - VTR_LOGV(verbose, - "\t%s\n", - sink_pb_pin->to_string().c_str()); + VTR_LOGV(verbose, "\t%s\n", sink_pb_pin->to_string().c_str()); } /* Add the net */ add_lb_router_net_to_route(lb_router, lb_rr_graph, std::vector(1, source_lb_rr_node), - sink_lb_rr_nodes, - atom_ctx, atom_net_id); + sink_lb_rr_nodes, atom_ctx, atom_net_id); net_counter++; - } + } /* Free */ free_pb_graph_pin_lookup_from_index(pb_graph_pin_lookup_from_index); - VTR_LOGV(verbose, - "Added %lu nets to be routed.\n", - net_counter); + VTR_LOGV(verbose, "Added %lu nets to be routed.\n", net_counter); } /*************************************************************************************** * Repack a clustered block in the physical mode - * This function will do - * - Find the lb_rr_graph that is affiliated to the clustered block - * and initilize the logcial tile router + * This function will do + * - Find the lb_rr_graph that is affiliated to the clustered block + * and initilize the logcial tile router * - Create nets to be routed, including the source nodes and terminals - * This should consider the net remapping in the clustering_annotation + * This should consider the net remapping in the clustering_annotation * - Run the router to finish the repacking - * - Output routing results to data structure PhysicalPb and store it in clustering annotation + * - Output routing results to data structure PhysicalPb and store it in + *clustering annotation ***************************************************************************************/ -static -void repack_cluster(const AtomContext& atom_ctx, - const ClusteringContext& clustering_ctx, - const VprDeviceAnnotation& device_annotation, - VprClusteringAnnotation& clustering_annotation, - const VprBitstreamAnnotation& bitstream_annotation, - const ClusterBlockId& block_id, - const RepackOption& options) { +static void repack_cluster(const AtomContext& atom_ctx, + const ClusteringContext& clustering_ctx, + const VprDeviceAnnotation& device_annotation, + VprClusteringAnnotation& clustering_annotation, + const VprBitstreamAnnotation& bitstream_annotation, + const ClusterBlockId& block_id, + const RepackOption& options) { /* Get the pb graph that current clustered block is mapped to */ - t_logical_block_type_ptr lb_type = clustering_ctx.clb_nlist.block_type(block_id); + t_logical_block_type_ptr lb_type = + clustering_ctx.clb_nlist.block_type(block_id); t_pb_graph_node* pb_graph_head = lb_type->pb_graph_head; VTR_ASSERT(nullptr != pb_graph_head); bool verbose = options.verbose_output(); /* We should get a non-empty graph */ - const LbRRGraph& lb_rr_graph = device_annotation.physical_lb_rr_graph(pb_graph_head); + const LbRRGraph& lb_rr_graph = + device_annotation.physical_lb_rr_graph(pb_graph_head); VTR_ASSERT(!lb_rr_graph.empty()); VTR_LOG("Repack clustered block '%s'...", @@ -750,17 +825,21 @@ void repack_cluster(const AtomContext& atom_ctx, LbRouter lb_router(lb_rr_graph, lb_type); /* Add nets to be routed with source and terminals */ - add_lb_router_nets(lb_router, lb_type, lb_rr_graph, atom_ctx, device_annotation, - clustering_ctx, const_cast(clustering_annotation), - block_id, options); + add_lb_router_nets( + lb_router, lb_type, lb_rr_graph, atom_ctx, device_annotation, + clustering_ctx, + const_cast(clustering_annotation), block_id, + options); - /* Initialize the modes to expand routing trees with the physical modes in device annotation - * This is a must-do before running the routeri in the purpose of repacking!!! + /* Initialize the modes to expand routing trees with the physical modes in + * device annotation This is a must-do before running the routeri in the + * purpose of repacking!!! */ - lb_router.set_physical_pb_modes(lb_rr_graph, device_annotation); + lb_router.set_physical_pb_modes(lb_rr_graph, device_annotation); /* Run the router */ - bool route_success = lb_router.try_route(lb_rr_graph, atom_ctx.nlist, verbose); + bool route_success = + lb_router.try_route(lb_rr_graph, atom_ctx.nlist, verbose); if (false == route_success) { VTR_LOGV(verbose, "Reroute failed\n"); @@ -772,15 +851,13 @@ void repack_cluster(const AtomContext& atom_ctx, /* Annotate routing results to physical pb */ PhysicalPb phy_pb; alloc_physical_pb_from_pb_graph(phy_pb, pb_graph_head, device_annotation); - rec_update_physical_pb_from_operating_pb(phy_pb, - clustering_ctx.clb_nlist.block_pb(block_id), - clustering_ctx.clb_nlist.block_pb(block_id)->pb_route, - atom_ctx, - device_annotation, - bitstream_annotation, - verbose); + rec_update_physical_pb_from_operating_pb( + phy_pb, clustering_ctx.clb_nlist.block_pb(block_id), + clustering_ctx.clb_nlist.block_pb(block_id)->pb_route, atom_ctx, + device_annotation, bitstream_annotation, verbose); /* Save routing results */ - save_lb_router_results_to_physical_pb(phy_pb, lb_router, lb_rr_graph, atom_ctx.nlist, verbose); + save_lb_router_results_to_physical_pb(phy_pb, lb_router, lb_rr_graph, + atom_ctx.nlist, verbose); VTR_LOGV(verbose, "Saved results in physical pb\n"); /* Add the pb to clustering context */ @@ -792,21 +869,18 @@ void repack_cluster(const AtomContext& atom_ctx, /*************************************************************************************** * Repack each clustered blocks in the clustering context ***************************************************************************************/ -static -void repack_clusters(const AtomContext& atom_ctx, - const ClusteringContext& clustering_ctx, - const VprDeviceAnnotation& device_annotation, - VprClusteringAnnotation& clustering_annotation, - const VprBitstreamAnnotation& bitstream_annotation, - const RepackOption& options) { - vtr::ScopedStartFinishTimer timer("Repack clustered blocks to physical implementation of logical tile"); +static void repack_clusters(const AtomContext& atom_ctx, + const ClusteringContext& clustering_ctx, + const VprDeviceAnnotation& device_annotation, + VprClusteringAnnotation& clustering_annotation, + const VprBitstreamAnnotation& bitstream_annotation, + const RepackOption& options) { + vtr::ScopedStartFinishTimer timer( + "Repack clustered blocks to physical implementation of logical tile"); for (auto blk_id : clustering_ctx.clb_nlist.blocks()) { - repack_cluster(atom_ctx, clustering_ctx, - device_annotation, - clustering_annotation, - bitstream_annotation, - blk_id, + repack_cluster(atom_ctx, clustering_ctx, device_annotation, + clustering_annotation, bitstream_annotation, blk_id, options); } } @@ -818,13 +892,11 @@ void repack_clusters(const AtomContext& atom_ctx, * by exploiting the routability of the physical mode of a programmable block * This is why this annotation is required ***************************************************************************************/ -static -void identify_physical_pb_wire_lut_created_by_repack(VprClusteringAnnotation& cluster_annotation, - const AtomContext& atom_ctx, - const ClusteringContext& cluster_ctx, - const VprDeviceAnnotation& device_annotation, - const CircuitLibrary& circuit_lib, - const bool& verbose) { +static void identify_physical_pb_wire_lut_created_by_repack( + VprClusteringAnnotation& cluster_annotation, const AtomContext& atom_ctx, + const ClusteringContext& cluster_ctx, + const VprDeviceAnnotation& device_annotation, + const CircuitLibrary& circuit_lib, const bool& verbose) { vtr::ScopedStartFinishTimer timer("Identify wire LUTs created by repacking"); int wire_lut_counter = 0; @@ -832,30 +904,31 @@ void identify_physical_pb_wire_lut_created_by_repack(VprClusteringAnnotation& cl PhysicalPb& physical_pb = cluster_annotation.mutable_physical_pb(blk_id); /* Find the LUT physical pb id */ for (const PhysicalPbId& primitive_pb : physical_pb.primitive_pbs()) { - CircuitModelId circuit_model = device_annotation.pb_type_circuit_model(physical_pb.pb_graph_node(primitive_pb)->pb_type); + CircuitModelId circuit_model = device_annotation.pb_type_circuit_model( + physical_pb.pb_graph_node(primitive_pb)->pb_type); VTR_ASSERT(true == circuit_lib.valid_model_id(circuit_model)); if (CIRCUIT_MODEL_LUT != circuit_lib.model_type(circuit_model)) { continue; } - - /* Reach here, we have a LUT to deal with. Find the wire LUT that mapped to the LUT */ - wire_lut_counter += identify_one_physical_pb_wire_lut_created_by_repack(physical_pb, primitive_pb, device_annotation, atom_ctx, circuit_lib, verbose); + + /* Reach here, we have a LUT to deal with. Find the wire LUT that mapped + * to the LUT */ + wire_lut_counter += identify_one_physical_pb_wire_lut_created_by_repack( + physical_pb, primitive_pb, device_annotation, atom_ctx, circuit_lib, + verbose); } } - VTR_LOG("Identified %d wire LUTs created by repacker\n", - wire_lut_counter); + VTR_LOG("Identified %d wire LUTs created by repacker\n", wire_lut_counter); } - - /*************************************************************************************** - * Top-level function to pack physical pb_graph + * Top-level function to pack physical pb_graph * This function will do : - * - create physical lb_rr_graph for each pb_graph considering physical modes only - * the lb_rr_graph will be added to device annotation - * - annotate nets to be routed for each clustered block from operating modes of pb_graph - * to physical modes of pb_graph + * - create physical lb_rr_graph for each pb_graph considering physical modes + *only the lb_rr_graph will be added to device annotation + * - annotate nets to be routed for each clustered block from operating modes + *of pb_graph to physical modes of pb_graph * - rerun the routing for each clustered block * - store the packing results to clustering annotation ***************************************************************************************/ @@ -867,28 +940,22 @@ void pack_physical_pbs(const DeviceContext& device_ctx, const VprBitstreamAnnotation& bitstream_annotation, const CircuitLibrary& circuit_lib, const RepackOption& options) { - /* build the routing resource graph for each logical tile */ - build_physical_lb_rr_graphs(device_ctx, - device_annotation, + build_physical_lb_rr_graphs(device_ctx, device_annotation, options.verbose_output()); - /* Call the LbRouter to re-pack each clustered block to physical implementation */ - repack_clusters(atom_ctx, clustering_ctx, + /* Call the LbRouter to re-pack each clustered block to physical + * implementation */ + repack_clusters(atom_ctx, clustering_ctx, const_cast(device_annotation), - clustering_annotation, - bitstream_annotation, - options); + clustering_annotation, bitstream_annotation, options); /* Annnotate wire LUTs that are ONLY created by repacker!!! * This is a MUST RUN! */ - identify_physical_pb_wire_lut_created_by_repack(clustering_annotation, - atom_ctx, - clustering_ctx, - device_annotation, - circuit_lib, - options.verbose_output()); + identify_physical_pb_wire_lut_created_by_repack( + clustering_annotation, atom_ctx, clustering_ctx, device_annotation, + circuit_lib, options.verbose_output()); } } /* end namespace openfpga */ diff --git a/openfpga/src/repack/repack.h b/openfpga/src/repack/repack.h index 5cb1d8320..eab98a221 100644 --- a/openfpga/src/repack/repack.h +++ b/openfpga/src/repack/repack.h @@ -4,13 +4,13 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" -#include "vpr_device_annotation.h" -#include "vpr_clustering_annotation.h" -#include "vpr_routing_annotation.h" -#include "vpr_bitstream_annotation.h" #include "circuit_library.h" #include "repack_option.h" +#include "vpr_bitstream_annotation.h" +#include "vpr_clustering_annotation.h" +#include "vpr_context.h" +#include "vpr_device_annotation.h" +#include "vpr_routing_annotation.h" /******************************************************************** * Function declaration diff --git a/openfpga/src/repack/repack_option.cpp b/openfpga/src/repack/repack_option.cpp index 13b3b54ce..b3a06f60f 100644 --- a/openfpga/src/repack/repack_option.cpp +++ b/openfpga/src/repack/repack_option.cpp @@ -1,15 +1,16 @@ /****************************************************************************** * Memember functions for data structure RepackOption ******************************************************************************/ -#include +#include "repack_option.h" + #include +#include + +#include "openfpga_port_parser.h" +#include "openfpga_tokenizer.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "repack_option.h" -#include "openfpga_tokenizer.h" -#include "openfpga_port_parser.h" - /* begin namespace openfpga */ namespace openfpga { @@ -22,13 +23,14 @@ RepackOption::RepackOption() { } /************************************************** - * Public Accessors + * Public Accessors *************************************************/ RepackDesignConstraints RepackOption::design_constraints() const { return design_constraints_; } -bool RepackOption::is_pin_ignore_global_nets(const std::string& pb_type_name, const BasicPort& pin) const { +bool RepackOption::is_pin_ignore_global_nets(const std::string& pb_type_name, + const BasicPort& pin) const { auto result = ignore_global_nets_on_pins_.find(pb_type_name); if (result == ignore_global_nets_on_pins_.end()) { /* Not found, return false */ @@ -44,14 +46,13 @@ bool RepackOption::is_pin_ignore_global_nets(const std::string& pb_type_name, co return false; } -bool RepackOption::verbose_output() const { - return verbose_output_; -} +bool RepackOption::verbose_output() const { return verbose_output_; } /****************************************************************************** * Private Mutators ******************************************************************************/ -void RepackOption::set_design_constraints(const RepackDesignConstraints& design_constraints) { +void RepackOption::set_design_constraints( + const RepackDesignConstraints& design_constraints) { design_constraints_ = design_constraints; } @@ -68,29 +69,33 @@ void RepackOption::set_ignore_global_nets_on_pins(const std::string& content) { std::vector pin_info = pin_tokenizer.split('.'); /* Expect two contents, otherwise error out */ if (pin_info.size() != 2) { - std::string err_msg = std::string("Invalid content '") + token + std::string("' to skip, expect .\n"); + std::string err_msg = + std::string("Invalid content '") + token + + std::string("' to skip, expect .\n"); VTR_LOG_ERROR(err_msg.c_str()); num_parse_errors_++; continue; } - std::string pb_type_name = pin_info[0]; + std::string pb_type_name = pin_info[0]; PortParser port_parser(pin_info[1]); BasicPort curr_port = port_parser.port(); if (!curr_port.is_valid()) { - std::string err_msg = std::string("Invalid pin definition '") + token + std::string("', expect .[int:int]\n"); + std::string err_msg = + std::string("Invalid pin definition '") + token + + std::string("', expect .[int:int]\n"); VTR_LOG_ERROR(err_msg.c_str()); num_parse_errors_++; continue; } - + /* Check if the existing port already in the ignore list or not */ auto result = ignore_global_nets_on_pins_.find(pb_type_name); if (result == ignore_global_nets_on_pins_.end()) { /* Not found, push the port */ ignore_global_nets_on_pins_[pb_type_name].push_back(curr_port); } else { - /* Already a list of ports. Check one by one. - * - It already contained, do nothing but throw a warning. + /* Already a list of ports. Check one by one. + * - It already contained, do nothing but throw a warning. * - If we can merge, merge it. * - Otherwise, create it */ bool included_by_existing_port = false; @@ -101,7 +106,9 @@ void RepackOption::set_ignore_global_nets_on_pins(const std::string& content) { included_by_existing_port = true; break; } else { - std::string warn_msg = std::string("Pin definition '") + token + std::string("' is already included by other pin\n"); + std::string warn_msg = + std::string("Pin definition '") + token + + std::string("' is already included by other pin\n"); VTR_LOG_WARN(warn_msg.c_str()); } } diff --git a/openfpga/src/repack/repack_option.h b/openfpga/src/repack/repack_option.h index a626dc714..24f46633d 100644 --- a/openfpga/src/repack/repack_option.h +++ b/openfpga/src/repack/repack_option.h @@ -6,6 +6,7 @@ *******************************************************************/ #include #include + #include "repack_design_constraints.h" /* Begin namespace openfpga */ @@ -15,36 +16,42 @@ namespace openfpga { * Options for RRGSB writer *******************************************************************/ class RepackOption { - public: /* Public constructor */ - /* Set default options */ - RepackOption(); - public: /* Public accessors */ - RepackDesignConstraints design_constraints() const; - /* Identify if a pin should ignore all the global nets */ - bool is_pin_ignore_global_nets(const std::string& pb_type_name, const BasicPort& pin) const; - bool verbose_output() const; - public: /* Public mutators */ - void set_design_constraints(const RepackDesignConstraints& design_constraints); - void set_ignore_global_nets_on_pins(const std::string& content); - void set_verbose_output(const bool& enabled); - public: /* Public validators */ - /* Check if the following internal data is valid or not: - * - no parsing errors - */ - bool valid() const; - private: /* Internal Data */ - RepackDesignConstraints design_constraints_; - /* The pin information on which global nets should be mapped to: [pb_type_name][0..num_ports] - * For example: - * - clb.I[0:1], clb.I[5:6] -> ["clb"][BasicPort(I, 0, 1), BasicPort(I, 5, 6)] - * - clb.I[0:1], clb.I[2:6] -> ["clb"][BasicPort(I, 0, 6)] - */ - std::map> ignore_global_nets_on_pins_; + public: /* Public constructor */ + /* Set default options */ + RepackOption(); - bool verbose_output_; + public: /* Public accessors */ + RepackDesignConstraints design_constraints() const; + /* Identify if a pin should ignore all the global nets */ + bool is_pin_ignore_global_nets(const std::string& pb_type_name, + const BasicPort& pin) const; + bool verbose_output() const; - /* A flag to indicate if the data parse is invalid or not */ - int num_parse_errors_; + public: /* Public mutators */ + void set_design_constraints( + const RepackDesignConstraints& design_constraints); + void set_ignore_global_nets_on_pins(const std::string& content); + void set_verbose_output(const bool& enabled); + + public: /* Public validators */ + /* Check if the following internal data is valid or not: + * - no parsing errors + */ + bool valid() const; + + private: /* Internal Data */ + RepackDesignConstraints design_constraints_; + /* The pin information on which global nets should be mapped to: + * [pb_type_name][0..num_ports] For example: + * - clb.I[0:1], clb.I[5:6] -> ["clb"][BasicPort(I, 0, 1), BasicPort(I, 5, 6)] + * - clb.I[0:1], clb.I[2:6] -> ["clb"][BasicPort(I, 0, 6)] + */ + std::map> ignore_global_nets_on_pins_; + + bool verbose_output_; + + /* A flag to indicate if the data parse is invalid or not */ + int num_parse_errors_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/tile_direct/build_tile_direct.cpp b/openfpga/src/tile_direct/build_tile_direct.cpp index 0ae3ae432..7ea380d8c 100644 --- a/openfpga/src/tile_direct/build_tile_direct.cpp +++ b/openfpga/src/tile_direct/build_tile_direct.cpp @@ -1,57 +1,58 @@ /*************************************************************************************** * This file includes functions that build the point-to-point direct connections - * between tiles (programmable blocks) + * between tiles (programmable blocks) ***************************************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_tokenizer.h" #include "openfpga_port.h" #include "openfpga_port_parser.h" +#include "openfpga_tokenizer.h" /* Headers from vpr library */ -#include "vpr_utils.h" - #include "build_tile_direct.h" +#include "vpr_utils.h" /* begin namespace openfpga */ namespace openfpga { /*************************************************************************************** - * Parse the from tile name from the direct definition + * Parse the from tile name from the direct definition * The definition string should be in the following format: - * .[:] + * .[:] ***************************************************************************************/ -static -std::string parse_direct_tile_name(const std::string& direct_tile_inf) { +static std::string parse_direct_tile_name(const std::string& direct_tile_inf) { StringToken tokenizer(direct_tile_inf); std::vector tokens = tokenizer.split('.'); /* We should have only 2 elements and the first is tile name */ if (2 != tokens.size()) { - VTR_LOG_ERROR("Invalid definition on direct tile '%s'!\n\tExpect .[:].\n", - direct_tile_inf.c_str()); + VTR_LOG_ERROR( + "Invalid definition on direct tile '%s'!\n\tExpect " + ".[:].\n", + direct_tile_inf.c_str()); } return tokens[0]; } /*************************************************************************************** - * Parse the pin name and port MSB/LSB from the direct definition + * Parse the pin name and port MSB/LSB from the direct definition * The definition string should be in the following format: - * .[:] + * .[:] ***************************************************************************************/ -static -std::string parse_direct_port(const std::string& direct_tile_inf) { +static std::string parse_direct_port(const std::string& direct_tile_inf) { StringToken tokenizer(direct_tile_inf); std::vector tokens = tokenizer.split('.'); /* We should have only 2 elements and the first is tile name */ if (2 != tokens.size()) { - VTR_LOG_ERROR("Invalid definition on direct tile '%s'!\n\tExpect .[:].\n", - direct_tile_inf.c_str()); + VTR_LOG_ERROR( + "Invalid definition on direct tile '%s'!\n\tExpect " + ".[:].\n", + direct_tile_inf.c_str()); } return tokens[1]; @@ -59,34 +60,32 @@ std::string parse_direct_port(const std::string& direct_tile_inf) { /*************************************************************************************** * Check if a pin is located on a given side of physical tile - * If the given side is NUM_SIDES, we will search all the sides + * If the given side is NUM_SIDES, we will search all the sides ***************************************************************************************/ -static -bool is_pin_locate_at_physical_tile_side(t_physical_tile_type_ptr physical_tile, - const size_t& pin_width_offset, - const size_t& pin_height_offset, - const size_t& pin_id, - const e_side& pin_side) { +static bool is_pin_locate_at_physical_tile_side( + t_physical_tile_type_ptr physical_tile, const size_t& pin_width_offset, + const size_t& pin_height_offset, const size_t& pin_id, + const e_side& pin_side) { if (NUM_SIDES == pin_side) { for (size_t side = 0; side < NUM_SIDES; ++side) { - if (true == physical_tile->pinloc[pin_width_offset][pin_height_offset][side][pin_id]) { + if (true == physical_tile->pinloc[pin_width_offset][pin_height_offset] + [side][pin_id]) { return true; } } } - - return physical_tile->pinloc[pin_width_offset][pin_height_offset][size_t(pin_side)][pin_id]; + + return physical_tile + ->pinloc[pin_width_offset][pin_height_offset][size_t(pin_side)][pin_id]; } /*************************************************************************************** - * Find the pin ids of a physical tile based on the given port name, LSB and MSB + * Find the pin ids of a physical tile based on the given port name, LSB and MSB ***************************************************************************************/ -static -std::vector find_physical_tile_pin_id(t_physical_tile_type_ptr physical_tile, - const size_t& pin_width_offset, - const size_t& pin_height_offset, - const BasicPort& tile_port, - const e_side& pin_side) { +static std::vector find_physical_tile_pin_id( + t_physical_tile_type_ptr physical_tile, const size_t& pin_width_offset, + const size_t& pin_height_offset, const BasicPort& tile_port, + const e_side& pin_side) { std::vector pin_ids; /* Walk through the port of the tile */ @@ -97,15 +96,17 @@ std::vector find_physical_tile_pin_id(t_physical_tile_type_ptr physical_ } /* If the wanted port is invalid, it assumes that we want the full port */ if (false == tile_port.is_valid()) { - for (int subtile_index = sub_tile.capacity.low; subtile_index <= sub_tile.capacity.high; subtile_index++) { + for (int subtile_index = sub_tile.capacity.low; + subtile_index <= sub_tile.capacity.high; subtile_index++) { for (int ipin = 0; ipin < physical_tile_port.num_pins; ++ipin) { - int pin_id = (subtile_index - sub_tile.capacity.low) * sub_tile.num_phy_pins / sub_tile.capacity.total() + physical_tile_port.absolute_first_pin_index + ipin; + int pin_id = (subtile_index - sub_tile.capacity.low) * + sub_tile.num_phy_pins / sub_tile.capacity.total() + + physical_tile_port.absolute_first_pin_index + ipin; VTR_ASSERT(pin_id < physical_tile->num_pins); /* Check if the pin is located on the wanted side */ - if (true == is_pin_locate_at_physical_tile_side(physical_tile, - pin_width_offset, - pin_height_offset, - pin_id, pin_side)) { + if (true == is_pin_locate_at_physical_tile_side( + physical_tile, pin_width_offset, pin_height_offset, + pin_id, pin_side)) { pin_ids.push_back(pin_id); } } @@ -114,24 +115,25 @@ std::vector find_physical_tile_pin_id(t_physical_tile_type_ptr physical_ } /* Find the LSB and MSB of the pin */ VTR_ASSERT_SAFE(true == tile_port.is_valid()); - BasicPort ref_port(physical_tile_port.name, physical_tile_port.num_pins); + BasicPort ref_port(physical_tile_port.name, physical_tile_port.num_pins); if (false == ref_port.contained(tile_port)) { - VTR_LOG_ERROR("Defined direct port '%s[%lu:%lu]' is out of range for physical port '%s[%lu:%lu]'!\n", - tile_port.get_name().c_str(), - tile_port.get_lsb(), tile_port.get_msb(), - ref_port.get_name().c_str(), - ref_port.get_lsb(), ref_port.get_msb()); + VTR_LOG_ERROR( + "Defined direct port '%s[%lu:%lu]' is out of range for physical port " + "'%s[%lu:%lu]'!\n", + tile_port.get_name().c_str(), tile_port.get_lsb(), + tile_port.get_msb(), ref_port.get_name().c_str(), ref_port.get_lsb(), + ref_port.get_msb()); exit(1); } for (const size_t& ipin : tile_port.pins()) { - int pin_id = physical_tile_port.absolute_first_pin_index + ipin * sub_tile.num_phy_pins / sub_tile.capacity.total() + ipin; + int pin_id = physical_tile_port.absolute_first_pin_index + + ipin * sub_tile.num_phy_pins / sub_tile.capacity.total() + + ipin; VTR_ASSERT(pin_id < physical_tile->num_pins); /* Check if the pin is located on the wanted side */ - if (true == is_pin_locate_at_physical_tile_side(physical_tile, - pin_width_offset, - pin_height_offset, - pin_id, pin_side)) { - + if (true == is_pin_locate_at_physical_tile_side( + physical_tile, pin_width_offset, pin_height_offset, + pin_id, pin_side)) { pin_ids.push_back(pin_id); } } @@ -142,79 +144,78 @@ std::vector find_physical_tile_pin_id(t_physical_tile_type_ptr physical_ } /******************************************************************** - * Check if the grid coorindate given is in the device grid range + * Check if the grid coorindate given is in the device grid range *******************************************************************/ -static -bool is_grid_coordinate_exist_in_device(const DeviceGrid& device_grid, - const vtr::Point& grid_coordinate) { - return (grid_coordinate < vtr::Point(device_grid.width(), device_grid.height())); +static bool is_grid_coordinate_exist_in_device( + const DeviceGrid& device_grid, const vtr::Point& grid_coordinate) { + return (grid_coordinate < + vtr::Point(device_grid.width(), device_grid.height())); } /******************************************************************** - * Find the coordinate of a grid in a specific column + * Find the coordinate of a grid in a specific column * with a given type * This function will return the coordinate of the grid that satifies * the type requirement *******************************************************************/ -static -vtr::Point find_grid_coordinate_given_type(const DeviceGrid& grids, - const std::vector>& candidate_coords, - const std::string& wanted_grid_type_name) { +static vtr::Point find_grid_coordinate_given_type( + const DeviceGrid& grids, + const std::vector>& candidate_coords, + const std::string& wanted_grid_type_name) { for (vtr::Point coord : candidate_coords) { /* If the next column is not longer in device range, we can return */ if (false == is_grid_coordinate_exist_in_device(grids, coord)) { continue; } - if (wanted_grid_type_name == std::string(grids[coord.x()][coord.y()].type->name)) { + if (wanted_grid_type_name == + std::string(grids[coord.x()][coord.y()].type->name)) { return coord; } } /* Return an valid coordinate */ - return vtr::Point(grids.width(), grids.height()); + return vtr::Point(grids.width(), grids.height()); } /******************************************************************** * Find the coordinate of the destination clb/heterogeneous block * considering intra column/row direct connections in core grids *******************************************************************/ -static -vtr::Point find_inter_direct_destination_coordinate(const DeviceGrid& grids, - const vtr::Point& src_coord, - const std::string des_tile_type_name, - const ArchDirect& arch_direct, - const ArchDirectId& arch_direct_id) { +static vtr::Point find_inter_direct_destination_coordinate( + const DeviceGrid& grids, const vtr::Point& src_coord, + const std::string des_tile_type_name, const ArchDirect& arch_direct, + const ArchDirectId& arch_direct_id) { vtr::Point des_coord(grids.width(), grids.height()); std::vector first_search_space; std::vector second_search_space; - /* Cross column connection from Bottom to Top on Right + /* Cross column connection from Bottom to Top on Right * The next column may NOT have the grid type we want! - * Think about heterogeneous architecture! - * Our search space will start from the next column - * and ends at the RIGHT side of fabric + * Think about heterogeneous architecture! + * Our search space will start from the next column + * and ends at the RIGHT side of fabric */ if (INTER_COLUMN == arch_direct.type(arch_direct_id)) { if (POSITIVE_DIR == arch_direct.x_dir(arch_direct_id)) { - /* Our first search space will be in x-direction: - * - * x ... nx - * +-----+ - * |Grid | -----> - * +-----+ - */ + /* Our first search space will be in x-direction: + * + * x ... nx + * +-----+ + * |Grid | -----> + * +-----+ + */ for (size_t ix = src_coord.x() + 1; ix < grids.width() - 1; ++ix) { first_search_space.push_back(ix); } - } else { + } else { VTR_ASSERT(NEGATIVE_DIR == arch_direct.x_dir(arch_direct_id)); - /* Our first search space will be in x-direction: - * - * 1 ... x - * +-----+ - * < -------|Grid | - * +-----+ - */ + /* Our first search space will be in x-direction: + * + * 1 ... x + * +-----+ + * < -------|Grid | + * +-----+ + */ for (size_t ix = src_coord.x() - 1; ix >= 1; --ix) { first_search_space.push_back(ix); } @@ -222,7 +223,7 @@ vtr::Point find_inter_direct_destination_coordinate(const DeviceGrid& gr /* Our second search space will be in y-direction: * - * +------+ + * +------+ * | Grid | ny * +------+ * ^ . @@ -232,13 +233,13 @@ vtr::Point find_inter_direct_destination_coordinate(const DeviceGrid& gr * | Grid | 1 * +------+ */ - for (size_t iy = 1 ; iy < grids.height() - 1; ++iy) { + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { second_search_space.push_back(iy); } /* For negative direction, our second search space will be in y-direction: * - * +------+ + * +------+ * | Grid | ny * +------+ * | . @@ -253,36 +254,35 @@ vtr::Point find_inter_direct_destination_coordinate(const DeviceGrid& gr } } - - /* Cross row connection from Bottom to Top on Right + /* Cross row connection from Bottom to Top on Right * The next column may NOT have the grid type we want! - * Think about heterogeneous architecture! - * Our search space will start from the next column - * and ends at the RIGHT side of fabric + * Think about heterogeneous architecture! + * Our search space will start from the next column + * and ends at the RIGHT side of fabric */ if (INTER_ROW == arch_direct.type(arch_direct_id)) { if (POSITIVE_DIR == arch_direct.y_dir(arch_direct_id)) { - /* Our first search space will be in y-direction: - * - * +------+ - * | Grid | ny - * +------+ - * ^ . - * | . - * | . - * +------+ - * | Grid | y - * +------+ - */ + /* Our first search space will be in y-direction: + * + * +------+ + * | Grid | ny + * +------+ + * ^ . + * | . + * | . + * +------+ + * | Grid | y + * +------+ + */ for (size_t iy = src_coord.y() + 1; iy < grids.height() - 1; ++iy) { first_search_space.push_back(iy); } - } else { + } else { VTR_ASSERT(NEGATIVE_DIR == arch_direct.y_dir(arch_direct_id)); /* For negative y-direction, * Our first search space will be in y-direction: * - * +------+ + * +------+ * | Grid | ny * +------+ * | . @@ -304,7 +304,7 @@ vtr::Point find_inter_direct_destination_coordinate(const DeviceGrid& gr * | Grid |<------| Grid | * +------+ +------+ */ - for (size_t ix = 1 ; ix < grids.width() - 1; ++ix) { + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { second_search_space.push_back(ix); } @@ -332,7 +332,8 @@ vtr::Point find_inter_direct_destination_coordinate(const DeviceGrid& gr next_col_row_coords.push_back(vtr::Point(iy, ix)); } } - vtr::Point des_coord_cand = find_grid_coordinate_given_type(grids, next_col_row_coords, des_tile_type_name); + vtr::Point des_coord_cand = find_grid_coordinate_given_type( + grids, next_col_row_coords, des_tile_type_name); /* For a valid coordinate, we can return */ if (true == is_grid_coordinate_exist_in_device(grids, des_coord_cand)) { return des_coord_cand; @@ -344,23 +345,20 @@ vtr::Point find_inter_direct_destination_coordinate(const DeviceGrid& gr /*************************************************************************************** * Report error for port matching failure ***************************************************************************************/ -static -void report_direct_from_port_and_to_port_mismatch(const t_direct_inf& vpr_direct, - const BasicPort& from_tile_port, - const BasicPort& to_tile_port) { - VTR_LOG_ERROR("From_port '%s[%lu:%lu] of direct '%s' does not match to_port '%s[%lu:%lu]'!\n", - from_tile_port.get_name().c_str(), - from_tile_port.get_lsb(), - from_tile_port.get_msb(), - vpr_direct.name, - to_tile_port.get_name().c_str(), - to_tile_port.get_lsb(), - to_tile_port.get_msb()); +static void report_direct_from_port_and_to_port_mismatch( + const t_direct_inf& vpr_direct, const BasicPort& from_tile_port, + const BasicPort& to_tile_port) { + VTR_LOG_ERROR( + "From_port '%s[%lu:%lu] of direct '%s' does not match to_port " + "'%s[%lu:%lu]'!\n", + from_tile_port.get_name().c_str(), from_tile_port.get_lsb(), + from_tile_port.get_msb(), vpr_direct.name, to_tile_port.get_name().c_str(), + to_tile_port.get_lsb(), to_tile_port.get_msb()); } /*************************************************************************************** - * Build the point-to-point direct connections based on - * - original VPR arch definition + * Build the point-to-point direct connections based on + * - original VPR arch definition * This is limited to the inner-column and inner-row connections * Note that the direct connections are not limited to CLBs only. * It can be more generic and thus cover all the grid types, @@ -373,7 +371,7 @@ void report_direct_from_port_and_to_port_mismatch(const t_direct_inf& vpr_direct * | Tile |----->| Tile | * | | | | * +------+ +------+ - * | direction connection + * | direction connection * v * +------+ * | | @@ -382,20 +380,22 @@ void report_direct_from_port_and_to_port_mismatch(const t_direct_inf& vpr_direct * +------+ * ***************************************************************************************/ -static -void build_inner_column_row_tile_direct(TileDirect& tile_direct, - const t_direct_inf& vpr_direct, - const DeviceContext& device_ctx, - const ArchDirectId& arch_direct_id, - const bool& verbose) { +static void build_inner_column_row_tile_direct( + TileDirect& tile_direct, const t_direct_inf& vpr_direct, + const DeviceContext& device_ctx, const ArchDirectId& arch_direct_id, + const bool& verbose) { /* Get the source tile and pin information */ - std::string from_tile_name = parse_direct_tile_name(std::string(vpr_direct.from_pin)); - PortParser from_tile_port_parser(parse_direct_port(std::string(vpr_direct.from_pin))); + std::string from_tile_name = + parse_direct_tile_name(std::string(vpr_direct.from_pin)); + PortParser from_tile_port_parser( + parse_direct_port(std::string(vpr_direct.from_pin))); const BasicPort& from_tile_port = from_tile_port_parser.port(); /* Get the sink tile and pin information */ - std::string to_tile_name = parse_direct_tile_name(std::string(vpr_direct.to_pin)); - PortParser to_tile_port_parser(parse_direct_port(std::string(vpr_direct.to_pin))); + std::string to_tile_name = + parse_direct_tile_name(std::string(vpr_direct.to_pin)); + PortParser to_tile_port_parser( + parse_direct_port(std::string(vpr_direct.to_pin))); const BasicPort& to_tile_port = to_tile_port_parser.port(); /* Walk through the device fabric and find the grid that fit the source */ @@ -416,27 +416,29 @@ void build_inner_column_row_tile_direct(TileDirect& tile_direct, * This should be reported to VPR!!! */ for (const e_side& from_side : {TOP, RIGHT, BOTTOM, LEFT}) { - /* Try to find the pin in this tile */ - std::vector from_pins = find_physical_tile_pin_id(device_ctx.grid[x][y].type, - device_ctx.grid[x][y].width_offset, - device_ctx.grid[x][y].height_offset, - from_tile_port, - from_side); + std::vector from_pins = find_physical_tile_pin_id( + device_ctx.grid[x][y].type, device_ctx.grid[x][y].width_offset, + device_ctx.grid[x][y].height_offset, from_tile_port, from_side); /* If nothing found, we can continue */ if (0 == from_pins.size()) { continue; } - - /* We should try to the sink grid for inner-column/row direct connections */ + + /* We should try to the sink grid for inner-column/row direct + * connections */ vtr::Point from_grid_coord(x, y); - vtr::Point to_grid_coord(x + vpr_direct.x_offset, y + vpr_direct.y_offset); - if (false == is_grid_coordinate_exist_in_device(device_ctx.grid, to_grid_coord)) { + vtr::Point to_grid_coord(x + vpr_direct.x_offset, + y + vpr_direct.y_offset); + if (false == is_grid_coordinate_exist_in_device(device_ctx.grid, + to_grid_coord)) { continue; } /* Bypass the grid that does not fit the from_tile name */ - if (to_tile_name != std::string(device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].type->name)) { + if (to_tile_name != + std::string(device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()] + .type->name)) { continue; } @@ -445,13 +447,12 @@ void build_inner_column_row_tile_direct(TileDirect& tile_direct, * This should be reported to VPR!!! */ for (const e_side& to_side : {TOP, RIGHT, BOTTOM, LEFT}) { - /* Try to find the pin in this tile */ - std::vector to_pins = find_physical_tile_pin_id(device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].type, - device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].width_offset, - device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].height_offset, - to_tile_port, - to_side); + std::vector to_pins = find_physical_tile_pin_id( + device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].type, + device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].width_offset, + device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].height_offset, + to_tile_port, to_side); /* If nothing found, we can continue */ if (0 == to_pins.size()) { continue; @@ -459,28 +460,26 @@ void build_inner_column_row_tile_direct(TileDirect& tile_direct, /* If from port and to port do not match in sizes, error out */ if (from_pins.size() != to_pins.size()) { - report_direct_from_port_and_to_port_mismatch(vpr_direct, from_tile_port, to_tile_port); + report_direct_from_port_and_to_port_mismatch( + vpr_direct, from_tile_port, to_tile_port); exit(1); } /* Now add the tile direct */ for (size_t ipin = 0; ipin < from_pins.size(); ++ipin) { VTR_LOGV(verbose, - "Built a inner-column/row tile-to-tile direct from %s[%lu][%lu].%s[%lu] at side '%s' to %s[%lu][%lu].%s[%lu] at side '%s'\n", + "Built a inner-column/row tile-to-tile direct from " + "%s[%lu][%lu].%s[%lu] at side '%s' to " + "%s[%lu][%lu].%s[%lu] at side '%s'\n", from_tile_name.c_str(), x, y, from_tile_port.get_name().c_str(), from_pins[ipin], - SIDE_STRING[from_side], - to_tile_name.c_str(), + SIDE_STRING[from_side], to_tile_name.c_str(), to_grid_coord.x(), to_grid_coord.y(), to_tile_port.get_name().c_str(), to_pins[ipin], - SIDE_STRING[to_side] - ); - TileDirectId tile_direct_id = tile_direct.add_direct(from_grid_coord, - from_side, - from_pins[ipin], - to_grid_coord, - to_side, - to_pins[ipin]); + SIDE_STRING[to_side]); + TileDirectId tile_direct_id = tile_direct.add_direct( + from_grid_coord, from_side, from_pins[ipin], to_grid_coord, + to_side, to_pins[ipin]); tile_direct.set_arch_direct_id(tile_direct_id, arch_direct_id); } } @@ -490,8 +489,8 @@ void build_inner_column_row_tile_direct(TileDirect& tile_direct, } /******************************************************************** - * Build the point-to-point direct connections based on - * - OpenFPGA arch definition + * Build the point-to-point direct connections based on + * - OpenFPGA arch definition * This is limited to the inter-column and inter-row connections * * Note that the direct connections are not limited to CLBs only. @@ -500,10 +499,10 @@ void build_inner_column_row_tile_direct(TileDirect& tile_direct, * * This function supports the following type of direct connection: * - * 1. Direct connections across columns and rows + * 1. Direct connections across columns and rows * +------+ * | | - * | v + * | v * +------+ | +------+ * | | | | | * | Grid | | | Grid | @@ -522,31 +521,32 @@ void build_inner_column_row_tile_direct(TileDirect& tile_direct, * I/Os or any blocks on the border of fabric are NOT supported! * *******************************************************************/ -static -void build_inter_column_row_tile_direct(TileDirect& tile_direct, - const t_direct_inf& vpr_direct, - const DeviceContext& device_ctx, - const ArchDirect& arch_direct, - const ArchDirectId& arch_direct_id, - const bool& verbose) { - +static void build_inter_column_row_tile_direct( + TileDirect& tile_direct, const t_direct_inf& vpr_direct, + const DeviceContext& device_ctx, const ArchDirect& arch_direct, + const ArchDirectId& arch_direct_id, const bool& verbose) { /* Get the source tile and pin information */ - std::string from_tile_name = parse_direct_tile_name(std::string(vpr_direct.from_pin)); - PortParser from_tile_port_parser(parse_direct_port(std::string(vpr_direct.from_pin))); + std::string from_tile_name = + parse_direct_tile_name(std::string(vpr_direct.from_pin)); + PortParser from_tile_port_parser( + parse_direct_port(std::string(vpr_direct.from_pin))); const BasicPort& from_tile_port = from_tile_port_parser.port(); /* Get the sink tile and pin information */ - std::string to_tile_name = parse_direct_tile_name(std::string(vpr_direct.to_pin)); - PortParser to_tile_port_parser(parse_direct_port(std::string(vpr_direct.to_pin))); + std::string to_tile_name = + parse_direct_tile_name(std::string(vpr_direct.to_pin)); + PortParser to_tile_port_parser( + parse_direct_port(std::string(vpr_direct.to_pin))); const BasicPort& to_tile_port = to_tile_port_parser.port(); - /* Go through the direct connection list, see if we need intra-column/row connection here */ - if ( (INTER_COLUMN != arch_direct.type(arch_direct_id)) - && (INTER_ROW != arch_direct.type(arch_direct_id))) { + /* Go through the direct connection list, see if we need intra-column/row + * connection here */ + if ((INTER_COLUMN != arch_direct.type(arch_direct_id)) && + (INTER_ROW != arch_direct.type(arch_direct_id))) { return; } - /* For cross-column connection, we will search the first valid grid in each column - * from y = 1 to y = ny + /* For cross-column connection, we will search the first valid grid in each + * column from y = 1 to y = ny * * +------+ * | Grid | y=ny @@ -558,7 +558,7 @@ void build_inter_column_row_tile_direct(TileDirect& tile_direct, * +------+ * | Grid | y=1 * +------+ - * + * */ if (INTER_COLUMN == arch_direct.type(arch_direct_id)) { for (size_t ix = 1; ix < device_ctx.grid.width() - 1; ++ix) { @@ -569,13 +569,17 @@ void build_inter_column_row_tile_direct(TileDirect& tile_direct, } /* For positive y- direction, we should start from y = 1 */ if (NEGATIVE_DIR == arch_direct.y_dir(arch_direct_id)) { - std::reverse(next_col_src_grid_coords.begin(), next_col_src_grid_coords.end()); + std::reverse(next_col_src_grid_coords.begin(), + next_col_src_grid_coords.end()); } /* Bypass the grid that does not fit the from_tile name */ - vtr::Point from_grid_coord = find_grid_coordinate_given_type(device_ctx.grid, next_col_src_grid_coords, from_tile_name); - /* Skip if we do not have a valid coordinate for source CLB/heterogeneous block */ - if (false == is_grid_coordinate_exist_in_device(device_ctx.grid, from_grid_coord)) { + vtr::Point from_grid_coord = find_grid_coordinate_given_type( + device_ctx.grid, next_col_src_grid_coords, from_tile_name); + /* Skip if we do not have a valid coordinate for source CLB/heterogeneous + * block */ + if (false == is_grid_coordinate_exist_in_device(device_ctx.grid, + from_grid_coord)) { continue; } @@ -584,23 +588,29 @@ void build_inter_column_row_tile_direct(TileDirect& tile_direct, * This should be reported to VPR!!! */ for (const e_side& from_side : {TOP, RIGHT, BOTTOM, LEFT}) { - /* Try to find the pin in this tile */ - std::vector from_pins = find_physical_tile_pin_id(device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].type, - device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].width_offset, - device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].height_offset, - from_tile_port, - from_side); + std::vector from_pins = find_physical_tile_pin_id( + device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].type, + device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()] + .width_offset, + device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()] + .height_offset, + from_tile_port, from_side); /* If nothing found, we can continue */ if (0 == from_pins.size()) { continue; } - /* For a valid coordinate, we can find the coordinate of the destination clb */ - vtr::Point to_grid_coord = find_inter_direct_destination_coordinate(device_ctx.grid, from_grid_coord, to_tile_name, arch_direct, arch_direct_id); - /* If destination clb is valid, we should add something */ - if (false == is_grid_coordinate_exist_in_device(device_ctx.grid, to_grid_coord)) { - continue; + /* For a valid coordinate, we can find the coordinate of the destination + * clb */ + vtr::Point to_grid_coord = + find_inter_direct_destination_coordinate( + device_ctx.grid, from_grid_coord, to_tile_name, arch_direct, + arch_direct_id); + /* If destination clb is valid, we should add something */ + if (false == is_grid_coordinate_exist_in_device(device_ctx.grid, + to_grid_coord)) { + continue; } /* Search all the sides, the to pin may locate any side! @@ -608,13 +618,12 @@ void build_inter_column_row_tile_direct(TileDirect& tile_direct, * This should be reported to VPR!!! */ for (const e_side& to_side : {TOP, RIGHT, BOTTOM, LEFT}) { - /* Try to find the pin in this tile */ - std::vector to_pins = find_physical_tile_pin_id(device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].type, - device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].width_offset, - device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].height_offset, - to_tile_port, - to_side); + std::vector to_pins = find_physical_tile_pin_id( + device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].type, + device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].width_offset, + device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].height_offset, + to_tile_port, to_side); /* If nothing found, we can continue */ if (0 == to_pins.size()) { continue; @@ -622,30 +631,27 @@ void build_inter_column_row_tile_direct(TileDirect& tile_direct, /* If from port and to port do not match in sizes, error out */ if (from_pins.size() != to_pins.size()) { - report_direct_from_port_and_to_port_mismatch(vpr_direct, from_tile_port, to_tile_port); + report_direct_from_port_and_to_port_mismatch( + vpr_direct, from_tile_port, to_tile_port); exit(1); } /* Now add the tile direct */ for (size_t ipin = 0; ipin < from_pins.size(); ++ipin) { VTR_LOGV(verbose, - "Built a inter-column/row tile-to-tile direct from %s[%lu][%lu].%s[%lu] at side '%s' to %s[%lu][%lu].%s[%lu] at side '%s'\n", - from_tile_name.c_str(), - from_grid_coord.x(), from_grid_coord.y(), - from_tile_port.get_name().c_str(), from_pins[ipin], - SIDE_STRING[from_side], - to_tile_name.c_str(), - to_grid_coord.x(), to_grid_coord.y(), + "Built a inter-column/row tile-to-tile direct from " + "%s[%lu][%lu].%s[%lu] at side '%s' to " + "%s[%lu][%lu].%s[%lu] at side '%s'\n", + from_tile_name.c_str(), from_grid_coord.x(), + from_grid_coord.y(), from_tile_port.get_name().c_str(), + from_pins[ipin], SIDE_STRING[from_side], + to_tile_name.c_str(), to_grid_coord.x(), to_grid_coord.y(), to_tile_port.get_name().c_str(), to_pins[ipin], - SIDE_STRING[to_side] - ); + SIDE_STRING[to_side]); - TileDirectId tile_direct_id = tile_direct.add_direct(from_grid_coord, - from_side, - from_pins[ipin], - to_grid_coord, - to_side, - to_pins[ipin]); + TileDirectId tile_direct_id = tile_direct.add_direct( + from_grid_coord, from_side, from_pins[ipin], to_grid_coord, + to_side, to_pins[ipin]); tile_direct.set_arch_direct_id(tile_direct_id, arch_direct_id); } } @@ -653,17 +659,17 @@ void build_inter_column_row_tile_direct(TileDirect& tile_direct, } return; /* Go to next direct type */ } - + /* Reach here, it must be a cross-row connection */ VTR_ASSERT(INTER_ROW == arch_direct.type(arch_direct_id)); - /* For cross-row connection, we will search the first valid grid in each column - * from x = 1 to x = nx + /* For cross-row connection, we will search the first valid grid in each + * column from x = 1 to x = nx * * x=1 x=nx * +------+ +------+ * | Grid | <--- ... ---- | Grid | * +------+ +------+ - * + * */ for (size_t iy = 1; iy < device_ctx.grid.height() - 1; ++iy) { std::vector> next_col_src_grid_coords; @@ -673,12 +679,16 @@ void build_inter_column_row_tile_direct(TileDirect& tile_direct, } /* For positive x- direction, we should start from x = 1 */ if (POSITIVE_DIR == arch_direct.x_dir(arch_direct_id)) { - std::reverse(next_col_src_grid_coords.begin(), next_col_src_grid_coords.end()); + std::reverse(next_col_src_grid_coords.begin(), + next_col_src_grid_coords.end()); } - vtr::Point from_grid_coord = find_grid_coordinate_given_type(device_ctx.grid, next_col_src_grid_coords, from_tile_name); - /* Skip if we do not have a valid coordinate for source CLB/heterogeneous block */ - if (false == is_grid_coordinate_exist_in_device(device_ctx.grid, from_grid_coord)) { + vtr::Point from_grid_coord = find_grid_coordinate_given_type( + device_ctx.grid, next_col_src_grid_coords, from_tile_name); + /* Skip if we do not have a valid coordinate for source CLB/heterogeneous + * block */ + if (false == + is_grid_coordinate_exist_in_device(device_ctx.grid, from_grid_coord)) { continue; } @@ -687,22 +697,26 @@ void build_inter_column_row_tile_direct(TileDirect& tile_direct, * This should be reported to VPR!!! */ for (const e_side& from_side : {TOP, RIGHT, BOTTOM, LEFT}) { - /* Try to find the pin in this tile */ - std::vector from_pins = find_physical_tile_pin_id(device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].type, - device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].width_offset, - device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].height_offset, - from_tile_port, - from_side); + std::vector from_pins = find_physical_tile_pin_id( + device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].type, + device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].width_offset, + device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].height_offset, + from_tile_port, from_side); /* If nothing found, we can continue */ if (0 == from_pins.size()) { continue; } - /* For a valid coordinate, we can find the coordinate of the destination clb */ - vtr::Point to_grid_coord = find_inter_direct_destination_coordinate(device_ctx.grid, from_grid_coord, to_tile_name, arch_direct, arch_direct_id); + /* For a valid coordinate, we can find the coordinate of the destination + * clb */ + vtr::Point to_grid_coord = + find_inter_direct_destination_coordinate(device_ctx.grid, + from_grid_coord, to_tile_name, + arch_direct, arch_direct_id); /* If destination clb is valid, we should add something */ - if (false == is_grid_coordinate_exist_in_device(device_ctx.grid, to_grid_coord)) { + if (false == + is_grid_coordinate_exist_in_device(device_ctx.grid, to_grid_coord)) { continue; } @@ -711,13 +725,12 @@ void build_inter_column_row_tile_direct(TileDirect& tile_direct, * This should be reported to VPR!!! */ for (const e_side& to_side : {TOP, RIGHT, BOTTOM, LEFT}) { - /* Try to find the pin in this tile */ - std::vector to_pins = find_physical_tile_pin_id(device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].type, - device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].width_offset, - device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].height_offset, - to_tile_port, - to_side); + std::vector to_pins = find_physical_tile_pin_id( + device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].type, + device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].width_offset, + device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].height_offset, + to_tile_port, to_side); /* If nothing found, we can continue */ if (0 == to_pins.size()) { continue; @@ -725,30 +738,27 @@ void build_inter_column_row_tile_direct(TileDirect& tile_direct, /* If from port and to port do not match in sizes, error out */ if (from_pins.size() != to_pins.size()) { - report_direct_from_port_and_to_port_mismatch(vpr_direct, from_tile_port, to_tile_port); + report_direct_from_port_and_to_port_mismatch( + vpr_direct, from_tile_port, to_tile_port); exit(1); } /* Now add the tile direct */ for (size_t ipin = 0; ipin < from_pins.size(); ++ipin) { VTR_LOGV(verbose, - "Built a inter-column/row tile-to-tile direct from %s[%lu][%lu].%s[%lu] at side '%s' to %s[%lu][%lu].%s[%lu] at side '%s'\n", - from_tile_name.c_str(), - from_grid_coord.x(), from_grid_coord.y(), - from_tile_port.get_name().c_str(), from_pins[ipin], - SIDE_STRING[from_side], - to_tile_name.c_str(), - to_grid_coord.x(), to_grid_coord.y(), + "Built a inter-column/row tile-to-tile direct from " + "%s[%lu][%lu].%s[%lu] at side '%s' to %s[%lu][%lu].%s[%lu] " + "at side '%s'\n", + from_tile_name.c_str(), from_grid_coord.x(), + from_grid_coord.y(), from_tile_port.get_name().c_str(), + from_pins[ipin], SIDE_STRING[from_side], + to_tile_name.c_str(), to_grid_coord.x(), to_grid_coord.y(), to_tile_port.get_name().c_str(), to_pins[ipin], - SIDE_STRING[to_side] - ); + SIDE_STRING[to_side]); - TileDirectId tile_direct_id = tile_direct.add_direct(from_grid_coord, - from_side, - from_pins[ipin], - to_grid_coord, - to_side, - to_pins[ipin]); + TileDirectId tile_direct_id = + tile_direct.add_direct(from_grid_coord, from_side, from_pins[ipin], + to_grid_coord, to_side, to_pins[ipin]); tile_direct.set_arch_direct_id(tile_direct_id, arch_direct_id); } } @@ -758,40 +768,40 @@ void build_inter_column_row_tile_direct(TileDirect& tile_direct, /*************************************************************************************** * Top-level functions that build the point-to-point direct connections - * between tiles (programmable blocks) + * between tiles (programmable blocks) ***************************************************************************************/ TileDirect build_device_tile_direct(const DeviceContext& device_ctx, const ArchDirect& arch_direct, const bool& verbose) { - vtr::ScopedStartFinishTimer timer("Build the annotation about direct connection between tiles"); + vtr::ScopedStartFinishTimer timer( + "Build the annotation about direct connection between tiles"); TileDirect tile_direct; /* Walk through each direct definition in the VPR arch */ for (int idirect = 0; idirect < device_ctx.arch->num_directs; ++idirect) { - ArchDirectId arch_direct_id = arch_direct.direct(std::string(device_ctx.arch->Directs[idirect].name)); + ArchDirectId arch_direct_id = + arch_direct.direct(std::string(device_ctx.arch->Directs[idirect].name)); if (ArchDirectId::INVALID() == arch_direct_id) { - VTR_LOG_ERROR("Unable to find an annotation in openfpga architecture XML for '%s'!\n", - device_ctx.arch->Directs[idirect].name); + VTR_LOG_ERROR( + "Unable to find an annotation in openfpga architecture XML for " + " '%s'!\n", + device_ctx.arch->Directs[idirect].name); exit(1); } /* Build from original VPR arch definition */ build_inner_column_row_tile_direct(tile_direct, device_ctx.arch->Directs[idirect], - device_ctx, - arch_direct_id, - verbose); - /* Build from OpenFPGA arch definition */ - build_inter_column_row_tile_direct(tile_direct, - device_ctx.arch->Directs[idirect], - device_ctx, - arch_direct, - arch_direct_id, - verbose); - } + device_ctx, arch_direct_id, verbose); + /* Build from OpenFPGA arch definition */ + build_inter_column_row_tile_direct( + tile_direct, device_ctx.arch->Directs[idirect], device_ctx, arch_direct, + arch_direct_id, verbose); + } - VTR_LOG("Built %lu tile-to-tile direct connections\n", - std::distance(tile_direct.directs().begin(), tile_direct.directs().end())); + VTR_LOG( + "Built %lu tile-to-tile direct connections\n", + std::distance(tile_direct.directs().begin(), tile_direct.directs().end())); return tile_direct; } diff --git a/openfpga/src/tile_direct/build_tile_direct.h b/openfpga/src/tile_direct/build_tile_direct.h index ed9e0c3bc..71d6a3955 100644 --- a/openfpga/src/tile_direct/build_tile_direct.h +++ b/openfpga/src/tile_direct/build_tile_direct.h @@ -4,10 +4,10 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" #include "arch_direct.h" -#include "tile_direct.h" #include "circuit_library.h" +#include "tile_direct.h" +#include "vpr_context.h" /******************************************************************** * Function declaration diff --git a/openfpga/src/tile_direct/tile_direct.cpp b/openfpga/src/tile_direct/tile_direct.cpp index 228724c78..bb6a4fb05 100644 --- a/openfpga/src/tile_direct/tile_direct.cpp +++ b/openfpga/src/tile_direct/tile_direct.cpp @@ -1,21 +1,22 @@ /****************************************************************************** * Memember functions for data structure TileDirect ******************************************************************************/ -#include "vtr_assert.h" - #include "tile_direct.h" +#include "vtr_assert.h" + /* begin namespace openfpga */ namespace openfpga { /************************************************** - * Public Accessors + * Public Accessors *************************************************/ TileDirect::tile_direct_range TileDirect::directs() const { return vtr::make_range(direct_ids_.begin(), direct_ids_.end()); } -vtr::Point TileDirect::from_tile_coordinate(const TileDirectId& direct_id) const { +vtr::Point TileDirect::from_tile_coordinate( + const TileDirectId& direct_id) const { /* Validate the direct_id */ VTR_ASSERT(valid_direct_id(direct_id)); return from_tile_coords_[direct_id]; @@ -33,7 +34,8 @@ e_side TileDirect::from_tile_side(const TileDirectId& direct_id) const { return from_tile_sides_[direct_id]; } -vtr::Point TileDirect::to_tile_coordinate(const TileDirectId& direct_id) const { +vtr::Point TileDirect::to_tile_coordinate( + const TileDirectId& direct_id) const { /* Validate the direct_id */ VTR_ASSERT(valid_direct_id(direct_id)); return to_tile_coords_[direct_id]; @@ -84,7 +86,7 @@ TileDirectId TileDirect::add_direct(const vtr::Point& from_tile_coord, return direct; } -void TileDirect::set_arch_direct_id(const TileDirectId& tile_direct_id, +void TileDirect::set_arch_direct_id(const TileDirectId& tile_direct_id, const ArchDirectId& arch_direct_id) { /* Validate the direct_id */ VTR_ASSERT(valid_direct_id(tile_direct_id)); @@ -95,7 +97,8 @@ void TileDirect::set_arch_direct_id(const TileDirectId& tile_direct_id, * Private validators/invalidators ******************************************************************************/ bool TileDirect::valid_direct_id(const TileDirectId& direct_id) const { - return ( size_t(direct_id) < direct_ids_.size() ) && ( direct_id == direct_ids_[direct_id] ); + return (size_t(direct_id) < direct_ids_.size()) && + (direct_id == direct_ids_[direct_id]); } } /* end namespace openfpga */ diff --git a/openfpga/src/tile_direct/tile_direct.h b/openfpga/src/tile_direct/tile_direct.h index 84593e80c..893b087e0 100644 --- a/openfpga/src/tile_direct/tile_direct.h +++ b/openfpga/src/tile_direct/tile_direct.h @@ -13,66 +13,70 @@ /* Headers from readarchopenfpga library */ #include "arch_direct.h" - #include "tile_direct_fwd.h" /* Begin namespace openfpga */ namespace openfpga { /******************************************************************** - * TileDirect object aims to be a database to store all the information + * TileDirect object aims to be a database to store all the information * about direct connection between tiles * - starting tile and end tile for each point-to-point direct connection * - circuit model to implement each direct connection * - * TileDirect is compiled from ArchDirect for a specific FPGA fabric. + * TileDirect is compiled from ArchDirect for a specific FPGA fabric. *******************************************************************/ class TileDirect { - public: /* Types and ranges */ - typedef vtr::vector::const_iterator tile_direct_iterator; - typedef vtr::Range tile_direct_range; - public: /* Public aggregators */ - tile_direct_range directs() const; - vtr::Point from_tile_coordinate(const TileDirectId& direct_id) const; - e_side from_tile_side(const TileDirectId& direct_id) const; - size_t from_tile_pin(const TileDirectId& direct_id) const; - vtr::Point to_tile_coordinate(const TileDirectId& direct_id) const; - e_side to_tile_side(const TileDirectId& direct_id) const; - size_t to_tile_pin(const TileDirectId& direct_id) const; - ArchDirectId arch_direct(const TileDirectId& direct_id) const; - public: /* Public mutators */ - TileDirectId add_direct(const vtr::Point& from_tile_coord, - const e_side& from_tile_side, - const size_t& from_tile_pin, - const vtr::Point& to_tile_coord, - const e_side& to_tile_side, - const size_t& to_tile_pin); - void set_arch_direct_id(const TileDirectId& tile_direct_id, - const ArchDirectId& arch_direct_id); - public: /* Public validators/invalidators */ - bool valid_direct_id(const TileDirectId& direct_id) const; - private: /* Internal Data */ - vtr::vector direct_ids_; + public: /* Types and ranges */ + typedef vtr::vector::const_iterator + tile_direct_iterator; + typedef vtr::Range tile_direct_range; - /* Detailed information about the starting tile - * - tile type description - * - tile coordinate - * - tile pin id - */ - vtr::vector> from_tile_coords_; - vtr::vector from_tile_sides_; - vtr::vector from_tile_pins_; + public: /* Public aggregators */ + tile_direct_range directs() const; + vtr::Point from_tile_coordinate(const TileDirectId& direct_id) const; + e_side from_tile_side(const TileDirectId& direct_id) const; + size_t from_tile_pin(const TileDirectId& direct_id) const; + vtr::Point to_tile_coordinate(const TileDirectId& direct_id) const; + e_side to_tile_side(const TileDirectId& direct_id) const; + size_t to_tile_pin(const TileDirectId& direct_id) const; + ArchDirectId arch_direct(const TileDirectId& direct_id) const; - /* Detailed information about the ending tile - * - tile type description - * - tile coordinate - * - tile pin id - */ - vtr::vector> to_tile_coords_; - vtr::vector to_tile_sides_; - vtr::vector to_tile_pins_; + public: /* Public mutators */ + TileDirectId add_direct(const vtr::Point& from_tile_coord, + const e_side& from_tile_side, + const size_t& from_tile_pin, + const vtr::Point& to_tile_coord, + const e_side& to_tile_side, + const size_t& to_tile_pin); + void set_arch_direct_id(const TileDirectId& tile_direct_id, + const ArchDirectId& arch_direct_id); - vtr::vector arch_directs_; + public: /* Public validators/invalidators */ + bool valid_direct_id(const TileDirectId& direct_id) const; + + private: /* Internal Data */ + vtr::vector direct_ids_; + + /* Detailed information about the starting tile + * - tile type description + * - tile coordinate + * - tile pin id + */ + vtr::vector> from_tile_coords_; + vtr::vector from_tile_sides_; + vtr::vector from_tile_pins_; + + /* Detailed information about the ending tile + * - tile type description + * - tile coordinate + * - tile pin id + */ + vtr::vector> to_tile_coords_; + vtr::vector to_tile_sides_; + vtr::vector to_tile_pins_; + + vtr::vector arch_directs_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/tile_direct/tile_direct_fwd.h b/openfpga/src/tile_direct/tile_direct_fwd.h index c83a00ee9..6a2acaf4b 100644 --- a/openfpga/src/tile_direct/tile_direct_fwd.h +++ b/openfpga/src/tile_direct/tile_direct_fwd.h @@ -1,5 +1,5 @@ /************************************************** - * This file includes only declarations for + * This file includes only declarations for * the data structures for TileDirect * Please refer to tile_direct.h for more details *************************************************/ @@ -20,4 +20,4 @@ class TileDirect; } /* end namespace openfpga */ -#endif +#endif diff --git a/openfpga/src/utils/check_tile_annotation.cpp b/openfpga/src/utils/check_tile_annotation.cpp index 4399fd888..6117e3109 100644 --- a/openfpga/src/utils/check_tile_annotation.cpp +++ b/openfpga/src/utils/check_tile_annotation.cpp @@ -9,13 +9,12 @@ #include /* Headers from vtrutil library */ +#include "check_tile_annotation.h" +#include "circuit_library_utils.h" +#include "openfpga_physical_tile_utils.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "openfpga_physical_tile_utils.h" -#include "circuit_library_utils.h" -#include "check_tile_annotation.h" - /* begin namespace openfpga */ namespace openfpga { @@ -23,60 +22,79 @@ namespace openfpga { * Check if the tile annotation is valid without any conflict with * circuit library content. * Items to check: - * - The global port defined in tile annotation has no conflicts with + * - The global port defined in tile annotation has no conflicts with * the global ports which are defined in circuit library: * - If a port has the same name, must ensure that its attributes are the same * i.e., is_clock, is_reset, is_set * - Otherwise, error out *******************************************************************/ -static -int check_tile_annotation_conflicts_with_circuit_library(const TileAnnotation& tile_annotation, - const CircuitLibrary& circuit_lib) { +static int check_tile_annotation_conflicts_with_circuit_library( + const TileAnnotation& tile_annotation, const CircuitLibrary& circuit_lib) { int num_err = 0; - - std::vector ckt_global_ports = find_circuit_library_global_ports(circuit_lib); - for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) { + + std::vector ckt_global_ports = + find_circuit_library_global_ports(circuit_lib); + for (const TileGlobalPortId& tile_global_port : + tile_annotation.global_ports()) { for (const CircuitPortId& ckt_global_port : ckt_global_ports) { - if (tile_annotation.global_port_name(tile_global_port) != circuit_lib.port_prefix(ckt_global_port)) { + if (tile_annotation.global_port_name(tile_global_port) != + circuit_lib.port_prefix(ckt_global_port)) { continue; } /* All the global clock port here must be operating clock */ bool is_both_op_signal = !circuit_lib.port_is_prog(ckt_global_port); if (false == is_both_op_signal) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Global port '%s' in tile annotation share the same name as global port '%s' in circuit library, which is defined for programming usage!\n", - tile_annotation.global_port_name(tile_global_port).c_str(), - circuit_lib.port_prefix(ckt_global_port).c_str()); + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Global port '%s' in tile annotation share the same name as global " + "port '%s' in circuit library, which is defined for programming " + "usage!\n", + tile_annotation.global_port_name(tile_global_port).c_str(), + circuit_lib.port_prefix(ckt_global_port).c_str()); num_err++; } /* Error out if one is defined as clock while another is not */ - bool is_clock_attr_same = (tile_annotation.global_port_is_clock(tile_global_port) != (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(ckt_global_port))); + bool is_clock_attr_same = + (tile_annotation.global_port_is_clock(tile_global_port) != + (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(ckt_global_port))); if (false == is_clock_attr_same) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Global port '%s' in tile annotation share the same name as global port '%s' in circuit library but has different definition as clock!\n", - tile_annotation.global_port_name(tile_global_port).c_str(), - circuit_lib.port_prefix(ckt_global_port).c_str()); + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Global port '%s' in tile annotation share the same name as global " + "port '%s' in circuit library but has different definition as " + "clock!\n", + tile_annotation.global_port_name(tile_global_port).c_str(), + circuit_lib.port_prefix(ckt_global_port).c_str()); num_err++; } /* Error out if one is defined as reset while another is not */ - bool is_reset_attr_same = (tile_annotation.global_port_is_reset(tile_global_port) != circuit_lib.port_is_reset(ckt_global_port)); + bool is_reset_attr_same = + (tile_annotation.global_port_is_reset(tile_global_port) != + circuit_lib.port_is_reset(ckt_global_port)); if (false == is_reset_attr_same) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Global port '%s' in tile annotation share the same name as global port '%s' in circuit library but has different definition as reset!\n", - tile_annotation.global_port_name(tile_global_port).c_str(), - circuit_lib.port_prefix(ckt_global_port).c_str()); + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Global port '%s' in tile annotation share the same name as global " + "port '%s' in circuit library but has different definition as " + "reset!\n", + tile_annotation.global_port_name(tile_global_port).c_str(), + circuit_lib.port_prefix(ckt_global_port).c_str()); num_err++; } /* Error out if one is defined as set while another is not */ - bool is_set_attr_same = (tile_annotation.global_port_is_set(tile_global_port) != circuit_lib.port_is_set(ckt_global_port)); + bool is_set_attr_same = + (tile_annotation.global_port_is_set(tile_global_port) != + circuit_lib.port_is_set(ckt_global_port)); if (false == is_set_attr_same) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Global port '%s' in tile annotation share the same name as global port '%s' in circuit library but has different definition as set!\n", - tile_annotation.global_port_name(tile_global_port).c_str(), - circuit_lib.port_prefix(ckt_global_port).c_str()); + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Global port '%s' in tile annotation share the same name as global " + "port '%s' in circuit library but has different definition as set!\n", + tile_annotation.global_port_name(tile_global_port).c_str(), + circuit_lib.port_prefix(ckt_global_port).c_str()); num_err++; } } @@ -89,28 +107,35 @@ int check_tile_annotation_conflicts_with_circuit_library(const TileAnnotation& t * Check if the tile annotation is valid without any conflict with * physical tile definition. * Items to check: - * - The global port defined in tile annotation is a valid port/pin in + * - The global port defined in tile annotation is a valid port/pin in * the physical tile definition. * - If the port properties match: - * - the port in physical tile should have Fc = 0 + * - the port in physical tile should have Fc = 0 * - a clock port should be also a clock port in physical tile - * - a non-clock port should be defined as a non-clock global port in physical tile + * - a non-clock port should be defined as a non-clock global port in physical + *tile *******************************************************************/ -static -int check_tile_annotation_conflicts_with_physical_tile(const TileAnnotation& tile_annotation, - const std::vector& physical_tile_types) { +static int check_tile_annotation_conflicts_with_physical_tile( + const TileAnnotation& tile_annotation, + const std::vector& physical_tile_types) { int num_err = 0; - for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) { - for (size_t tile_info_id = 0; tile_info_id < tile_annotation.global_port_tile_names(tile_global_port).size(); ++tile_info_id) { + for (const TileGlobalPortId& tile_global_port : + tile_annotation.global_ports()) { + for (size_t tile_info_id = 0; + tile_info_id < + tile_annotation.global_port_tile_names(tile_global_port).size(); + ++tile_info_id) { /* Must find a valid physical tile in the same name */ - size_t found_matched_physical_tile = 0; - size_t found_matched_physical_tile_port = 0; + size_t found_matched_physical_tile = 0; + size_t found_matched_physical_tile_port = 0; - std::string required_tile_name = tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id]; - BasicPort required_tile_port = tile_annotation.global_port_tile_ports(tile_global_port)[tile_info_id]; + std::string required_tile_name = + tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id]; + BasicPort required_tile_port = + tile_annotation.global_port_tile_ports(tile_global_port)[tile_info_id]; - for (const t_physical_tile_type& physical_tile : physical_tile_types) { + for (const t_physical_tile_type& physical_tile : physical_tile_types) { if (std::string(physical_tile.name) != required_tile_name) { continue; } @@ -118,114 +143,125 @@ int check_tile_annotation_conflicts_with_physical_tile(const TileAnnotation& til /* Found a match, increment the counter */ found_matched_physical_tile++; - /* Must found a valid port where both port name and port size must match!!! */ + /* Must found a valid port where both port name and port size must + * match!!! */ for (const t_sub_tile& sub_tile : physical_tile.sub_tiles) { - for (const t_physical_tile_port& tile_port : sub_tile.ports) { + for (const t_physical_tile_port& tile_port : sub_tile.ports) { if (std::string(tile_port.name) != required_tile_port.get_name()) { continue; } - BasicPort ref_tile_port(tile_port.name, sub_tile.capacity.total() * tile_port.num_pins); + BasicPort ref_tile_port( + tile_port.name, sub_tile.capacity.total() * tile_port.num_pins); /* Port size must be in range!!! */ if (false == ref_tile_port.contained(required_tile_port)) { - VTR_LOG_ERROR("Tile annotation port '%s[%lu:%lu]' is out of the range of physical tile port '%s[%lu:%lu]'!", - required_tile_port.get_name().c_str(), - required_tile_port.get_lsb(), - required_tile_port.get_msb(), - ref_tile_port.get_name().c_str(), - ref_tile_port.get_lsb(), - ref_tile_port.get_msb()); + VTR_LOG_ERROR( + "Tile annotation port '%s[%lu:%lu]' is out of the range of " + "physical tile port '%s[%lu:%lu]'!", + required_tile_port.get_name().c_str(), + required_tile_port.get_lsb(), required_tile_port.get_msb(), + ref_tile_port.get_name().c_str(), ref_tile_port.get_lsb(), + ref_tile_port.get_msb()); num_err++; continue; } - /* Check if port property matches */ int grid_pin_index = tile_port.absolute_first_pin_index; - if (tile_port.is_clock != tile_annotation.global_port_is_clock(tile_global_port)) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match physical tile port %s.%s in clock property (one is defined as clock while the other is not)!\n", - required_tile_name.c_str(), - required_tile_port.get_name().c_str(), - required_tile_port.get_lsb(), - required_tile_port.get_msb(), - tile_annotation.global_port_name(tile_global_port).c_str(), - physical_tile.name, tile_port.name); + if (tile_port.is_clock != + tile_annotation.global_port_is_clock(tile_global_port)) { + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not " + "match physical tile port %s.%s in clock property (one is " + "defined as clock while the other is not)!\n", + required_tile_name.c_str(), + required_tile_port.get_name().c_str(), + required_tile_port.get_lsb(), required_tile_port.get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str(), + physical_tile.name, tile_port.name); num_err++; } - if ((false == tile_port.is_clock) - && (false == tile_port.is_non_clock_global)) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but is not defined as a non-clock global port!\n", - required_tile_name.c_str(), - required_tile_port.get_name().c_str(), - required_tile_port.get_lsb(), - required_tile_port.get_msb(), - tile_annotation.global_port_name(tile_global_port).c_str(), - physical_tile.name, tile_port.name); + if ((false == tile_port.is_clock) && + (false == tile_port.is_non_clock_global)) { + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match " + "physical tile port %s.%s but is not defined as a non-clock " + "global port!\n", + required_tile_name.c_str(), + required_tile_port.get_name().c_str(), + required_tile_port.get_lsb(), required_tile_port.get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str(), + physical_tile.name, tile_port.name); num_err++; } - float pin_Fc = find_physical_tile_pin_Fc(&physical_tile, grid_pin_index); - if (0. != pin_Fc) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but its Fc is not zero '%g' !\n", - required_tile_name.c_str(), - required_tile_port.get_name().c_str(), - required_tile_port.get_lsb(), - required_tile_port.get_msb(), - tile_annotation.global_port_name(tile_global_port).c_str(), - physical_tile.name, tile_port.name, pin_Fc); - + float pin_Fc = + find_physical_tile_pin_Fc(&physical_tile, grid_pin_index); + if (0. != pin_Fc) { + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match " + "physical tile port %s.%s but its Fc is not zero '%g' !\n", + required_tile_name.c_str(), + required_tile_port.get_name().c_str(), + required_tile_port.get_lsb(), required_tile_port.get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str(), + physical_tile.name, tile_port.name, pin_Fc); } - - found_matched_physical_tile_port++; + + found_matched_physical_tile_port++; } } } /* If we found no match, error out */ if (0 == found_matched_physical_tile) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Tile name '%s' in tile annotation '%s' does not match any physical tile!\n", - required_tile_name.c_str(), - tile_annotation.global_port_name(tile_global_port).c_str()); + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Tile name '%s' in tile annotation '%s' does not match any physical " + "tile!\n", + required_tile_name.c_str(), + tile_annotation.global_port_name(tile_global_port).c_str()); num_err++; } if (0 == found_matched_physical_tile_port) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match any physical tile port!\n", - required_tile_name.c_str(), - required_tile_port.get_name().c_str(), - required_tile_port.get_lsb(), - required_tile_port.get_msb(), - tile_annotation.global_port_name(tile_global_port).c_str()); + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match " + "any physical tile port!\n", + required_tile_name.c_str(), required_tile_port.get_name().c_str(), + required_tile_port.get_lsb(), required_tile_port.get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str()); num_err++; } /* If we found more than 1 match, error out */ if (1 < found_matched_physical_tile) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Tile name '%s' in tile annotation '%s' match more than 1 physical tile!\n", - required_tile_name.c_str(), - tile_annotation.global_port_name(tile_global_port).c_str()); + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Tile name '%s' in tile annotation '%s' match more than 1 physical " + "tile!\n", + required_tile_name.c_str(), + tile_annotation.global_port_name(tile_global_port).c_str()); num_err++; } if (1 < found_matched_physical_tile_port) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match more than 1 physical tile port!\n", - required_tile_name.c_str(), - required_tile_port.get_name().c_str(), - required_tile_port.get_lsb(), - required_tile_port.get_msb(), - tile_annotation.global_port_name(tile_global_port).c_str()); + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match more than " + "1 physical tile port!\n", + required_tile_name.c_str(), required_tile_port.get_name().c_str(), + required_tile_port.get_lsb(), required_tile_port.get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str()); num_err++; } } } - + return num_err; } @@ -233,16 +269,17 @@ int check_tile_annotation_conflicts_with_physical_tile(const TileAnnotation& til * Check if the tile annotation is valid without any conflict with * circuit library content and physical tiles. *******************************************************************/ -bool check_tile_annotation(const TileAnnotation& tile_annotation, - const CircuitLibrary& circuit_lib, - const std::vector& physical_tile_types) { +bool check_tile_annotation( + const TileAnnotation& tile_annotation, const CircuitLibrary& circuit_lib, + const std::vector& physical_tile_types) { int num_err = 0; - num_err += check_tile_annotation_conflicts_with_circuit_library(tile_annotation, circuit_lib); + num_err += check_tile_annotation_conflicts_with_circuit_library( + tile_annotation, circuit_lib); - num_err += check_tile_annotation_conflicts_with_physical_tile(tile_annotation, physical_tile_types); + num_err += check_tile_annotation_conflicts_with_physical_tile( + tile_annotation, physical_tile_types); - VTR_LOG("Found %ld errors when checking tile annotation!\n", - num_err); + VTR_LOG("Found %ld errors when checking tile annotation!\n", num_err); return (0 == num_err); } diff --git a/openfpga/src/utils/check_tile_annotation.h b/openfpga/src/utils/check_tile_annotation.h index 7b2216a27..d35142ea2 100644 --- a/openfpga/src/utils/check_tile_annotation.h +++ b/openfpga/src/utils/check_tile_annotation.h @@ -5,9 +5,10 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "tile_annotation.h" + #include "circuit_library.h" #include "physical_types.h" +#include "tile_annotation.h" /******************************************************************** * Function declaration @@ -16,9 +17,9 @@ /* begin namespace openfpga */ namespace openfpga { -bool check_tile_annotation(const TileAnnotation& tile_annotations, - const CircuitLibrary& circuit_lib, - const std::vector& physical_tile_types); +bool check_tile_annotation( + const TileAnnotation& tile_annotations, const CircuitLibrary& circuit_lib, + const std::vector& physical_tile_types); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/circuit_library_utils.cpp b/openfpga/src/utils/circuit_library_utils.cpp index 45eea879c..abcac433c 100644 --- a/openfpga/src/utils/circuit_library_utils.cpp +++ b/openfpga/src/utils/circuit_library_utils.cpp @@ -1,5 +1,5 @@ /************************************************************************ - * Function to perform fundamental operation for the circuit library + * Function to perform fundamental operation for the circuit library * These functions are not universal methods for the CircuitLibrary class * They are made to ease the development in some specific purposes * Please classify such functions in this file @@ -8,46 +8,48 @@ #include /* Headers from vtrutil library */ +#include "check_circuit_library.h" +#include "circuit_library_utils.h" +#include "decoder_library_utils.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "check_circuit_library.h" -#include "decoder_library_utils.h" -#include "circuit_library_utils.h" - /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * Get the model id of a SRAM model that is used to configure + * Get the model id of a SRAM model that is used to configure * a circuit model *******************************************************************/ -std::vector find_circuit_sram_models(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model) { +std::vector find_circuit_sram_models( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model) { /* SRAM model id is stored in the sram ports of a circuit model */ - std::vector sram_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_SRAM); + std::vector sram_ports = + circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_SRAM); std::vector sram_models; - + /* Create a list of sram models, but avoid duplicated model ids */ for (const auto& sram_port : sram_ports) { CircuitModelId sram_model = circuit_lib.port_tri_state_model(sram_port); - VTR_ASSERT( true == circuit_lib.valid_model_id(sram_model) ); - if (sram_models.end() != std::find(sram_models.begin(), sram_models.end(), sram_model)) { - continue; /* Already in the list, skip the addition */ + VTR_ASSERT(true == circuit_lib.valid_model_id(sram_model)); + if (sram_models.end() != + std::find(sram_models.begin(), sram_models.end(), sram_model)) { + continue; /* Already in the list, skip the addition */ } /* Not in the list, add it */ sram_models.push_back(sram_model); } - + return sram_models; } /******************************************************************** * Find regular (not mode select) sram ports of a circuit model *******************************************************************/ -std::vector find_circuit_regular_sram_ports(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model) { - std::vector sram_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_SRAM, true); +std::vector find_circuit_regular_sram_ports( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model) { + std::vector sram_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_SRAM, true); std::vector regular_sram_ports; for (const auto& port : sram_ports) { @@ -63,9 +65,10 @@ std::vector find_circuit_regular_sram_ports(const CircuitLibrary& /******************************************************************** * Find mode select sram ports of a circuit model *******************************************************************/ -std::vector find_circuit_mode_select_sram_ports(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model) { - std::vector sram_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_SRAM, true); +std::vector find_circuit_mode_select_sram_ports( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model) { + std::vector sram_ports = circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_SRAM, true); std::vector mode_select_sram_ports; for (const auto& port : sram_ports) { @@ -78,121 +81,132 @@ std::vector find_circuit_mode_select_sram_ports(const CircuitLibr return mode_select_sram_ports; } - /******************************************************************** - * Find the number of shared configuration bits for a ReRAM circuit - * TODO: this function is subjected to be changed due to ReRAM-based SRAM cell design!!! + * Find the number of shared configuration bits for a ReRAM circuit + * TODO: this function is subjected to be changed due to ReRAM-based SRAM cell + *design!!! *******************************************************************/ -static -size_t find_rram_circuit_num_shared_config_bits(const CircuitLibrary& circuit_lib, - const CircuitModelId& rram_model, - const e_config_protocol_type& sram_orgz_type) { +static size_t find_rram_circuit_num_shared_config_bits( + const CircuitLibrary& circuit_lib, const CircuitModelId& rram_model, + const e_config_protocol_type& sram_orgz_type) { size_t num_shared_config_bits = 0; - /* Branch on the organization of configuration protocol */ + /* Branch on the organization of configuration protocol */ switch (sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - case CONFIG_MEM_SCAN_CHAIN: - break; - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: { - /* Find BL/WL ports */ - std::vector blb_ports = circuit_lib.model_ports_by_type(rram_model, CIRCUIT_MODEL_PORT_BLB); - for (auto blb_port : blb_ports) { - num_shared_config_bits = std::max((int)num_shared_config_bits, (int)circuit_lib.port_size(blb_port) - 1); + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_SCAN_CHAIN: + break; + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: { + /* Find BL/WL ports */ + std::vector blb_ports = + circuit_lib.model_ports_by_type(rram_model, CIRCUIT_MODEL_PORT_BLB); + for (auto blb_port : blb_ports) { + num_shared_config_bits = + std::max((int)num_shared_config_bits, + (int)circuit_lib.port_size(blb_port) - 1); + } + break; } - break; - } - default: - VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); - exit(1); + default: + VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); + exit(1); } return num_shared_config_bits; } /******************************************************************** - * A generic function to find the number of shared configuration bits + * A generic function to find the number of shared configuration bits * for circuit model - * It will return 0 for CMOS circuits + * It will return 0 for CMOS circuits * It will return the maximum shared configuration bits across ReRAM models * * Note: This function may give WRONG results when all the SRAM ports * are not properly linked to its circuit models! * So, it should be called after the SRAM linking is done!!! * - * IMPORTANT: This function should NOT be used to find the number of shared configuration bits - * for a multiplexer, because the multiplexer size is determined during - * the FPGA architecture generation (NOT during the XML parsing). + * IMPORTANT: This function should NOT be used to find the number of shared + *configuration bits for a multiplexer, because the multiplexer size is + *determined during the FPGA architecture generation (NOT during the XML + *parsing). *******************************************************************/ -size_t find_circuit_num_shared_config_bits(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const e_config_protocol_type& sram_orgz_type) { +size_t find_circuit_num_shared_config_bits( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const e_config_protocol_type& sram_orgz_type) { size_t num_shared_config_bits = 0; - std::vector sram_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_SRAM); + std::vector sram_ports = + circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_SRAM); for (auto sram_port : sram_ports) { CircuitModelId sram_model = circuit_lib.port_tri_state_model(sram_port); - VTR_ASSERT( true == circuit_lib.valid_model_id(sram_model) ); + VTR_ASSERT(true == circuit_lib.valid_model_id(sram_model)); - /* Depend on the design technolgy of SRAM model, the number of configuration bits will be different */ + /* Depend on the design technolgy of SRAM model, the number of configuration + * bits will be different */ switch (circuit_lib.design_tech_type(sram_model)) { - case CIRCUIT_MODEL_DESIGN_CMOS: - /* CMOS circuit do not need shared configuration bits */ - break; - case CIRCUIT_MODEL_DESIGN_RRAM: - /* RRAM circuit do need shared configuration bits, but it is subjected to the largest one among different SRAM models */ - num_shared_config_bits = std::max((int)num_shared_config_bits, (int)find_rram_circuit_num_shared_config_bits(circuit_lib, sram_model, sram_orgz_type)); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid design technology for SRAM model!\n"); - exit(1); + case CIRCUIT_MODEL_DESIGN_CMOS: + /* CMOS circuit do not need shared configuration bits */ + break; + case CIRCUIT_MODEL_DESIGN_RRAM: + /* RRAM circuit do need shared configuration bits, but it is subjected + * to the largest one among different SRAM models */ + num_shared_config_bits = + std::max((int)num_shared_config_bits, + (int)find_rram_circuit_num_shared_config_bits( + circuit_lib, sram_model, sram_orgz_type)); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid design technology for SRAM model!\n"); + exit(1); } - } + } return num_shared_config_bits; } /******************************************************************** - * A generic function to find the number of configuration bits + * A generic function to find the number of configuration bits * for circuit model - * It will sum up the sizes of all the sram ports - * - * IMPORTANT: This function should NOT be used to find the number of configuration bits - * for a multiplexer, because the multiplexer size is determined during - * the FPGA architecture generation (NOT during the XML parsing). + * It will sum up the sizes of all the sram ports + * + * IMPORTANT: This function should NOT be used to find the number of + *configuration bits for a multiplexer, because the multiplexer size is + *determined during the FPGA architecture generation (NOT during the XML + *parsing). *******************************************************************/ -size_t find_circuit_num_config_bits(const e_config_protocol_type& config_protocol_type, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model) { +size_t find_circuit_num_config_bits( + const e_config_protocol_type& config_protocol_type, + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model) { size_t num_config_bits = 0; - std::vector sram_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_SRAM); + std::vector sram_ports = + circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_SRAM); for (auto sram_port : sram_ports) { - num_config_bits += circuit_lib.port_size(sram_port); - } + num_config_bits += circuit_lib.port_size(sram_port); + } switch (config_protocol_type) { - case CONFIG_MEM_STANDALONE: - case CONFIG_MEM_SCAN_CHAIN: - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: { - break; - } - case CONFIG_MEM_FRAME_BASED: { - /* For frame-based configuration protocol - * The number of configuration bits is the address size - */ - if (0 < num_config_bits) { - num_config_bits = find_mux_local_decoder_addr_size(num_config_bits); + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_SCAN_CHAIN: + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: { + break; } - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization !\n"); - exit(1); + case CONFIG_MEM_FRAME_BASED: { + /* For frame-based configuration protocol + * The number of configuration bits is the address size + */ + if (0 < num_config_bits) { + num_config_bits = find_mux_local_decoder_addr_size(num_config_bits); + } + break; + } + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization !\n"); + exit(1); } return num_config_bits; @@ -200,11 +214,12 @@ size_t find_circuit_num_config_bits(const e_config_protocol_type& config_protoco /******************************************************************** * A generic function to find all the global ports in a circuit library - * - * IMPORTANT: This function will uniquify the global ports whose share + * + * IMPORTANT: This function will uniquify the global ports whose share * share the same name !!! *******************************************************************/ -std::vector find_circuit_library_global_ports(const CircuitLibrary& circuit_lib) { +std::vector find_circuit_library_global_ports( + const CircuitLibrary& circuit_lib) { std::vector global_ports; for (auto port : circuit_lib.ports()) { @@ -215,7 +230,8 @@ std::vector find_circuit_library_global_ports(const CircuitLibrar /* Check if a same port with the same name has already been in the list */ bool add_to_list = true; for (const auto& global_port : global_ports) { - if (0 == circuit_lib.port_prefix(port).compare(circuit_lib.port_prefix(global_port))) { + if (0 == circuit_lib.port_prefix(port).compare( + circuit_lib.port_prefix(global_port))) { /* Same name, skip list update */ add_to_list = false; break; @@ -225,7 +241,7 @@ std::vector find_circuit_library_global_ports(const CircuitLibrar /* Add the global_port to the list */ global_ports.push_back(port); } - } + } return global_ports; } @@ -235,7 +251,8 @@ std::vector find_circuit_library_global_ports(const CircuitLibrar * Verilog netlists in a circuit library * Netlists with same names will be considered as one *******************************************************************/ -std::vector find_circuit_library_unique_verilog_netlists(const CircuitLibrary& circuit_lib) { +std::vector find_circuit_library_unique_verilog_netlists( + const CircuitLibrary& circuit_lib) { std::vector netlists; for (const CircuitModelId& model : circuit_lib.models()) { @@ -244,13 +261,15 @@ std::vector find_circuit_library_unique_verilog_netlists(const Circ continue; } /* See if the netlist name is already in the list */ - std::vector::iterator it = std::find(netlists.begin(), netlists.end(), circuit_lib.model_verilog_netlist(model)); + std::vector::iterator it = + std::find(netlists.begin(), netlists.end(), + circuit_lib.model_verilog_netlist(model)); if (it == netlists.end()) { netlists.push_back(circuit_lib.model_verilog_netlist(model)); } } - return netlists; + return netlists; } /******************************************************************** @@ -258,7 +277,8 @@ std::vector find_circuit_library_unique_verilog_netlists(const Circ * Verilog netlists in a circuit library * Netlists with same names will be considered as one *******************************************************************/ -std::vector find_circuit_library_unique_spice_netlists(const CircuitLibrary& circuit_lib) { +std::vector find_circuit_library_unique_spice_netlists( + const CircuitLibrary& circuit_lib) { std::vector netlists; for (const CircuitModelId& model : circuit_lib.models()) { @@ -267,13 +287,14 @@ std::vector find_circuit_library_unique_spice_netlists(const Circui continue; } /* See if the netlist name is already in the list */ - std::vector::iterator it = std::find(netlists.begin(), netlists.end(), circuit_lib.model_spice_netlist(model)); + std::vector::iterator it = std::find( + netlists.begin(), netlists.end(), circuit_lib.model_spice_netlist(model)); if (it == netlists.end()) { netlists.push_back(circuit_lib.model_spice_netlist(model)); } } - return netlists; + return netlists; } /************************************************************************ @@ -281,78 +302,80 @@ std::vector find_circuit_library_unique_spice_netlists(const Circui * satisfy the needs of configuration protocol * - Configuration chain -based: we check if we have a CCFF model * - Flatten/Frame -based: we check if we have a SRAM model which has BL and WL - * - Memory bank: we check if we have a SRAM model. Also we need to check if we have valid CCFF models for BL/WL models (if selected) + * - Memory bank: we check if we have a SRAM model. Also we need to check if we + *have valid CCFF models for BL/WL models (if selected) ***********************************************************************/ -bool check_configurable_memory_circuit_model(const ConfigProtocol& config_protocol, - const CircuitLibrary& circuit_lib) { +bool check_configurable_memory_circuit_model( + const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib) { size_t num_err = 0; CircuitModelId config_mem_circuit_model = config_protocol.memory_model(); switch (config_protocol.type()) { - case CONFIG_MEM_SCAN_CHAIN: - num_err = check_ccff_circuit_model_ports(circuit_lib, - config_mem_circuit_model); - break; - case CONFIG_MEM_QL_MEMORY_BANK: { - num_err = check_sram_circuit_model_ports(circuit_lib, - config_mem_circuit_model, - true); - /* Check circuit model for BL protocol */ - CircuitModelId bl_memory_model = config_protocol.bl_memory_model(); - if ( BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type() - && CircuitModelId::INVALID() == bl_memory_model) { - VTR_LOG_ERROR("Expect a valid CCFF circuit model for BL protocol"); - num_err++; - } - if (bl_memory_model) { - num_err += check_bl_ccff_circuit_model_ports(circuit_lib, - bl_memory_model); - } + case CONFIG_MEM_SCAN_CHAIN: + num_err = + check_ccff_circuit_model_ports(circuit_lib, config_mem_circuit_model); + break; + case CONFIG_MEM_QL_MEMORY_BANK: { + num_err = check_sram_circuit_model_ports(circuit_lib, + config_mem_circuit_model, true); + /* Check circuit model for BL protocol */ + CircuitModelId bl_memory_model = config_protocol.bl_memory_model(); + if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type() && + CircuitModelId::INVALID() == bl_memory_model) { + VTR_LOG_ERROR("Expect a valid CCFF circuit model for BL protocol"); + num_err++; + } + if (bl_memory_model) { + num_err += + check_bl_ccff_circuit_model_ports(circuit_lib, bl_memory_model); + } - /* Check circuit model for WL protocol */ - CircuitModelId wl_memory_model = config_protocol.wl_memory_model(); - if ( BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type() - && CircuitModelId::INVALID() == wl_memory_model) { - VTR_LOG_ERROR("Expect a valid CCFF circuit model for WL protocol"); - num_err++; + /* Check circuit model for WL protocol */ + CircuitModelId wl_memory_model = config_protocol.wl_memory_model(); + if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type() && + CircuitModelId::INVALID() == wl_memory_model) { + VTR_LOG_ERROR("Expect a valid CCFF circuit model for WL protocol"); + num_err++; + } + if (wl_memory_model) { + num_err += + check_wl_ccff_circuit_model_ports(circuit_lib, wl_memory_model); + } + break; } - if (wl_memory_model) { - num_err += check_wl_ccff_circuit_model_ports(circuit_lib, - wl_memory_model); - } - break; + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_MEMORY_BANK: + case CONFIG_MEM_FRAME_BASED: + num_err = check_sram_circuit_model_ports(circuit_lib, + config_mem_circuit_model, true); + + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of configuration protocol!\n"); + return false; } - case CONFIG_MEM_STANDALONE: - case CONFIG_MEM_MEMORY_BANK: - case CONFIG_MEM_FRAME_BASED: - num_err = check_sram_circuit_model_ports(circuit_lib, - config_mem_circuit_model, - true); - - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of configuration protocol!\n"); - return false; - } - - VTR_LOG("Found %ld errors when checking configurable memory circuit models!\n", - num_err); + + VTR_LOG( + "Found %ld errors when checking configurable memory circuit models!\n", + num_err); return (0 == num_err); } /************************************************************************ - * Try to find the enable port control power-gate for a power-gated circuit model - * We will return the first port that meet the requirement: + * Try to find the enable port control power-gate for a power-gated circuit + *model We will return the first port that meet the requirement: * - a global port * - its function is labelled as config_enable * - default value is 0 * Return invalid id if not found ***********************************************************************/ -CircuitPortId find_circuit_model_power_gate_en_port(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model) { +CircuitPortId find_circuit_model_power_gate_en_port( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model) { VTR_ASSERT(true == circuit_lib.is_power_gated(circuit_model)); - std::vector global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector global_ports = + circuit_lib.model_global_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); /* Try to find an ENABLE port from the global ports */ CircuitPortId en_port = CircuitPortId::INVALID(); @@ -371,18 +394,20 @@ CircuitPortId find_circuit_model_power_gate_en_port(const CircuitLibrary& circui } /************************************************************************ - * Try to find the enableB port control power-gate for a power-gated circuit model - * We will return the first port that meet the requirement: + * Try to find the enableB port control power-gate for a power-gated circuit + *model We will return the first port that meet the requirement: * - a global port * - its function is labelled as config_enable * - default value is 1 * Return invalid id if not found ***********************************************************************/ -CircuitPortId find_circuit_model_power_gate_enb_port(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model) { +CircuitPortId find_circuit_model_power_gate_enb_port( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model) { CircuitPortId enb_port = CircuitPortId::INVALID(); VTR_ASSERT(true == circuit_lib.is_power_gated(circuit_model)); - std::vector global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); + std::vector global_ports = + circuit_lib.model_global_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true); /* Try to find an ENABLE_B port from the global ports */ for (const auto& port : global_ports) { @@ -400,22 +425,23 @@ CircuitPortId find_circuit_model_power_gate_enb_port(const CircuitLibrary& circu } /************************************************************************ - * Try to find the input ports for a LUT circuit model (EXCLUDE the global ports) - * which can optionally include those ports drives or is driven by hard logic + * Try to find the input ports for a LUT circuit model (EXCLUDE the global + *ports) which can optionally include those ports drives or is driven by hard + *logic ***********************************************************************/ -std::vector find_lut_circuit_model_input_port(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const bool& include_harden_port, - const bool& include_global_port) { +std::vector find_lut_circuit_model_input_port( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const bool& include_harden_port, const bool& include_global_port) { VTR_ASSERT(CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)); std::vector input_ports; /* Find all the non-global input ports */ - for (const auto& port : circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, !include_global_port)) { + for (const auto& port : circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_INPUT, !include_global_port)) { /* Skip harden ports if specified */ - if ( (true == circuit_lib.port_is_harden_lut_port(port)) - && (false == include_harden_port)) { + if ((true == circuit_lib.port_is_harden_lut_port(port)) && + (false == include_harden_port)) { continue; } input_ports.push_back(port); @@ -425,22 +451,23 @@ std::vector find_lut_circuit_model_input_port(const CircuitLibrar } /************************************************************************ - * Try to find the output ports for a LUT circuit model (EXCLUDE the global ports) - * which can optionally include those ports drives or is driven by hard logic + * Try to find the output ports for a LUT circuit model (EXCLUDE the global + *ports) which can optionally include those ports drives or is driven by hard + *logic ***********************************************************************/ -std::vector find_lut_circuit_model_output_port(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const bool& include_harden_port, - const bool& include_global_port) { +std::vector find_lut_circuit_model_output_port( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const bool& include_harden_port, const bool& include_global_port) { VTR_ASSERT(CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)); std::vector output_ports; /* Find all the non-global input ports */ - for (const auto& port : circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, !include_global_port)) { + for (const auto& port : circuit_lib.model_ports_by_type( + circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, !include_global_port)) { /* Skip harden ports if specified */ - if ( (true == circuit_lib.port_is_harden_lut_port(port)) - && (false == include_harden_port)) { + if ((true == circuit_lib.port_is_harden_lut_port(port)) && + (false == include_harden_port)) { continue; } output_ports.push_back(port); diff --git a/openfpga/src/utils/circuit_library_utils.h b/openfpga/src/utils/circuit_library_utils.h index fe5fb03f7..9a1d9e144 100644 --- a/openfpga/src/utils/circuit_library_utils.h +++ b/openfpga/src/utils/circuit_library_utils.h @@ -8,6 +8,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "circuit_library.h" #include "config_protocol.h" @@ -18,47 +19,48 @@ /* begin namespace openfpga */ namespace openfpga { -std::vector find_circuit_sram_models(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model); +std::vector find_circuit_sram_models( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model); -std::vector find_circuit_regular_sram_ports(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model); +std::vector find_circuit_regular_sram_ports( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model); -std::vector find_circuit_mode_select_sram_ports(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model); +std::vector find_circuit_mode_select_sram_ports( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model); -size_t find_circuit_num_shared_config_bits(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const e_config_protocol_type& sram_orgz_type); +size_t find_circuit_num_shared_config_bits( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const e_config_protocol_type& sram_orgz_type); -size_t find_circuit_num_config_bits(const e_config_protocol_type& config_protocol_type, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model); +size_t find_circuit_num_config_bits( + const e_config_protocol_type& config_protocol_type, + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model); -std::vector find_circuit_library_global_ports(const CircuitLibrary& circuit_lib); +std::vector find_circuit_library_global_ports( + const CircuitLibrary& circuit_lib); -std::vector find_circuit_library_unique_verilog_netlists(const CircuitLibrary& circuit_lib); +std::vector find_circuit_library_unique_verilog_netlists( + const CircuitLibrary& circuit_lib); -std::vector find_circuit_library_unique_spice_netlists(const CircuitLibrary& circuit_lib); +std::vector find_circuit_library_unique_spice_netlists( + const CircuitLibrary& circuit_lib); -bool check_configurable_memory_circuit_model(const ConfigProtocol& config_protocol, - const CircuitLibrary& circuit_lib); +bool check_configurable_memory_circuit_model( + const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib); -CircuitPortId find_circuit_model_power_gate_en_port(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model); +CircuitPortId find_circuit_model_power_gate_en_port( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model); -CircuitPortId find_circuit_model_power_gate_enb_port(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model); +CircuitPortId find_circuit_model_power_gate_enb_port( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model); -std::vector find_lut_circuit_model_input_port(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const bool& include_harden_port, - const bool& include_global_port = true); +std::vector find_lut_circuit_model_input_port( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const bool& include_harden_port, const bool& include_global_port = true); -std::vector find_lut_circuit_model_output_port(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const bool& include_harden_port, - const bool& include_global_port = true); +std::vector find_lut_circuit_model_output_port( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const bool& include_harden_port, const bool& include_global_port = true); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/decoder_library_utils.cpp b/openfpga/src/utils/decoder_library_utils.cpp index b44bb106c..d3232b7ae 100644 --- a/openfpga/src/utils/decoder_library_utils.cpp +++ b/openfpga/src/utils/decoder_library_utils.cpp @@ -1,20 +1,21 @@ /*************************************************************************************** - * This file includes most utilized functions for the DecoderLibrary data structure + * This file includes most utilized functions for the DecoderLibrary data + *structure ***************************************************************************************/ +#include "decoder_library_utils.h" + #include #include "vtr_assert.h" -#include "decoder_library_utils.h" - /* Begin namespace openfpga */ namespace openfpga { /*************************************************************************************** * NOTE: This function is mainly designed for local decoders inside multiplexers * Find the size of address lines for a decoder with a given data output size - * Addr lines - * | | ... | + * Addr lines + * | | ... | * v v v * +-----------+ * / Local \ @@ -23,10 +24,10 @@ namespace openfpga { * | | | ... | | | * v v v v v v * Data outputs - * + * * The outputs are assumes to be one-hot codes (at most only one '1' exist) - * Considering this fact, there are only num_of_outputs + 1 conditions to be encoded. - * Therefore, the number of inputs is ceil(log(num_of_outputs+1)/log(2)) + * Considering this fact, there are only num_of_outputs + 1 conditions to be + *encoded. Therefore, the number of inputs is ceil(log(num_of_outputs+1)/log(2)) * We plus 1, which is all-zero condition for outputs ***************************************************************************************/ size_t find_mux_local_decoder_addr_size(const size_t& data_size) { @@ -34,14 +35,14 @@ size_t find_mux_local_decoder_addr_size(const size_t& data_size) { if (1 == data_size) { return 1; } - VTR_ASSERT (2 <= data_size); + VTR_ASSERT(2 <= data_size); return ceil(log(data_size) / log(2)); } /*************************************************************************************** * Find the size of address lines for a memory decoder to access a memory array - * Addr lines - * | | ... | + * Addr lines + * | | ... | * v v v * +-----------+ * / Local \ @@ -68,19 +69,22 @@ size_t find_mux_local_decoder_addr_size(const size_t& data_size) { * | [x] | | [x+1]| | [N] | * +------+ +------+ +------+ * - * Due to the shared lines in the array, + * Due to the shared lines in the array, * each memory decoder (BL or WL) will access sqrt(N) control lins (BL or WL) - * Then we can use the function for mux local encoder to compute the address size - * + * Then we can use the function for mux local encoder to compute the address + *size + * ***************************************************************************************/ size_t find_memory_decoder_addr_size(const size_t& num_mems) { - return find_mux_local_decoder_addr_size(find_memory_decoder_data_size(num_mems)); + return find_mux_local_decoder_addr_size( + find_memory_decoder_data_size(num_mems)); } /*************************************************************************************** - * Find the size of data lines (BLs and WLs) for a memory decoder to access a memory array - * As the memory cells are organized in an array with shared bit lines and word lines, - * the number of data lines will be a square root of the number of memory cells. + * Find the size of data lines (BLs and WLs) for a memory decoder to access a + *memory array As the memory cells are organized in an array with shared bit + *lines and word lines, the number of data lines will be a square root of the + *number of memory cells. ***************************************************************************************/ size_t find_memory_decoder_data_size(const size_t& num_mems) { return (size_t)std::ceil(std::sqrt((float)num_mems)); @@ -88,15 +92,15 @@ size_t find_memory_decoder_data_size(const size_t& num_mems) { /*************************************************************************************** * Find the size of WL data lines for a memory decoder to access a memory array - * This function is applicable to a memory bank organization where BL data lines - * is the dominant factor. It means that the BL data lines is strictly an integeter close - * to the square root of the number of memory cells. - * For example, 203 memory cells leads to 15 BLs to control - * The WL data lines may not be exactly the same as the number of BLs. - * Considering the example of 203 memory cells again, when 15 BLs are used, we just need - * 203 / 15 = 13.5555 -> 14 WLs + * This function is applicable to a memory bank organization where BL data lines + * is the dominant factor. It means that the BL data lines is strictly an + *integeter close to the square root of the number of memory cells. For example, + *203 memory cells leads to 15 BLs to control The WL data lines may not be + *exactly the same as the number of BLs. Considering the example of 203 memory + *cells again, when 15 BLs are used, we just need 203 / 15 = 13.5555 -> 14 WLs ***************************************************************************************/ -size_t find_memory_wl_decoder_data_size(const size_t& num_mems, const size_t& num_bls) { +size_t find_memory_wl_decoder_data_size(const size_t& num_mems, + const size_t& num_bls) { /* Handle exception: zero BLs should have zero WLs */ if (0 == num_bls) { return 0; @@ -105,18 +109,20 @@ size_t find_memory_wl_decoder_data_size(const size_t& num_mems, const size_t& nu } /*************************************************************************************** - * Try to find if the decoder already exists in the library, - * If there is no such decoder, add it to the library + * Try to find if the decoder already exists in the library, + * If there is no such decoder, add it to the library ***************************************************************************************/ -DecoderId add_mux_local_decoder_to_library(DecoderLibrary& decoder_lib, +DecoderId add_mux_local_decoder_to_library(DecoderLibrary& decoder_lib, const size_t data_size) { size_t addr_size = find_mux_local_decoder_addr_size(data_size); - DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, false, false, true, false); + DecoderId decoder_id = + decoder_lib.find_decoder(addr_size, data_size, false, false, true, false); - if (DecoderId::INVALID() == decoder_id) { + if (DecoderId::INVALID() == decoder_id) { /* Add the decoder */ - return decoder_lib.add_decoder(addr_size, data_size, false, false, true, false); + return decoder_lib.add_decoder(addr_size, data_size, false, false, true, + false); } /* There is already a decoder in the library, return the decoder id */ diff --git a/openfpga/src/utils/decoder_library_utils.h b/openfpga/src/utils/decoder_library_utils.h index 34b8662ef..51d6da6dd 100644 --- a/openfpga/src/utils/decoder_library_utils.h +++ b/openfpga/src/utils/decoder_library_utils.h @@ -17,9 +17,10 @@ size_t find_memory_decoder_addr_size(const size_t& num_mems); size_t find_memory_decoder_data_size(const size_t& num_mems); -size_t find_memory_wl_decoder_data_size(const size_t& num_mems, const size_t& num_bls); +size_t find_memory_wl_decoder_data_size(const size_t& num_mems, + const size_t& num_bls); -DecoderId add_mux_local_decoder_to_library(DecoderLibrary& decoder_lib, +DecoderId add_mux_local_decoder_to_library(DecoderLibrary& decoder_lib, const size_t data_size); } /* End namespace openfpga*/ diff --git a/openfpga/src/utils/device_rr_gsb_utils.cpp b/openfpga/src/utils/device_rr_gsb_utils.cpp index dfda5618a..31d1669ec 100644 --- a/openfpga/src/utils/device_rr_gsb_utils.cpp +++ b/openfpga/src/utils/device_rr_gsb_utils.cpp @@ -3,11 +3,11 @@ * DeviceRRGSB *******************************************************************/ /* Headers from vtrutil library */ +#include "device_rr_gsb_utils.h" + #include "vtr_assert.h" #include "vtr_log.h" -#include "device_rr_gsb_utils.h" - /* begin namespace openfpga */ namespace openfpga { @@ -18,8 +18,8 @@ namespace openfpga { size_t find_device_rr_gsb_num_cb_modules(const DeviceRRGSB& device_rr_gsb, const t_rr_type& cb_type) { size_t counter = 0; - for (size_t x = 0; x < device_rr_gsb.get_gsb_range().x(); ++x) { - for (size_t y = 0; y < device_rr_gsb.get_gsb_range().y(); ++y) { + for (size_t x = 0; x < device_rr_gsb.get_gsb_range().x(); ++x) { + for (size_t y = 0; y < device_rr_gsb.get_gsb_range().y(); ++y) { const RRGSB& rr_gsb = device_rr_gsb.get_gsb(x, y); if (true == rr_gsb.is_cb_exist(cb_type)) { counter++; @@ -36,8 +36,8 @@ size_t find_device_rr_gsb_num_cb_modules(const DeviceRRGSB& device_rr_gsb, *******************************************************************/ size_t find_device_rr_gsb_num_sb_modules(const DeviceRRGSB& device_rr_gsb) { size_t counter = 0; - for (size_t x = 0; x < device_rr_gsb.get_gsb_range().x(); ++x) { - for (size_t y = 0; y < device_rr_gsb.get_gsb_range().y(); ++y) { + for (size_t x = 0; x < device_rr_gsb.get_gsb_range().x(); ++x) { + for (size_t y = 0; y < device_rr_gsb.get_gsb_range().y(); ++y) { const RRGSB& rr_gsb = device_rr_gsb.get_gsb(x, y); if (true == rr_gsb.is_sb_exist()) { counter++; @@ -53,8 +53,8 @@ size_t find_device_rr_gsb_num_sb_modules(const DeviceRRGSB& device_rr_gsb) { *******************************************************************/ size_t find_device_rr_gsb_num_gsb_modules(const DeviceRRGSB& device_rr_gsb) { size_t counter = 0; - for (size_t x = 0; x < device_rr_gsb.get_gsb_range().x(); ++x) { - for (size_t y = 0; y < device_rr_gsb.get_gsb_range().y(); ++y) { + for (size_t x = 0; x < device_rr_gsb.get_gsb_range().x(); ++x) { + for (size_t y = 0; y < device_rr_gsb.get_gsb_range().y(); ++y) { if (true == device_rr_gsb.is_gsb_exist(vtr::Point(x, y))) { counter++; } @@ -62,7 +62,6 @@ size_t find_device_rr_gsb_num_gsb_modules(const DeviceRRGSB& device_rr_gsb) { } return counter; - } } /* end namespace openfpga */ diff --git a/openfpga/src/utils/device_rr_gsb_utils.h b/openfpga/src/utils/device_rr_gsb_utils.h index 7b49839a9..0b7424b4f 100644 --- a/openfpga/src/utils/device_rr_gsb_utils.h +++ b/openfpga/src/utils/device_rr_gsb_utils.h @@ -6,6 +6,7 @@ *******************************************************************/ #include #include + #include "device_rr_gsb.h" /******************************************************************** diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index e7492b1cd..00afc6e55 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -13,10 +13,9 @@ #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_reserved_words.h" -#include "openfpga_decode.h" - #include "fabric_bitstream_utils.h" +#include "openfpga_decode.h" +#include "openfpga_reserved_words.h" /* begin namespace openfpga */ namespace openfpga { @@ -24,11 +23,13 @@ namespace openfpga { /******************************************************************** * Find the longest bitstream size of a fabric bitstream *******************************************************************/ -size_t find_fabric_regional_bitstream_max_size(const FabricBitstream& fabric_bitstream) { +size_t find_fabric_regional_bitstream_max_size( + const FabricBitstream& fabric_bitstream) { size_t regional_bitstream_max_size = 0; /* Find the longest regional bitstream */ for (const auto& region : fabric_bitstream.regions()) { - if (regional_bitstream_max_size < fabric_bitstream.region_bits(region).size()) { + if (regional_bitstream_max_size < + fabric_bitstream.region_bits(region).size()) { regional_bitstream_max_size = fabric_bitstream.region_bits(region).size(); } } @@ -45,61 +46,69 @@ size_t find_fabric_regional_bitstream_max_size(const FabricBitstream& fabric_bit * The number of bits that can be skipped is limited by Region 2 * Find the longest bitstream size of a fabric bitstream *******************************************************************/ -size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped(const FabricBitstream& fabric_bitstream, - const BitstreamManager& bitstream_manager, - const bool& bit_value_to_skip) { - size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream); +size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped( + const FabricBitstream& fabric_bitstream, + const BitstreamManager& bitstream_manager, const bool& bit_value_to_skip) { + size_t regional_bitstream_max_size = + find_fabric_regional_bitstream_max_size(fabric_bitstream); size_t num_bits_to_skip = size_t(-1); for (const auto& region : fabric_bitstream.regions()) { size_t curr_region_num_bits_to_skip = 0; for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { - if (bit_value_to_skip != bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) { + if (bit_value_to_skip != + bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id))) { break; } curr_region_num_bits_to_skip++; } /* For regional bitstream which is short than the longest region bitstream, - * The number of bits to skip + * The number of bits to skip */ - curr_region_num_bits_to_skip += regional_bitstream_max_size - fabric_bitstream.region_bits(region).size(); - num_bits_to_skip = std::min(curr_region_num_bits_to_skip, num_bits_to_skip); + curr_region_num_bits_to_skip += + regional_bitstream_max_size - fabric_bitstream.region_bits(region).size(); + num_bits_to_skip = std::min(curr_region_num_bits_to_skip, num_bits_to_skip); } return num_bits_to_skip; } /******************************************************************** - * Build a fabric bitstream which can be directly loaded to a configuration + * Build a fabric bitstream which can be directly loaded to a configuration * chain (either single-head or multi-bit) - * We will organize the bitstreams in each region and align them + * We will organize the bitstreams in each region and align them * Logic '0' bits may be deposited to those bitstream whose length is smaller * than the maximum bitstream among all the regions * For example: * Region 0: 000000001111101010 <- max. bitstream length - * Region 1: 00000011010101 <- shorter bitstream than the max.; add zeros to the head - * Region 2: 0010101111000110 <- shorter bitstream than the max.; add zeros to the head + * Region 1: 00000011010101 <- shorter bitstream than the max.; add zeros + *to the head Region 2: 0010101111000110 <- shorter bitstream than the max.; + *add zeros to the head *******************************************************************/ -ConfigChainFabricBitstream build_config_chain_fabric_bitstream_by_region(const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream) { +ConfigChainFabricBitstream build_config_chain_fabric_bitstream_by_region( + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream) { /* Find the longest bitstream */ - size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream); + size_t regional_bitstream_max_size = + find_fabric_regional_bitstream_max_size(fabric_bitstream); ConfigChainFabricBitstream regional_bitstreams; regional_bitstreams.reserve(fabric_bitstream.regions().size()); for (const FabricBitRegionId& region : fabric_bitstream.regions()) { std::vector curr_regional_bitstream; curr_regional_bitstream.resize(regional_bitstream_max_size, false); - /* Starting index should consider the offset between the current bitstream size and - * the maximum size of regional bitstream + /* Starting index should consider the offset between the current bitstream + * size and the maximum size of regional bitstream */ - size_t offset = regional_bitstream_max_size - fabric_bitstream.region_bits(region).size(); + size_t offset = + regional_bitstream_max_size - fabric_bitstream.region_bits(region).size(); for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { - curr_regional_bitstream[offset] = bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id)); + curr_regional_bitstream[offset] = + bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id)); offset++; } VTR_ASSERT(offset == regional_bitstream_max_size); - + /* Add the adapt sub-bitstream */ regional_bitstreams.push_back(curr_regional_bitstream); } @@ -109,15 +118,15 @@ ConfigChainFabricBitstream build_config_chain_fabric_bitstream_by_region(const B /******************************************************************** * Reorganize the fabric bitstream for frame-based protocol * by the same address across regions: - * This is due to that the length of fabric bitstream could be different in each region. - * Template: - *
- * An example: + * This is due to that the length of fabric bitstream could be different in each + *region. Template:
An example: * 000000 1011 * - * Note: the std::map may cause large memory footprint for large bitstream databases! + * Note: the std::map may cause large memory footprint for large bitstream + *databases! *******************************************************************/ -FrameFabricBitstream build_frame_based_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream) { +FrameFabricBitstream build_frame_based_fabric_bitstream_by_address( + const FabricBitstream& fabric_bitstream) { FrameFabricBitstream fabric_bits_by_addr; for (const FabricBitRegionId& region : fabric_bitstream.regions()) { for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { @@ -128,15 +137,18 @@ FrameFabricBitstream build_frame_based_fabric_bitstream_by_address(const FabricB } /* Expand all the don't care bits */ - for (const std::string& curr_addr_str : expand_dont_care_bin_str(addr_str)) { + for (const std::string& curr_addr_str : + expand_dont_care_bin_str(addr_str)) { /* Place the config bit */ auto result = fabric_bits_by_addr.find(curr_addr_str); if (result == fabric_bits_by_addr.end()) { /* This is a new bit, resize the vector to the number of regions * and deposit '0' to all the bits */ - fabric_bits_by_addr[curr_addr_str] = std::vector(fabric_bitstream.regions().size(), false); - fabric_bits_by_addr[curr_addr_str][size_t(region)] = fabric_bitstream.bit_din(bit_id); + fabric_bits_by_addr[curr_addr_str] = + std::vector(fabric_bitstream.regions().size(), false); + fabric_bits_by_addr[curr_addr_str][size_t(region)] = + fabric_bitstream.bit_din(bit_id); } else { VTR_ASSERT_SAFE(result != fabric_bits_by_addr.end()); result->second[size_t(region)] = fabric_bitstream.bit_din(bit_id); @@ -144,31 +156,29 @@ FrameFabricBitstream build_frame_based_fabric_bitstream_by_address(const FabricB } } } - + return fabric_bits_by_addr; } /******************************************************************** * For fast configuration, the number of bits to be skipped - * the rule to skip any configuration bit should consider the whole data input values. - * Only all the bits in the din port match the value to be skipped, - * the programming cycle can be skipped! - * For example: - * Address: 010101 - * Region 0: 0 - * Region 1: 1 - * Region 2: 0 + * the rule to skip any configuration bit should consider the whole data input + *values. Only all the bits in the din port match the value to be skipped, the + *programming cycle can be skipped! For example: Address: 010101 Region 0: 0 + * Region 1: 1 + * Region 2: 0 * This bit cannot be skipped if the bit_value_to_skip is 0 * * Address: 010101 * Region 0: 0 - * Region 1: 0 - * Region 2: 0 + * Region 1: 0 + * Region 2: 0 * This bit can be skipped if the bit_value_to_skip is 0 *******************************************************************/ -size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream, - const bool& bit_value_to_skip) { - FrameFabricBitstream fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream); +size_t find_frame_based_fast_configuration_fabric_bitstream_size( + const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip) { + FrameFabricBitstream fabric_bits_by_addr = + build_frame_based_fabric_bitstream_by_address(fabric_bitstream); size_t num_bits = 0; @@ -192,15 +202,15 @@ size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBit /******************************************************************** * Reorganize the fabric bitstream for memory banks which use BL and WL decoders * by the same address across regions: - * This is due to that the length of fabric bitstream could be different in each region. - * Template: - * - * An example: - * 000000 00000 1011 + * This is due to that the length of fabric bitstream could be different in each + *region. Template: + * An example: 000000 00000 1011 * - * Note: the std::map may cause large memory footprint for large bitstream databases! + * Note: the std::map may cause large memory footprint for large bitstream + *databases! *******************************************************************/ -MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream) { +MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address( + const FabricBitstream& fabric_bitstream) { MemoryBankFabricBitstream fabric_bits_by_addr; for (const FabricBitRegionId& region : fabric_bitstream.regions()) { for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { @@ -217,13 +227,16 @@ MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const Fa } /* Place the config bit */ - auto result = fabric_bits_by_addr.find(std::make_pair(bl_addr_str, wl_addr_str)); + auto result = + fabric_bits_by_addr.find(std::make_pair(bl_addr_str, wl_addr_str)); if (result == fabric_bits_by_addr.end()) { /* This is a new bit, resize the vector to the number of regions * and deposit '0' to all the bits */ - fabric_bits_by_addr[std::make_pair(bl_addr_str, wl_addr_str)] = std::vector(fabric_bitstream.regions().size(), false); - fabric_bits_by_addr[std::make_pair(bl_addr_str, wl_addr_str)][size_t(region)] = fabric_bitstream.bit_din(bit_id); + fabric_bits_by_addr[std::make_pair(bl_addr_str, wl_addr_str)] = + std::vector(fabric_bitstream.regions().size(), false); + fabric_bits_by_addr[std::make_pair(bl_addr_str, wl_addr_str)] + [size_t(region)] = fabric_bitstream.bit_din(bit_id); } else { VTR_ASSERT_SAFE(result != fabric_bits_by_addr.end()); result->second[size_t(region)] = fabric_bitstream.bit_din(bit_id); @@ -234,18 +247,20 @@ MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const Fa return fabric_bits_by_addr; } -MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const char& dont_care_bit) { - /* If fast configuration is not enabled, we need all the wl address even some of them have all-dont-care-bits BLs */ +MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream( + const FabricBitstream& fabric_bitstream, const bool& fast_configuration, + const bool& bit_value_to_skip, const char& dont_care_bit) { + /* If fast configuration is not enabled, we need all the wl address even some + * of them have all-dont-care-bits BLs */ if (!fast_configuration) { - vtr::vector> fabric_bits_per_region; + vtr::vector> + fabric_bits_per_region; fabric_bits_per_region.resize(fabric_bitstream.num_regions()); for (const FabricBitRegionId& region : fabric_bitstream.regions()) { for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { /* Create string for BL address with complete don't care bits */ - std::string bl_addr_str(fabric_bitstream.bit_bl_address(bit_id).size(), dont_care_bit); + std::string bl_addr_str(fabric_bitstream.bit_bl_address(bit_id).size(), + dont_care_bit); /* Create string for WL address */ std::string wl_addr_str; @@ -259,8 +274,10 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons } } - /* Build the bitstream by each region, here we use (WL, BL) pairs when storing bitstreams */ - vtr::vector> fabric_bits_per_region; + /* Build the bitstream by each region, here we use (WL, BL) pairs when storing + * bitstreams */ + vtr::vector> + fabric_bits_per_region; fabric_bits_per_region.resize(fabric_bitstream.num_regions()); for (const FabricBitRegionId& region : fabric_bitstream.regions()) { for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { @@ -292,50 +309,65 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons } } - /* Find all the keys for the hash tables containing bitstream of each region */ - vtr::vector> fabric_bits_per_region_keys; + /* Find all the keys for the hash tables containing bitstream of each region + */ + vtr::vector> + fabric_bits_per_region_keys; fabric_bits_per_region_keys.resize(fabric_bitstream.num_regions()); for (const FabricBitRegionId& region : fabric_bitstream.regions()) { /* Pre-allocate memory, because the key size may be large */ - fabric_bits_per_region_keys[region].reserve(fabric_bits_per_region[region].size()); + fabric_bits_per_region_keys[region].reserve( + fabric_bits_per_region[region].size()); for (const auto& pair : fabric_bits_per_region[region]) { fabric_bits_per_region_keys[region].push_back(pair.first); - } + } } /* Find the maxium key size */ size_t max_key_size = 0; for (const FabricBitRegionId& region : fabric_bitstream.regions()) { - max_key_size = std::max(max_key_size, fabric_bits_per_region_keys[region].size()); - } - - /* Find the BL/WL sizes per region; Pair convention is (BL, WL) - * The address sizes are the same across any element, - * just get it from the 1st element to save runtime - */ - vtr::vector> max_blwl_sizes_per_region; - max_blwl_sizes_per_region.resize(fabric_bitstream.num_regions()); - for (const FabricBitRegionId& region : fabric_bitstream.regions()) { - max_blwl_sizes_per_region[region].first = std::max(max_blwl_sizes_per_region[region].first, fabric_bits_per_region[region].begin()->second.size()); - max_blwl_sizes_per_region[region].second = std::max(max_blwl_sizes_per_region[region].second, fabric_bits_per_region[region].begin()->first.size()); + max_key_size = + std::max(max_key_size, fabric_bits_per_region_keys[region].size()); } - /* Combine the bitstream from different region into a unique one. Now we follow the convention: use (WL, BL) pairs */ + /* Find the BL/WL sizes per region; Pair convention is (BL, WL) + * The address sizes are the same across any element, + * just get it from the 1st element to save runtime + */ + vtr::vector> + max_blwl_sizes_per_region; + max_blwl_sizes_per_region.resize(fabric_bitstream.num_regions()); + for (const FabricBitRegionId& region : fabric_bitstream.regions()) { + max_blwl_sizes_per_region[region].first = + std::max(max_blwl_sizes_per_region[region].first, + fabric_bits_per_region[region].begin()->second.size()); + max_blwl_sizes_per_region[region].second = + std::max(max_blwl_sizes_per_region[region].second, + fabric_bits_per_region[region].begin()->first.size()); + } + + /* Combine the bitstream from different region into a unique one. Now we + * follow the convention: use (WL, BL) pairs */ MemoryBankFlattenFabricBitstream fabric_bits; for (size_t ikey = 0; ikey < max_key_size; ikey++) { /* Prepare the final BL/WL vectors to be added to the bitstream database */ std::vector cur_bl_vectors; std::vector cur_wl_vectors; for (const FabricBitRegionId& region : fabric_bitstream.regions()) { - /* If the key id is in bound for the key list in this region, find the BL and WL and add to the final bitstream database - * If the key id is out of bound for the key list in this region, we append an all-'x' string for both BL and WLs + /* If the key id is in bound for the key list in this region, find the BL + * and WL and add to the final bitstream database If the key id is out of + * bound for the key list in this region, we append an all-'x' string for + * both BL and WLs */ if (ikey < fabric_bits_per_region_keys[region].size()) { cur_wl_vectors.push_back(fabric_bits_per_region_keys[region][ikey]); - cur_bl_vectors.push_back(fabric_bits_per_region[region].at(fabric_bits_per_region_keys[region][ikey])); + cur_bl_vectors.push_back(fabric_bits_per_region[region].at( + fabric_bits_per_region_keys[region][ikey])); } else { - cur_wl_vectors.push_back(std::string(max_blwl_sizes_per_region[region].second, dont_care_bit)); - cur_bl_vectors.push_back(std::string(max_blwl_sizes_per_region[region].first, dont_care_bit)); + cur_wl_vectors.push_back( + std::string(max_blwl_sizes_per_region[region].second, dont_care_bit)); + cur_bl_vectors.push_back( + std::string(max_blwl_sizes_per_region[region].first, dont_care_bit)); } } /* Add the pair to std map */ @@ -354,13 +386,13 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons * vector 0: 000000001111101010 * vector 1: 00000011010101 * vector 2: 0010101111000110 - * + * * - Fill void in each vector with desired bits (Here assume fill 'x' * index ----------------------> * vector 0: 000000001111101010 * vector 1: 00000011010101xxxx * vector 2: 0010101111000110xx - * + * * - Rotate the array by 90 degree * index -----------------------> * vector 0: 000 @@ -368,22 +400,25 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons * vector 2: 001 * ... * vector N: 0xx - * + * *******************************************************************/ -static -std::vector reshape_bitstream_vectors_to_first_element(const std::vector& bitstream_vectors, - const char& default_bit_to_fill) { - /* Find the max sizes of BL bits, this determines the size of shift register chain */ +static std::vector reshape_bitstream_vectors_to_first_element( + const std::vector& bitstream_vectors, + const char& default_bit_to_fill) { + /* Find the max sizes of BL bits, this determines the size of shift register + * chain */ size_t max_vec_size = 0; for (const auto& vec : bitstream_vectors) { max_vec_size = std::max(max_vec_size, vec.size()); } /* Reshape the BL vectors */ - std::vector reshaped_vectors(bitstream_vectors.size(), std::string()); + std::vector reshaped_vectors(bitstream_vectors.size(), + std::string()); size_t col_cnt = 0; for (const auto& vec : bitstream_vectors) { reshaped_vectors[col_cnt] += vec; - reshaped_vectors[col_cnt] += std::string(max_vec_size - vec.size(), default_bit_to_fill); + reshaped_vectors[col_cnt] += + std::string(max_vec_size - vec.size(), default_bit_to_fill); col_cnt++; } @@ -394,23 +429,20 @@ std::vector reshape_bitstream_vectors_to_first_element(const std::v for (size_t icol = 0; icol < reshaped_vectors.size(); ++icol) { cur_vec.push_back(reshaped_vectors[icol][irow]); } - rotated_vectors.push_back(cur_vec); + rotated_vectors.push_back(cur_vec); } - + return rotated_vectors; } -/** @brief Split each BL vector in a configuration region into multiple shift register banks - * For example - * Original vector: 1xxx010xxx1 - * Resulting vector (2 register register banks): - * 1xxx0 - * 10xxx1 +/** @brief Split each BL vector in a configuration region into multiple shift + * register banks For example Original vector: 1xxx010xxx1 Resulting vector (2 + * register register banks): 1xxx0 10xxx1 */ -static -std::vector redistribute_bl_vectors_to_shift_register_banks(const std::vector bl_vectors, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const char& dont_care_bit) { +static std::vector redistribute_bl_vectors_to_shift_register_banks( + const std::vector bl_vectors, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const char& dont_care_bit) { std::vector multi_bank_bl_vec; /* Resize the vector by counting the dimension */ @@ -419,9 +451,9 @@ std::vector redistribute_bl_vectors_to_shift_register_banks(const s region_start_index.resize(blwl_sr_banks.regions().size(), 0); size_t total_num_banks = 0; for (const auto& region : blwl_sr_banks.regions()) { - region_start_index[region] = total_num_banks; + region_start_index[region] = total_num_banks; total_num_banks += blwl_sr_banks.bl_banks(region).size(); - } + } multi_bank_bl_vec.resize(total_num_banks); /* Resize each bank to be memory efficient */ @@ -439,10 +471,12 @@ std::vector redistribute_bl_vectors_to_shift_register_banks(const s for (size_t ibit = 0; ibit < region_bl_vec.size(); ++ibit) { /* Find the shift register bank id and the offset in data lines */ BasicPort bl_port(std::string(MEMORY_BL_PORT_NAME), ibit, ibit); - FabricBitLineBankId bank_id = blwl_sr_banks.find_bl_shift_register_bank_id(region, bl_port); - BasicPort sr_port = blwl_sr_banks.find_bl_shift_register_bank_data_port(region, bl_port); + FabricBitLineBankId bank_id = + blwl_sr_banks.find_bl_shift_register_bank_id(region, bl_port); + BasicPort sr_port = + blwl_sr_banks.find_bl_shift_register_bank_data_port(region, bl_port); VTR_ASSERT(1 == sr_port.get_width()); - + size_t vec_index = region_start_index[region] + size_t(bank_id); multi_bank_bl_vec[vec_index][sr_port.get_lsb()] = region_bl_vec[ibit]; } @@ -451,17 +485,14 @@ std::vector redistribute_bl_vectors_to_shift_register_banks(const s return multi_bank_bl_vec; } -/** @brief Split each WL vector in a configuration region into multiple shift register banks - * For example - * Original vector: 1xxx010xxx1 - * Resulting vector (2 register register banks): - * 1xxx0 - * 10xxx1 +/** @brief Split each WL vector in a configuration region into multiple shift + * register banks For example Original vector: 1xxx010xxx1 Resulting vector (2 + * register register banks): 1xxx0 10xxx1 */ -static -std::vector redistribute_wl_vectors_to_shift_register_banks(const std::vector wl_vectors, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const char& dont_care_bit) { +static std::vector redistribute_wl_vectors_to_shift_register_banks( + const std::vector wl_vectors, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const char& dont_care_bit) { std::vector multi_bank_wl_vec; /* Resize the vector by counting the dimension */ @@ -470,9 +501,9 @@ std::vector redistribute_wl_vectors_to_shift_register_banks(const s region_start_index.resize(blwl_sr_banks.regions().size(), 0); size_t total_num_banks = 0; for (const auto& region : blwl_sr_banks.regions()) { - region_start_index[region] = total_num_banks; + region_start_index[region] = total_num_banks; total_num_banks += blwl_sr_banks.wl_banks(region).size(); - } + } multi_bank_wl_vec.resize(total_num_banks); /* Resize each bank to be memory efficient */ @@ -490,10 +521,12 @@ std::vector redistribute_wl_vectors_to_shift_register_banks(const s for (size_t ibit = 0; ibit < region_wl_vec.size(); ++ibit) { /* Find the shift register bank id and the offset in data lines */ BasicPort wl_port(std::string(MEMORY_WL_PORT_NAME), ibit, ibit); - FabricWordLineBankId bank_id = blwl_sr_banks.find_wl_shift_register_bank_id(region, wl_port); - BasicPort sr_port = blwl_sr_banks.find_wl_shift_register_bank_data_port(region, wl_port); + FabricWordLineBankId bank_id = + blwl_sr_banks.find_wl_shift_register_bank_id(region, wl_port); + BasicPort sr_port = + blwl_sr_banks.find_wl_shift_register_bank_data_port(region, wl_port); VTR_ASSERT(1 == sr_port.get_width()); - + size_t vec_index = region_start_index[region] + size_t(bank_id); multi_bank_wl_vec[vec_index][sr_port.get_lsb()] = region_wl_vec[ibit]; } @@ -502,41 +535,56 @@ std::vector redistribute_wl_vectors_to_shift_register_banks(const s return multi_bank_wl_vec; } -MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const char& dont_care_bit) { - vtr::ScopedStartFinishTimer timer("Reshape fabric bitstream for memory bank using shift registers"); - MemoryBankFlattenFabricBitstream raw_fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip, dont_care_bit); - MemoryBankShiftRegisterFabricBitstream fabric_bits; +MemoryBankShiftRegisterFabricBitstream +build_memory_bank_shift_register_fabric_bitstream( + const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const bool& fast_configuration, const bool& bit_value_to_skip, + const char& dont_care_bit) { + vtr::ScopedStartFinishTimer timer( + "Reshape fabric bitstream for memory bank using shift registers"); + MemoryBankFlattenFabricBitstream raw_fabric_bits = + build_memory_bank_flatten_fabric_bitstream( + fabric_bitstream, fast_configuration, bit_value_to_skip, dont_care_bit); + MemoryBankShiftRegisterFabricBitstream fabric_bits; - /* Iterate over each word */ + /* Iterate over each word */ for (const auto& wl_vec : raw_fabric_bits.wl_vectors()) { std::vector bl_vec = raw_fabric_bits.bl_vector(wl_vec); - MemoryBankShiftRegisterFabricBitstreamWordId word_id = fabric_bits.create_word(); + MemoryBankShiftRegisterFabricBitstreamWordId word_id = + fabric_bits.create_word(); /* Redistribute the BL vector to multiple banks */ - std::vector multi_bank_bl_vec = redistribute_bl_vectors_to_shift_register_banks(bl_vec, blwl_sr_banks, dont_care_bit); + std::vector multi_bank_bl_vec = + redistribute_bl_vectors_to_shift_register_banks(bl_vec, blwl_sr_banks, + dont_care_bit); - std::vector reshaped_bl_vectors = reshape_bitstream_vectors_to_first_element(multi_bank_bl_vec, dont_care_bit); - /* Reverse the vectors due to the shift register chain nature: first-in first-out */ + std::vector reshaped_bl_vectors = + reshape_bitstream_vectors_to_first_element(multi_bank_bl_vec, + dont_care_bit); + /* Reverse the vectors due to the shift register chain nature: first-in + * first-out */ std::reverse(reshaped_bl_vectors.begin(), reshaped_bl_vectors.end()); /* Add the BL word to final bitstream */ for (const auto& reshaped_bl_vec : reshaped_bl_vectors) { - fabric_bits.add_bl_vectors(word_id, reshaped_bl_vec); + fabric_bits.add_bl_vectors(word_id, reshaped_bl_vec); } /* Redistribute the WL vector to multiple banks */ - std::vector multi_bank_wl_vec = redistribute_wl_vectors_to_shift_register_banks(wl_vec, blwl_sr_banks, dont_care_bit); + std::vector multi_bank_wl_vec = + redistribute_wl_vectors_to_shift_register_banks(wl_vec, blwl_sr_banks, + dont_care_bit); - std::vector reshaped_wl_vectors = reshape_bitstream_vectors_to_first_element(multi_bank_wl_vec, dont_care_bit); - /* Reverse the vectors due to the shift register chain nature: first-in first-out */ + std::vector reshaped_wl_vectors = + reshape_bitstream_vectors_to_first_element(multi_bank_wl_vec, + dont_care_bit); + /* Reverse the vectors due to the shift register chain nature: first-in + * first-out */ std::reverse(reshaped_wl_vectors.begin(), reshaped_wl_vectors.end()); /* Add the BL word to final bitstream */ for (const auto& reshaped_wl_vec : reshaped_wl_vectors) { - fabric_bits.add_wl_vectors(word_id, reshaped_wl_vec); + fabric_bits.add_wl_vectors(word_id, reshaped_wl_vec); } } @@ -545,27 +593,23 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b /******************************************************************** * For fast configuration, the number of bits to be skipped - * the rule to skip any configuration bit should consider the whole data input values. - * Only all the bits in the din port match the value to be skipped, - * the programming cycle can be skipped! - * For example: - * BL Address: 010101 - * WL Address: 010101 - * Region 0: 0 - * Region 1: 1 - * Region 2: 0 - * This bit cannot be skipped if the bit_value_to_skip is 0 + * the rule to skip any configuration bit should consider the whole data input + *values. Only all the bits in the din port match the value to be skipped, the + *programming cycle can be skipped! For example: BL Address: 010101 WL Address: + *010101 Region 0: 0 Region 1: 1 Region 2: 0 This bit cannot be skipped if the + *bit_value_to_skip is 0 * * BL Address: 010101 * WL Address: 010101 * Region 0: 0 - * Region 1: 0 - * Region 2: 0 + * Region 1: 0 + * Region 2: 0 * This bit can be skipped if the bit_value_to_skip is 0 *******************************************************************/ -size_t find_memory_bank_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream, - const bool& bit_value_to_skip) { - MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); +size_t find_memory_bank_fast_configuration_fabric_bitstream_size( + const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip) { + MemoryBankFabricBitstream fabric_bits_by_addr = + build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); size_t num_bits = 0; diff --git a/openfpga/src/utils/fabric_bitstream_utils.h b/openfpga/src/utils/fabric_bitstream_utils.h index 3cb1285bb..fe8b0b9e6 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.h +++ b/openfpga/src/utils/fabric_bitstream_utils.h @@ -7,14 +7,15 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include -#include #include +#include +#include + #include "bitstream_manager.h" +#include "fabric_bitstream.h" #include "memory_bank_flatten_fabric_bitstream.h" #include "memory_bank_shift_register_banks.h" #include "memory_bank_shift_register_fabric_bitstream.h" -#include "fabric_bitstream.h" /******************************************************************** * Function declaration @@ -23,89 +24,97 @@ /* begin namespace openfpga */ namespace openfpga { -size_t find_fabric_regional_bitstream_max_size(const FabricBitstream& fabric_bitstream); +size_t find_fabric_regional_bitstream_max_size( + const FabricBitstream& fabric_bitstream); -size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped(const FabricBitstream& fabric_bitstream, - const BitstreamManager& bitstream_manager, - const bool& bit_value_to_skip); +size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped( + const FabricBitstream& fabric_bitstream, + const BitstreamManager& bitstream_manager, const bool& bit_value_to_skip); -/* Alias to a specific organization of bitstreams for frame-based configuration protocol */ +/* Alias to a specific organization of bitstreams for frame-based configuration + * protocol */ typedef std::vector> ConfigChainFabricBitstream; -ConfigChainFabricBitstream build_config_chain_fabric_bitstream_by_region(const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream); +ConfigChainFabricBitstream build_config_chain_fabric_bitstream_by_region( + const BitstreamManager& bitstream_manager, + const FabricBitstream& fabric_bitstream); -/* Alias to a specific organization of bitstreams for frame-based configuration protocol */ +/* Alias to a specific organization of bitstreams for frame-based configuration + * protocol */ typedef std::map> FrameFabricBitstream; -FrameFabricBitstream build_frame_based_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream); +FrameFabricBitstream build_frame_based_fabric_bitstream_by_address( + const FabricBitstream& fabric_bitstream); -size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream, - const bool& bit_value_to_skip); +size_t find_frame_based_fast_configuration_fabric_bitstream_size( + const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip); /******************************************************************** - * @ brief Reorganize the fabric bitstream for memory banks which use flatten BL and WLs - * For each configuration region, we will merge BL address (which are 1-hot codes) under the same WL address + * @ brief Reorganize the fabric bitstream for memory banks which use flatten BL + *and WLs For each configuration region, we will merge BL address (which are + *1-hot codes) under the same WL address * * Quick Example * _ _ * An example: * 010_111 000_101 * - * Note that all the BL/WLs across configuration regions are independent. We will combine them together - * Quick Example - * _ _ - * 001_010 000_000 - * 100_100 000_000 - * + * Note that all the BL/WLs across configuration regions are independent. We + *will combine them together Quick Example _ _ 001_010 000_000 100_100 000_000 + * * the bitstream will be merged as * 101_110 000_000 * - * @note the std::map may cause large memory footprint for large bitstream databases! + * @note the std::map may cause large memory footprint for large bitstream + *databases! *******************************************************************/ -MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const char& dont_care_bit = 'x'); +MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream( + const FabricBitstream& fabric_bitstream, const bool& fast_configuration, + const bool& bit_value_to_skip, const char& dont_care_bit = 'x'); /******************************************************************** - * @ brief Reorganize the fabric bitstream for memory banks which use shift register to manipulate BL and WLs - * For each configuration region, we will merge BL address (which are 1-hot codes) under the same WL address + * @ brief Reorganize the fabric bitstream for memory banks which use shift + *register to manipulate BL and WLs For each configuration region, we will merge + *BL address (which are 1-hot codes) under the same WL address * * Quick Example * _ _ * An example: * 010_111 000_101 * - * Note that all the BL/WLs across configuration regions are independent. We will combine them together - * Quick Example - * _ _ - * 001_010 000_000 - * 100_100 000_000 - * + * Note that all the BL/WLs across configuration regions are independent. We + *will combine them together Quick Example _ _ 001_010 000_000 100_100 000_000 + * * the bitstream will be merged as * 101_110 000_000 * - * Because that the BL/WL are loaded through shift registers (perhaps using multiple heads), the bitstream will be reorganized as - * Considering single head: - * + * Because that the BL/WL are loaded through shift registers (perhaps using + *multiple heads), the bitstream will be reorganized as Considering single head: + * * _ _ * 1_1 0_0 * 0_1 0_0 - * 1_0 0_0 + * 1_0 0_0 * - * @note the std::map may cause large memory footprint for large bitstream databases! + * @note the std::map may cause large memory footprint for large bitstream + *databases! *******************************************************************/ -MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const char& dont_care_bit = 'x'); +MemoryBankShiftRegisterFabricBitstream +build_memory_bank_shift_register_fabric_bitstream( + const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const bool& fast_configuration, const bool& bit_value_to_skip, + const char& dont_care_bit = 'x'); -/* Alias to a specific organization of bitstreams for memory bank configuration protocol */ -typedef std::map, std::vector> MemoryBankFabricBitstream; -MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream); +/* Alias to a specific organization of bitstreams for memory bank configuration + * protocol */ +typedef std::map, std::vector> + MemoryBankFabricBitstream; +MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address( + const FabricBitstream& fabric_bitstream); -size_t find_memory_bank_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream, - const bool& bit_value_to_skip); +size_t find_memory_bank_fast_configuration_fabric_bitstream_size( + const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/fabric_global_port_info_utils.cpp b/openfpga/src/utils/fabric_global_port_info_utils.cpp index 9fbd707c5..533df628f 100644 --- a/openfpga/src/utils/fabric_global_port_info_utils.cpp +++ b/openfpga/src/utils/fabric_global_port_info_utils.cpp @@ -8,29 +8,31 @@ #include /* Headers from vtrutil library */ +#include "fabric_global_port_info_utils.h" +#include "openfpga_naming.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "openfpga_naming.h" - -#include "fabric_global_port_info_utils.h" - /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * Identify global reset ports for programming + * Identify global reset ports for programming *******************************************************************/ -std::vector find_fabric_global_programming_reset_ports(const FabricGlobalPortInfo& fabric_global_port_info) { +std::vector find_fabric_global_programming_reset_ports( + const FabricGlobalPortInfo& fabric_global_port_info) { /* Try to find global reset ports for programming */ std::vector global_prog_reset_ports; - for (const FabricGlobalPortId& global_port : fabric_global_port_info.global_ports()) { + for (const FabricGlobalPortId& global_port : + fabric_global_port_info.global_ports()) { if (false == fabric_global_port_info.global_port_is_prog(global_port)) { continue; } - VTR_ASSERT(true == fabric_global_port_info.global_port_is_prog(global_port)); - VTR_ASSERT( (false == fabric_global_port_info.global_port_is_reset(global_port)) - || (false == fabric_global_port_info.global_port_is_set(global_port))); + VTR_ASSERT(true == + fabric_global_port_info.global_port_is_prog(global_port)); + VTR_ASSERT( + (false == fabric_global_port_info.global_port_is_reset(global_port)) || + (false == fabric_global_port_info.global_port_is_set(global_port))); if (true == fabric_global_port_info.global_port_is_reset(global_port)) { global_prog_reset_ports.push_back(global_port); } @@ -40,18 +42,22 @@ std::vector find_fabric_global_programming_reset_ports(const } /******************************************************************** - * Identify global set ports for programming + * Identify global set ports for programming *******************************************************************/ -std::vector find_fabric_global_programming_set_ports(const FabricGlobalPortInfo& fabric_global_port_info) { +std::vector find_fabric_global_programming_set_ports( + const FabricGlobalPortInfo& fabric_global_port_info) { /* Try to find global set ports for programming */ std::vector global_prog_set_ports; - for (const FabricGlobalPortId& global_port : fabric_global_port_info.global_ports()) { + for (const FabricGlobalPortId& global_port : + fabric_global_port_info.global_ports()) { if (false == fabric_global_port_info.global_port_is_prog(global_port)) { continue; } - VTR_ASSERT(true == fabric_global_port_info.global_port_is_prog(global_port)); - VTR_ASSERT( (false == fabric_global_port_info.global_port_is_reset(global_port)) - || (false == fabric_global_port_info.global_port_is_set(global_port))); + VTR_ASSERT(true == + fabric_global_port_info.global_port_is_prog(global_port)); + VTR_ASSERT( + (false == fabric_global_port_info.global_port_is_reset(global_port)) || + (false == fabric_global_port_info.global_port_is_set(global_port))); if (true == fabric_global_port_info.global_port_is_set(global_port)) { global_prog_set_ports.push_back(global_port); } @@ -64,22 +70,29 @@ std::vector find_fabric_global_programming_set_ports(const F * Identify if a port is in the list of fabric global port * and its functionality is a reset port which is not used for programming FPGAs *******************************************************************/ -bool port_is_fabric_global_reset_port(const FabricGlobalPortInfo& fabric_global_port_info, - const ModuleManager& module_manager, - const BasicPort& port) { - /* Find the top_module: the fabric global ports are always part of the ports of the top module */ - ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name()); +bool port_is_fabric_global_reset_port( + const FabricGlobalPortInfo& fabric_global_port_info, + const ModuleManager& module_manager, const BasicPort& port) { + /* Find the top_module: the fabric global ports are always part of the ports + * of the top module */ + ModuleId top_module = + module_manager.find_module(generate_fpga_top_module_name()); VTR_ASSERT(true == module_manager.valid_module_id(top_module)); - for (const FabricGlobalPortId& fabric_global_port_id : fabric_global_port_info.global_ports()) { - if ( (false == fabric_global_port_info.global_port_is_reset(fabric_global_port_id)) - || (true == fabric_global_port_info.global_port_is_prog(fabric_global_port_id))) { + for (const FabricGlobalPortId& fabric_global_port_id : + fabric_global_port_info.global_ports()) { + if ((false == + fabric_global_port_info.global_port_is_reset(fabric_global_port_id)) || + (true == + fabric_global_port_info.global_port_is_prog(fabric_global_port_id))) { continue; } - BasicPort module_global_port = module_manager.module_port(top_module, fabric_global_port_info.global_module_port(fabric_global_port_id)); - if ( (true == module_global_port.mergeable(port)) - && (true == module_global_port.contained(port)) ) { + BasicPort module_global_port = module_manager.module_port( + top_module, + fabric_global_port_info.global_module_port(fabric_global_port_id)); + if ((true == module_global_port.mergeable(port)) && + (true == module_global_port.contained(port))) { return true; } } @@ -90,17 +103,22 @@ bool port_is_fabric_global_reset_port(const FabricGlobalPortInfo& fabric_global_ /******************************************************************** * Find a global port with a given name *******************************************************************/ -FabricGlobalPortId find_fabric_global_port(const FabricGlobalPortInfo& fabric_global_port_info, - const ModuleManager& module_manager, - const BasicPort& port) { - /* Find the top_module: the fabric global ports are always part of the ports of the top module */ - ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name()); +FabricGlobalPortId find_fabric_global_port( + const FabricGlobalPortInfo& fabric_global_port_info, + const ModuleManager& module_manager, const BasicPort& port) { + /* Find the top_module: the fabric global ports are always part of the ports + * of the top module */ + ModuleId top_module = + module_manager.find_module(generate_fpga_top_module_name()); VTR_ASSERT(true == module_manager.valid_module_id(top_module)); - for (const FabricGlobalPortId& fabric_global_port_id : fabric_global_port_info.global_ports()) { - BasicPort module_global_port = module_manager.module_port(top_module, fabric_global_port_info.global_module_port(fabric_global_port_id)); - if ( (true == module_global_port.mergeable(port)) - && (true == module_global_port.contained(port)) ) { + for (const FabricGlobalPortId& fabric_global_port_id : + fabric_global_port_info.global_ports()) { + BasicPort module_global_port = module_manager.module_port( + top_module, + fabric_global_port_info.global_module_port(fabric_global_port_id)); + if ((true == module_global_port.mergeable(port)) && + (true == module_global_port.contained(port))) { return fabric_global_port_id; } } diff --git a/openfpga/src/utils/fabric_global_port_info_utils.h b/openfpga/src/utils/fabric_global_port_info_utils.h index 99611bc8b..5fd300337 100644 --- a/openfpga/src/utils/fabric_global_port_info_utils.h +++ b/openfpga/src/utils/fabric_global_port_info_utils.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include + #include "fabric_global_port_info.h" #include "module_manager.h" @@ -15,17 +16,19 @@ /* begin namespace openfpga */ namespace openfpga { -std::vector find_fabric_global_programming_reset_ports(const FabricGlobalPortInfo& fabric_global_port_info); +std::vector find_fabric_global_programming_reset_ports( + const FabricGlobalPortInfo& fabric_global_port_info); -std::vector find_fabric_global_programming_set_ports(const FabricGlobalPortInfo& fabric_global_port_info); +std::vector find_fabric_global_programming_set_ports( + const FabricGlobalPortInfo& fabric_global_port_info); -bool port_is_fabric_global_reset_port(const FabricGlobalPortInfo& fabric_global_port_info, - const ModuleManager& module_manager, - const BasicPort& port); +bool port_is_fabric_global_reset_port( + const FabricGlobalPortInfo& fabric_global_port_info, + const ModuleManager& module_manager, const BasicPort& port); -FabricGlobalPortId find_fabric_global_port(const FabricGlobalPortInfo& fabric_global_port_info, - const ModuleManager& module_manager, - const BasicPort& port); +FabricGlobalPortId find_fabric_global_port( + const FabricGlobalPortInfo& fabric_global_port_info, + const ModuleManager& module_manager, const BasicPort& port); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/lut_utils.cpp b/openfpga/src/utils/lut_utils.cpp index bcf3703f9..def2fe742 100644 --- a/openfpga/src/utils/lut_utils.cpp +++ b/openfpga/src/utils/lut_utils.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * This file includes most utilized functions to manipulate LUTs, + * This file includes most utilized functions to manipulate LUTs, * especially their truth tables, in the OpenFPGA context *******************************************************************/ #include @@ -9,34 +9,33 @@ #include "vtr_log.h" /* Headers from openfpgautil library */ -#include "openfpga_decode.h" - #include "lut_utils.h" +#include "openfpga_decode.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * This function aims to adapt the truth table to a mapped physical LUT + * This function aims to adapt the truth table to a mapped physical LUT * subject to a pin rotation map * The modification is applied to line by line * - For unused inputs : insert dont care - * - For used inputs : find the bit in the truth table rows and move it by the given mapping + * - For used inputs : find the bit in the truth table rows and move it by the + *given mapping * * The rotated pin map is the reference to adapt the truth table. - * Each element of the map represents the input index in the original truth table - * The sequence of the rotate pin map is the final sequence of how - * each line of the original truth table should be shuffled - * Example: - * output_value(we do not modify) + * Each element of the map represents the input index in the original truth + *table The sequence of the rotate pin map is the final sequence of how each + *line of the original truth table should be shuffled Example: output_value(we + *do not modify) * | * v * Truth table line: 00111 * rotated_pin_map: 2310 - * Adapt truth table line: 11001 + * Adapt truth table line: 11001 + * + * An illustrative example: * - * An illustrative example: - * * Original Truth Table Post VPR Truth Table * * +-------+ +-------+ @@ -50,8 +49,9 @@ namespace openfpga { * 01 1 10 1 * *******************************************************************/ -AtomNetlist::TruthTable lut_truth_table_adaption(const AtomNetlist::TruthTable& orig_tt, - const std::vector& rotated_pin_map) { +AtomNetlist::TruthTable lut_truth_table_adaption( + const AtomNetlist::TruthTable& orig_tt, + const std::vector& rotated_pin_map) { AtomNetlist::TruthTable tt; for (auto row : orig_tt) { @@ -62,12 +62,12 @@ AtomNetlist::TruthTable lut_truth_table_adaption(const AtomNetlist::TruthTable& for (size_t i = 0; i < rotated_pin_map.size(); ++i) { if (-1 == rotated_pin_map[i]) { tt_line.push_back(vtr::LogicValue::DONT_CARE); - } else { + } else { /* Ensure we never access the last digit, i.e., the output value! */ VTR_ASSERT((size_t)rotated_pin_map[i] < row.size() - 1); tt_line.push_back(row[rotated_pin_map[i]]); } - } + } /* Do not miss the last digit in the final result */ tt_line.push_back(row.back()); @@ -75,12 +75,13 @@ AtomNetlist::TruthTable lut_truth_table_adaption(const AtomNetlist::TruthTable& } return tt; -} +} /******************************************************************** * Convert a truth table to strings, which are ready to be printed out *******************************************************************/ -std::vector truth_table_to_string(const AtomNetlist::TruthTable& tt) { +std::vector truth_table_to_string( + const AtomNetlist::TruthTable& tt) { std::vector tt_str; for (auto row : tt) { std::string row_str; @@ -110,9 +111,9 @@ std::vector truth_table_to_string(const AtomNetlist::TruthTable& tt } /******************************************************************** - * Adapt the truth table from the short-wire connection + * Adapt the truth table from the short-wire connection * from the input nets of a LUT to an output of a LUT - * + * * LUT * +-------------+ * lut_input--->|----+ | @@ -124,26 +125,26 @@ std::vector truth_table_to_string(const AtomNetlist::TruthTable& tt * In this case, LUT is configured as a wiring module * This function will generate a truth for the wiring LUT * - * For example: - * The truth table of the case where the 3rd input of - * a 4-input LUT is wired to output - * + * For example: + * The truth table of the case where the 3rd input of + * a 4-input LUT is wired to output + * * --1- 1 - * + * ********************************************************************/ -AtomNetlist::TruthTable build_wired_lut_truth_table(const size_t& lut_size, - const size_t& wire_input_id) { +AtomNetlist::TruthTable build_wired_lut_truth_table( + const size_t& lut_size, const size_t& wire_input_id) { AtomNetlist::TruthTable tt; - + /* There is always only one line in this truth table */ tt.resize(1); - /* Pre-allocate the truth table: + /* Pre-allocate the truth table: * Each truth table line is organized in BLIF format: * |<---LUT size--->| * < a string of 0 or 1> <0 or 1> - * The first of characters represent the input values of each LUT input - * Here, we add 2 characters, which denote the space and a digit (0|1) + * The first of characters represent the input values of each LUT + * input Here, we add 2 characters, which denote the space and a digit (0|1) * By default, we set all the inputs as don't care value '-' * * For more details, please refer to the BLIF format documentation @@ -151,7 +152,7 @@ AtomNetlist::TruthTable build_wired_lut_truth_table(const size_t& lut_size, tt[0].resize(lut_size, vtr::LogicValue::DONT_CARE); /* Fill the truth table !!! */ VTR_ASSERT(wire_input_id < lut_size); - tt[0][wire_input_id] = vtr::LogicValue::TRUE; + tt[0][wire_input_id] = vtr::LogicValue::TRUE; tt[0].push_back(vtr::LogicValue::TRUE); return tt; @@ -160,11 +161,12 @@ AtomNetlist::TruthTable build_wired_lut_truth_table(const size_t& lut_size, /******************************************************************** * Adapt truth table for a fracturable LUT * Determine fixed input bits for this truth table: - * 1. input bits within frac_level (all '-' if not specified) - * 2. input bits outside frac_level, decoded to its output mask (0 -> first part -> all '1') + * 1. input bits within frac_level (all '-' if not specified) + * 2. input bits outside frac_level, decoded to its output mask (0 -> first part + *-> all '1') * - * For example: - * A 4-input function is mapped to input[0..3] of a 6-input fracturable LUT + * For example: + * A 4-input function is mapped to input[0..3] of a 6-input fracturable LUT * Plus, it uses the 2nd output of the fracturable LUT * The truth table of the 4-input function is * 1001 1 @@ -172,17 +174,15 @@ AtomNetlist::TruthTable build_wired_lut_truth_table(const size_t& lut_size, * Therefore, it must be adapted by adding mask bits, which are * a number of fixed digits to configure the fracturable LUT to * operate in a 4-input LUT mode - * The mask bits can be decoded from the index of output used in the fracturable LUT - * For the 2nd output, it will be '01', the binary representation of index '1' - * Now the truth table will be adapt to - * 100101 1 - * where the first 4 digits come from the original truth table - * the 2 following digits are mask bits - * + * The mask bits can be decoded from the index of output used in the + *fracturable LUT For the 2nd output, it will be '01', the binary representation + *of index '1' Now the truth table will be adapt to 100101 1 where the first 4 + *digits come from the original truth table the 2 following digits are mask bits + * ********************************************************************/ -AtomNetlist::TruthTable adapt_truth_table_for_frac_lut(const size_t& lut_frac_level, - const size_t& lut_output_mask, - const AtomNetlist::TruthTable& truth_table) { +AtomNetlist::TruthTable adapt_truth_table_for_frac_lut( + const size_t& lut_frac_level, const size_t& lut_output_mask, + const AtomNetlist::TruthTable& truth_table) { /* No adaption required for when the lut_frac_level is not set */ if (size_t(OPEN) == lut_frac_level) { return truth_table; @@ -198,23 +198,23 @@ AtomNetlist::TruthTable adapt_truth_table_for_frac_lut(const size_t& lut_frac_le int num_mask_bits = lut_size - lut_frac_level; /* Check if we need to modify any bits */ VTR_ASSERT(0 <= num_mask_bits); - if ( 0 == num_mask_bits ) { + if (0 == num_mask_bits) { /* No modification needed, push to adapted truth table */ adapt_truth_table.push_back(tt_line); continue; } /* Modify bits starting from lut_frac_level */ - /* Decode the lut_output_mask to LUT input codes */ + /* Decode the lut_output_mask to LUT input codes */ int temp = pow(2., num_mask_bits) - 1 - lut_output_mask; VTR_ASSERT(0 <= temp); std::vector mask_bits_vec = itobin_vec(temp, num_mask_bits); /* Copy the bits to the truth table line */ std::vector adapt_tt_line = tt_line; - for (size_t itt = lut_frac_level; itt < lut_frac_level + mask_bits_vec.size(); ++itt) { - + for (size_t itt = lut_frac_level; + itt < lut_frac_level + mask_bits_vec.size(); ++itt) { vtr::LogicValue logic_val = vtr::LogicValue::FALSE; - VTR_ASSERT( (1 == mask_bits_vec[itt - lut_frac_level]) - || (0 == mask_bits_vec[itt - lut_frac_level]) ); + VTR_ASSERT((1 == mask_bits_vec[itt - lut_frac_level]) || + (0 == mask_bits_vec[itt - lut_frac_level])); if (1 == mask_bits_vec[itt - lut_frac_level]) { logic_val = vtr::LogicValue::TRUE; } @@ -239,23 +239,23 @@ bool lut_truth_table_use_on_set(const AtomNetlist::TruthTable& truth_table) { for (const std::vector& tt_line : truth_table) { switch (tt_line.back()) { - case vtr::LogicValue::TRUE : - on_set = true; - break; - case vtr::LogicValue::FALSE : - off_set = true; - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid truth_table_line ending '%s'!\n", - vtr::LOGIC_VALUE_STRING[size_t(tt_line.back())]); - exit(1); + case vtr::LogicValue::TRUE: + on_set = true; + break; + case vtr::LogicValue::FALSE: + off_set = true; + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid truth_table_line ending '%s'!\n", + vtr::LOGIC_VALUE_STRING[size_t(tt_line.back())]); + exit(1); } } /* Prefer on_set if both are true */ if (true == on_set && true == off_set) { - on_set = true; + on_set = true; off_set = false; } VTR_ASSERT(on_set == !off_set); @@ -270,18 +270,17 @@ bool lut_truth_table_use_on_set(const AtomNetlist::TruthTable& truth_table) { * So, in truth table line, there may be 10- 1 * In this case, we should complete it by --10- 1 *******************************************************************/ -static -std::vector complete_truth_table_line(const size_t& lut_size, - const std::vector& tt_line) { +static std::vector complete_truth_table_line( + const size_t& lut_size, const std::vector& tt_line) { std::vector ret; VTR_ASSERT(0 < tt_line.size()); /* Complete the truth table line*/ - size_t cover_len = tt_line.size() - 1; + size_t cover_len = tt_line.size() - 1; VTR_ASSERT(cover_len <= lut_size); - /* Copy the original truth table line */ + /* Copy the original truth table line */ ret = tt_line; /* Kick out the last value for now as it is the output value */ ret.pop_back(); @@ -291,12 +290,12 @@ std::vector complete_truth_table_line(const size_t& lut_size, ret.push_back(vtr::LogicValue::DONT_CARE); } - /* Copy the original truth table line */ + /* Copy the original truth table line */ ret.push_back(tt_line.back()); /* Check if the size of ret matches our expectation */ VTR_ASSERT(lut_size + 1 == ret.size()); - + return ret; } @@ -306,19 +305,17 @@ std::vector complete_truth_table_line(const size_t& lut_size, * Start_point: the position we start converting don't care sign '-' * to explicit '0' or '1' *******************************************************************/ -static -void rec_build_lut_bitstream_per_line(std::vector& lut_bitstream, - const size_t& lut_size, - const std::vector& tt_line, - const size_t& start_point) { +static void rec_build_lut_bitstream_per_line( + std::vector& lut_bitstream, const size_t& lut_size, + const std::vector& tt_line, const size_t& start_point) { std::vector temp_line = tt_line; /* Check the length of sram bits and truth table line */ VTR_ASSERT(lut_size + 1 == tt_line.size()); /* lut_size + '1|0' */ - /* End of truth_table_line should be "space" and "1" */ - VTR_ASSERT( (vtr::LogicValue::TRUE == tt_line.back()) - || (vtr::LogicValue::FALSE == tt_line.back()) ); + /* End of truth_table_line should be "space" and "1" */ + VTR_ASSERT((vtr::LogicValue::TRUE == tt_line.back()) || + (vtr::LogicValue::FALSE == tt_line.back())); /* Make sure before start point there is no '-' */ VTR_ASSERT(start_point < tt_line.size()); @@ -331,12 +328,14 @@ void rec_build_lut_bitstream_per_line(std::vector& lut_bitstream, if (vtr::LogicValue::DONT_CARE == tt_line[i]) { /* if we find a dont_care, we don't do configure now but recursively*/ /* '0' branch */ - temp_line[i] = vtr::LogicValue::FALSE; - rec_build_lut_bitstream_per_line(lut_bitstream, lut_size, temp_line, start_point + 1); + temp_line[i] = vtr::LogicValue::FALSE; + rec_build_lut_bitstream_per_line(lut_bitstream, lut_size, temp_line, + start_point + 1); /* '1' branch */ - temp_line[i] = vtr::LogicValue::TRUE; - rec_build_lut_bitstream_per_line(lut_bitstream, lut_size, temp_line, start_point + 1); - return; + temp_line[i] = vtr::LogicValue::TRUE; + rec_build_lut_bitstream_per_line(lut_bitstream, lut_size, temp_line, + start_point + 1); + return; } } @@ -346,19 +345,19 @@ void rec_build_lut_bitstream_per_line(std::vector& lut_bitstream, for (size_t i = 0; i < lut_size; ++i) { /* Should be either '0' or '1' */ switch (tt_line[i]) { - case vtr::LogicValue::FALSE : - /* We assume the 1-lut pass sram1 when input = 0 */ - sram_id += (size_t)pow(2., (double)(i)); - break; - case vtr::LogicValue::TRUE : - /* We assume the 1-lut pass sram0 when input = 1 */ - break; - case vtr::LogicValue::DONT_CARE : - default : - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid truth_table bit '%s', should be [0|1|]!\n", - vtr::LOGIC_VALUE_STRING[size_t(tt_line[i])]); - exit(1); + case vtr::LogicValue::FALSE: + /* We assume the 1-lut pass sram1 when input = 0 */ + sram_id += (size_t)pow(2., (double)(i)); + break; + case vtr::LogicValue::TRUE: + /* We assume the 1-lut pass sram0 when input = 1 */ + break; + case vtr::LogicValue::DONT_CARE: + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid truth_table bit '%s', should be [0|1|]!\n", + vtr::LOGIC_VALUE_STRING[size_t(tt_line[i])]); + exit(1); } } /* Set the sram bit to '1'*/ @@ -368,7 +367,7 @@ void rec_build_lut_bitstream_per_line(std::vector& lut_bitstream, } else if (vtr::LogicValue::FALSE == tt_line.back()) { lut_bitstream[sram_id] = false; /* off set */ } else { - VTR_LOGF_ERROR(__FILE__, __LINE__, + VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid truth_table_line ending '%s'!\n", vtr::LOGIC_VALUE_STRING[size_t(tt_line.back())]); exit(1); @@ -377,14 +376,13 @@ void rec_build_lut_bitstream_per_line(std::vector& lut_bitstream, /******************************************************************** * Generate the bitstream for a single-output LUT with a given truth table - * As truth tables may come from different logic blocks, truth tables could be in on and off sets - * We first build a base SRAM bits, where different parts are set to tbe on/off sets - * Then, we can decode SRAM bits as regular process + * As truth tables may come from different logic blocks, truth tables could be + *in on and off sets We first build a base SRAM bits, where different parts are + *set to tbe on/off sets Then, we can decode SRAM bits as regular process *******************************************************************/ -static -std::vector build_single_output_lut_bitstream(const AtomNetlist::TruthTable& truth_table, - const MuxGraph& lut_mux_graph, - const size_t& default_sram_bit_value) { +static std::vector build_single_output_lut_bitstream( + const AtomNetlist::TruthTable& truth_table, const MuxGraph& lut_mux_graph, + const size_t& default_sram_bit_value) { size_t lut_size = lut_mux_graph.num_memory_bits(); size_t bitstream_size = lut_mux_graph.num_inputs(); std::vector lut_bitstream(bitstream_size, false); @@ -395,19 +393,19 @@ std::vector build_single_output_lut_bitstream(const AtomNetlist::TruthTabl /* if No truth_table, do default*/ if (0 == truth_table.size()) { switch (default_sram_bit_value) { - case 0: - on_set = true; - off_set = false; - break; - case 1: - on_set = false; - off_set = true; - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid default_signal_init_value '%lu'!\n", - default_sram_bit_value); - exit(1); + case 0: + on_set = true; + off_set = false; + break; + case 1: + on_set = false; + off_set = true; + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid default_signal_init_value '%lu'!\n", + default_sram_bit_value); + exit(1); } } else { on_set = lut_truth_table_use_on_set(truth_table); @@ -417,7 +415,8 @@ std::vector build_single_output_lut_bitstream(const AtomNetlist::TruthTabl /* Read in truth table lines, decode one by one */ for (const std::vector& tt_line : truth_table) { /* Complete the truth table line by line*/ - completed_truth_table.push_back(complete_truth_table_line(lut_size, tt_line)); + completed_truth_table.push_back( + complete_truth_table_line(lut_size, tt_line)); } /* Initial all the bits in the bitstream */ @@ -425,7 +424,7 @@ std::vector build_single_output_lut_bitstream(const AtomNetlist::TruthTabl /* By default, the lut_bitstream is initialize for on_set * For off set, it should be flipped */ - lut_bitstream.clear(); + lut_bitstream.clear(); lut_bitstream.resize(bitstream_size, true); } @@ -438,42 +437,55 @@ std::vector build_single_output_lut_bitstream(const AtomNetlist::TruthTabl } /******************************************************************** - * Generate bitstream for a fracturable LUT (also applicable to single-output LUT) - * Check type of truth table of each mapped logical block - * if it is on-set, we give a all 0 base bitstream - * if it is off-set, we give a all 1 base bitstream + * Generate bitstream for a fracturable LUT (also applicable to single-output + *LUT) Check type of truth table of each mapped logical block if it is on-set, + *we give a all 0 base bitstream if it is off-set, we give a all 1 base + *bitstream *******************************************************************/ -std::vector build_frac_lut_bitstream(const CircuitLibrary& circuit_lib, - const MuxGraph& lut_mux_graph, - const VprDeviceAnnotation& device_annotation, - const std::map& truth_tables, - const size_t& default_sram_bit_value) { +std::vector build_frac_lut_bitstream( + const CircuitLibrary& circuit_lib, const MuxGraph& lut_mux_graph, + const VprDeviceAnnotation& device_annotation, + const std::map& truth_tables, + const size_t& default_sram_bit_value) { /* Initialization */ - std::vector lut_bitstream(lut_mux_graph.num_inputs(), default_sram_bit_value); + std::vector lut_bitstream(lut_mux_graph.num_inputs(), + default_sram_bit_value); - for (const std::pair& element : truth_tables) { - /* Find the corresponding circuit model output port and assoicated lut_output_mask */ - CircuitPortId lut_model_output_port = device_annotation.pb_circuit_port(element.first->port); - size_t lut_frac_level = circuit_lib.port_lut_frac_level(lut_model_output_port); - /* By default, lut_frac_level will be the lut_size, i.e., number of levels of the mux graph */ + for (const std::pair& + element : truth_tables) { + /* Find the corresponding circuit model output port and assoicated + * lut_output_mask */ + CircuitPortId lut_model_output_port = + device_annotation.pb_circuit_port(element.first->port); + size_t lut_frac_level = + circuit_lib.port_lut_frac_level(lut_model_output_port); + /* By default, lut_frac_level will be the lut_size, i.e., number of levels + * of the mux graph */ if (size_t(-1) == lut_frac_level) { lut_frac_level = lut_mux_graph.num_levels(); } - /* Find the corresponding circuit model output port and assoicated lut_output_mask */ - size_t lut_output_mask = circuit_lib.port_lut_output_mask(lut_model_output_port)[element.first->pin_number]; + /* Find the corresponding circuit model output port and assoicated + * lut_output_mask */ + size_t lut_output_mask = circuit_lib.port_lut_output_mask( + lut_model_output_port)[element.first->pin_number]; /* Decode lut sram bits */ - std::vector temp_bitstream = build_single_output_lut_bitstream(element.second, lut_mux_graph, default_sram_bit_value); + std::vector temp_bitstream = build_single_output_lut_bitstream( + element.second, lut_mux_graph, default_sram_bit_value); - /* Depending on the frac-level, we get the location(starting/end points) of sram bits */ - size_t length_of_temp_bitstream_to_copy = (size_t)pow(2., (double)(lut_frac_level)); - size_t bitstream_offset = length_of_temp_bitstream_to_copy * lut_output_mask; - /* Ensure the offset is in range */ + /* Depending on the frac-level, we get the location(starting/end points) of + * sram bits */ + size_t length_of_temp_bitstream_to_copy = + (size_t)pow(2., (double)(lut_frac_level)); + size_t bitstream_offset = + length_of_temp_bitstream_to_copy * lut_output_mask; + /* Ensure the offset is in range */ VTR_ASSERT(bitstream_offset < lut_bitstream.size()); - VTR_ASSERT(bitstream_offset + length_of_temp_bitstream_to_copy <= lut_bitstream.size()); + VTR_ASSERT(bitstream_offset + length_of_temp_bitstream_to_copy <= + lut_bitstream.size()); - /* Print debug information + /* Print debug information bool verbose = true; VTR_LOGV(verbose, "Full truth table\n"); for (const std::string& tt_line : truth_table_to_string(element.second)) { @@ -493,20 +505,22 @@ std::vector build_frac_lut_bitstream(const CircuitLibrary& circuit_lib, VTR_LOGV(verbose, "\n"); VTR_LOGV(verbose, "Bitstream offset = %d\n", bitstream_offset); - VTR_LOGV(verbose, "Bitstream length to be used = %d\n", length_of_temp_bitstream_to_copy); + VTR_LOGV(verbose, "Bitstream length to be used = %d\n", + length_of_temp_bitstream_to_copy); */ /* Copy to the segment of bitstream */ - for (size_t bit = bitstream_offset; bit < bitstream_offset + length_of_temp_bitstream_to_copy; ++bit) { + for (size_t bit = bitstream_offset; + bit < bitstream_offset + length_of_temp_bitstream_to_copy; ++bit) { lut_bitstream[bit] = temp_bitstream[bit]; } } - return lut_bitstream; + return lut_bitstream; } /*************************************************************************************** - * Identify if LUT is used as wiring + * Identify if LUT is used as wiring * In this case, LUT functions as a buffer * +------+ * in0 -->|--- | @@ -514,9 +528,9 @@ std::vector build_frac_lut_bitstream(const CircuitLibrary& circuit_lib, * in1 -->| --|--->out * ... * - * Note that this function judge the LUT operating mode from the input nets and output - * nets that are mapped to inputs and outputs. - * If the output net appear in the list of input nets, this LUT is used as a wire + * Note that this function judge the LUT operating mode from the input nets and + *output nets that are mapped to inputs and outputs. If the output net appear in + *the list of input nets, this LUT is used as a wire ***************************************************************************************/ bool is_wired_lut(const std::vector& input_nets, const AtomNetId& output_net) { @@ -525,7 +539,7 @@ bool is_wired_lut(const std::vector& input_nets, return true; } } - + return false; } diff --git a/openfpga/src/utils/lut_utils.h b/openfpga/src/utils/lut_utils.h index fb79a0f94..249d84250 100644 --- a/openfpga/src/utils/lut_utils.h +++ b/openfpga/src/utils/lut_utils.h @@ -4,9 +4,10 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ +#include #include #include -#include + #include "atom_netlist.h" #include "mux_graph.h" #include "physical_types.h" @@ -19,25 +20,27 @@ /* begin namespace openfpga */ namespace openfpga { -AtomNetlist::TruthTable lut_truth_table_adaption(const AtomNetlist::TruthTable& orig_tt, - const std::vector& rotated_pin_map); +AtomNetlist::TruthTable lut_truth_table_adaption( + const AtomNetlist::TruthTable& orig_tt, + const std::vector& rotated_pin_map); -std::vector truth_table_to_string(const AtomNetlist::TruthTable& tt); +std::vector truth_table_to_string( + const AtomNetlist::TruthTable& tt); -AtomNetlist::TruthTable build_wired_lut_truth_table(const size_t& lut_size, - const size_t& wire_input_id); +AtomNetlist::TruthTable build_wired_lut_truth_table( + const size_t& lut_size, const size_t& wire_input_id); -AtomNetlist::TruthTable adapt_truth_table_for_frac_lut(const size_t& lut_frac_level, - const size_t& lut_output_mask, - const AtomNetlist::TruthTable& truth_table); +AtomNetlist::TruthTable adapt_truth_table_for_frac_lut( + const size_t& lut_frac_level, const size_t& lut_output_mask, + const AtomNetlist::TruthTable& truth_table); bool lut_truth_table_use_on_set(const AtomNetlist::TruthTable& truth_table); -std::vector build_frac_lut_bitstream(const CircuitLibrary& circuit_lib, - const MuxGraph& lut_mux_graph, - const VprDeviceAnnotation& device_annotation, - const std::map& truth_tables, - const size_t& default_sram_bit_value); +std::vector build_frac_lut_bitstream( + const CircuitLibrary& circuit_lib, const MuxGraph& lut_mux_graph, + const VprDeviceAnnotation& device_annotation, + const std::map& truth_tables, + const size_t& default_sram_bit_value); bool is_wired_lut(const std::vector& input_nets, const AtomNetId& output_net); diff --git a/openfpga/src/utils/memory_bank_utils.cpp b/openfpga/src/utils/memory_bank_utils.cpp index 98f0ffca6..d961be561 100644 --- a/openfpga/src/utils/memory_bank_utils.cpp +++ b/openfpga/src/utils/memory_bank_utils.cpp @@ -1,5 +1,5 @@ /******************************************************************** - * This file includes functions that are used to organize memories + * This file includes functions that are used to organize memories * in the top module of FPGA fabric *******************************************************************/ #include @@ -15,69 +15,90 @@ /* Headers from openfpgashell library */ #include "command_exit_codes.h" - -#include "rr_gsb_utils.h" -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" - -#include "memory_utils.h" #include "decoder_library_utils.h" -#include "module_manager_utils.h" #include "memory_bank_utils.h" +#include "memory_utils.h" +#include "module_manager_utils.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "rr_gsb_utils.h" /* begin namespace openfpga */ namespace openfpga { -std::pair compute_memory_bank_regional_configurable_child_x_range(const ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigRegionId& config_region) { - std::pair child_x_range(std::numeric_limits::max(), std::numeric_limits::min()); // Deposit an invalid range first: LSB->max(); MSB->min() - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - child_x_range.first = std::min(coord.x(), child_x_range.first); - child_x_range.second = std::max(coord.x(), child_x_range.second); +std::pair compute_memory_bank_regional_configurable_child_x_range( + const ModuleManager& module_manager, const ModuleId& top_module, + const ConfigRegionId& config_region) { + std::pair child_x_range( + std::numeric_limits::max(), + std::numeric_limits::min()); // Deposit an invalid range first: + // LSB->max(); MSB->min() + for (size_t child_id = 0; + child_id < + module_manager.region_configurable_children(top_module, config_region) + .size(); + ++child_id) { + vtr::Point coord = + module_manager.region_configurable_child_coordinates( + top_module, config_region)[child_id]; + child_x_range.first = std::min(coord.x(), child_x_range.first); + child_x_range.second = std::max(coord.x(), child_x_range.second); } VTR_ASSERT(child_x_range.first <= child_x_range.second); return child_x_range; } -std::pair compute_memory_bank_regional_configurable_child_y_range(const ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigRegionId& config_region) { - std::pair child_y_range(std::numeric_limits::max(), std::numeric_limits::min()); // Deposit an invalid range first: LSB->max(); MSB->min() - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - child_y_range.first = std::min(coord.y(), child_y_range.first); - child_y_range.second = std::max(coord.y(), child_y_range.second); +std::pair compute_memory_bank_regional_configurable_child_y_range( + const ModuleManager& module_manager, const ModuleId& top_module, + const ConfigRegionId& config_region) { + std::pair child_y_range( + std::numeric_limits::max(), + std::numeric_limits::min()); // Deposit an invalid range first: + // LSB->max(); MSB->min() + for (size_t child_id = 0; + child_id < + module_manager.region_configurable_children(top_module, config_region) + .size(); + ++child_id) { + vtr::Point coord = + module_manager.region_configurable_child_coordinates( + top_module, config_region)[child_id]; + child_y_range.first = std::min(coord.y(), child_y_range.first); + child_y_range.second = std::max(coord.y(), child_y_range.second); } VTR_ASSERT(child_y_range.first <= child_y_range.second); return child_y_range; } -size_t find_module_ql_memory_bank_num_blwls(const ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& circuit_port_type) { - std::vector config_port_names = generate_sram_port_names(circuit_lib, sram_model, sram_orgz_type); +size_t find_module_ql_memory_bank_num_blwls( + const ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& circuit_port_type) { + std::vector config_port_names = + generate_sram_port_names(circuit_lib, sram_model, sram_orgz_type); size_t num_blwls = 0; /* By default it has zero configuration bits*/ /* Try to find these ports in the module manager */ for (const std::string& config_port_name : config_port_names) { - ModulePortId module_port_id = module_manager.find_module_port(module_id, config_port_name); + ModulePortId module_port_id = + module_manager.find_module_port(module_id, config_port_name); /* If the port does not exist, go to the next */ - if (false == module_manager.valid_module_port_id(module_id, module_port_id)) { + if (false == + module_manager.valid_module_port_id(module_id, module_port_id)) { continue; } /* We only care about a give type of ports */ - if (circuit_port_type != circuit_lib.port_type(circuit_lib.model_port(sram_model, config_port_name))) { + if (circuit_port_type != circuit_lib.port_type(circuit_lib.model_port( + sram_model, config_port_name))) { continue; } - /* The port exist, find the port size and update the num_config_bits if the size is larger */ - BasicPort module_port = module_manager.module_port(module_id, module_port_id); + /* The port exist, find the port size and update the num_config_bits if the + * size is larger */ + BasicPort module_port = + module_manager.module_port(module_id, module_port_id); num_blwls = std::max((int)num_blwls, (int)module_port.get_width()); } @@ -90,8 +111,9 @@ size_t compute_memory_bank_regional_num_bls(const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model) { size_t num_bls = 0; - std::map num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module, - config_region, circuit_lib, sram_model); + std::map num_bls_per_tile = + compute_memory_bank_regional_bitline_numbers_per_tile( + module_manager, top_module, config_region, circuit_lib, sram_model); for (const auto& pair : num_bls_per_tile) { num_bls += pair.second; } @@ -99,17 +121,27 @@ size_t compute_memory_bank_regional_num_bls(const ModuleManager& module_manager, return num_bls; } -std::map compute_memory_bank_regional_bitline_numbers_per_tile(const ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigRegionId& config_region, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model) { +std::map compute_memory_bank_regional_bitline_numbers_per_tile( + const ModuleManager& module_manager, const ModuleId& top_module, + const ConfigRegionId& config_region, const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model) { std::map num_bls_per_tile; - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - num_bls_per_tile[coord.x()] = std::max(num_bls_per_tile[coord.x()], find_module_ql_memory_bank_num_blwls(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_BL)); + for (size_t child_id = 0; + child_id < + module_manager.region_configurable_children(top_module, config_region) + .size(); + ++child_id) { + ModuleId child_module = module_manager.region_configurable_children( + top_module, config_region)[child_id]; + vtr::Point coord = + module_manager.region_configurable_child_coordinates( + top_module, config_region)[child_id]; + num_bls_per_tile[coord.x()] = + std::max(num_bls_per_tile[coord.x()], + find_module_ql_memory_bank_num_blwls( + module_manager, child_module, circuit_lib, sram_model, + CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_BL)); } return num_bls_per_tile; @@ -122,8 +154,9 @@ size_t compute_memory_bank_regional_num_wls(const ModuleManager& module_manager, const CircuitModelId& sram_model) { size_t num_wls = 0; - std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, - config_region, circuit_lib, sram_model); + std::map num_wls_per_tile = + compute_memory_bank_regional_wordline_numbers_per_tile( + module_manager, top_module, config_region, circuit_lib, sram_model); for (const auto& pair : num_wls_per_tile) { num_wls += pair.second; } @@ -131,39 +164,51 @@ size_t compute_memory_bank_regional_num_wls(const ModuleManager& module_manager, return num_wls; } -std::map compute_memory_bank_regional_wordline_numbers_per_tile(const ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigRegionId& config_region, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model) { +std::map compute_memory_bank_regional_wordline_numbers_per_tile( + const ModuleManager& module_manager, const ModuleId& top_module, + const ConfigRegionId& config_region, const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model) { std::map num_wls_per_tile; - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - num_wls_per_tile[coord.y()] = std::max(num_wls_per_tile[coord.y()], find_module_ql_memory_bank_num_blwls(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_WL)); + for (size_t child_id = 0; + child_id < + module_manager.region_configurable_children(top_module, config_region) + .size(); + ++child_id) { + ModuleId child_module = module_manager.region_configurable_children( + top_module, config_region)[child_id]; + vtr::Point coord = + module_manager.region_configurable_child_coordinates( + top_module, config_region)[child_id]; + num_wls_per_tile[coord.y()] = + std::max(num_wls_per_tile[coord.y()], + find_module_ql_memory_bank_num_blwls( + module_manager, child_module, circuit_lib, sram_model, + CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_WL)); } return num_wls_per_tile; } -std::map compute_memory_bank_regional_blwl_start_index_per_tile(const std::pair& child_xy_range, - const std::map& num_blwls_per_tile) { +std::map compute_memory_bank_regional_blwl_start_index_per_tile( + const std::pair& child_xy_range, + const std::map& num_blwls_per_tile) { std::map blwl_start_index_per_tile; - for (int iblwl = child_xy_range.first; iblwl <= child_xy_range.second; ++iblwl) { + for (int iblwl = child_xy_range.first; iblwl <= child_xy_range.second; + ++iblwl) { if (iblwl == child_xy_range.first) { blwl_start_index_per_tile[iblwl] = 0; } else { auto result = num_blwls_per_tile.find(iblwl - 1); if (result == num_blwls_per_tile.end()) { - blwl_start_index_per_tile[iblwl] = blwl_start_index_per_tile[iblwl - 1]; + blwl_start_index_per_tile[iblwl] = blwl_start_index_per_tile[iblwl - 1]; } else { - blwl_start_index_per_tile[iblwl] = result->second + blwl_start_index_per_tile[iblwl - 1]; + blwl_start_index_per_tile[iblwl] = + result->second + blwl_start_index_per_tile[iblwl - 1]; } } - } + } return blwl_start_index_per_tile; } } /* end namespace openfpga */ - diff --git a/openfpga/src/utils/memory_bank_utils.h b/openfpga/src/utils/memory_bank_utils.h index 730d19271..73a30aa7a 100644 --- a/openfpga/src/utils/memory_bank_utils.h +++ b/openfpga/src/utils/memory_bank_utils.h @@ -5,14 +5,15 @@ * Include header files that are required by function declaration *******************************************************************/ -#include #include -#include "vtr_vector.h" -#include "vtr_ndmatrix.h" -#include "module_manager.h" +#include + +#include "build_top_module_memory_utils.h" #include "circuit_library.h" #include "decoder_library.h" -#include "build_top_module_memory_utils.h" +#include "module_manager.h" +#include "vtr_ndmatrix.h" +#include "vtr_vector.h" /******************************************************************** * Function declaration @@ -22,34 +23,36 @@ namespace openfpga { /** - * @brief Precompute the range of x coordinates of all the configurable children under a specific configuration region - * The lower bound is stored in the first element of the return struct - * The upper bound is stored in the second element of the return struct + * @brief Precompute the range of x coordinates of all the configurable children + * under a specific configuration region The lower bound is stored in the first + * element of the return struct The upper bound is stored in the second element + * of the return struct */ -std::pair compute_memory_bank_regional_configurable_child_x_range(const ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigRegionId& config_region); +std::pair compute_memory_bank_regional_configurable_child_x_range( + const ModuleManager& module_manager, const ModuleId& top_module, + const ConfigRegionId& config_region); /** - * @brief Precompute the range of y coordinates of all the configurable children under a specific configuration region - * The lower bound is stored in the first element of the return struct - * The upper bound is stored in the second element of the return struct + * @brief Precompute the range of y coordinates of all the configurable children + * under a specific configuration region The lower bound is stored in the first + * element of the return struct The upper bound is stored in the second element + * of the return struct */ -std::pair compute_memory_bank_regional_configurable_child_y_range(const ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigRegionId& config_region); +std::pair compute_memory_bank_regional_configurable_child_y_range( + const ModuleManager& module_manager, const ModuleId& top_module, + const ConfigRegionId& config_region); /** * @brief Find the size of BL or WL ports for a given module */ -size_t find_module_ql_memory_bank_num_blwls(const ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& circuit_port_type); +size_t find_module_ql_memory_bank_num_blwls( + const ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& circuit_port_type); /** - * @brief Precompute the total number of bit lines required by a specific configuration region + * @brief Precompute the total number of bit lines required by a specific + * configuration region */ size_t compute_memory_bank_regional_num_bls(const ModuleManager& module_manager, const ModuleId& top_module, @@ -58,18 +61,22 @@ size_t compute_memory_bank_regional_num_bls(const ModuleManager& module_manager, const CircuitModelId& sram_model); /** - * @brief Precompute the number of bit lines required by each tile under a specific configuration region - * @note - * Not every index in the range computed by the compute_memory_bank_regional_configurable_child_x_range() function has a postive number of bit lines - * If an empty entry is found (e.g., std::map::find(x) is empty), it means there are not bit lines required in that tile + * @brief Precompute the number of bit lines required by each tile under a + * specific configuration region + * @note + * Not every index in the range computed by the + * compute_memory_bank_regional_configurable_child_x_range() function has a + * postive number of bit lines If an empty entry is found (e.g., + * std::map::find(x) is empty), it means there are not bit lines required in + * that tile */ -std::map compute_memory_bank_regional_bitline_numbers_per_tile(const ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigRegionId& config_region, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model); +std::map compute_memory_bank_regional_bitline_numbers_per_tile( + const ModuleManager& module_manager, const ModuleId& top_module, + const ConfigRegionId& config_region, const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model); /** - * @brief Precompute the total number of word lines required by a specific configuration region + * @brief Precompute the total number of word lines required by a specific + * configuration region */ size_t compute_memory_bank_regional_num_wls(const ModuleManager& module_manager, const ModuleId& top_module, @@ -78,29 +85,38 @@ size_t compute_memory_bank_regional_num_wls(const ModuleManager& module_manager, const CircuitModelId& sram_model); /** - * @brief Precompute the number of word lines required by each tile under a specific configuration region - * @note - * Not every index in the range computed by the compute_memory_bank_regional_configurable_child_y_range() function has a postive number of word lines - * If an empty entry is found (e.g., std::map::find(y) is empty), it means there are not word lines required in that tile + * @brief Precompute the number of word lines required by each tile under a + * specific configuration region * @note - * This function requires an input argument which describes number of bitlines per tile. Base on the information, the number of word lines are inferred - * by total number of memores / number of bit lines at a given tile location - * This strategy is chosen because in each column, the number of bit lines are bounded by the tile which consumes most configuation bits. It may reduces - * the use of word lines. For example, a tile[0][0] has only 8 bits, from which we may infer 3 BLs and 3 WLs. However, when tile[0][1] contains 100 bits, - * which will force the number of BLs to be 10. In such case, tile[0][0] only requires 1 WL + * Not every index in the range computed by the + * compute_memory_bank_regional_configurable_child_y_range() function has a + * postive number of word lines If an empty entry is found (e.g., + * std::map::find(y) is empty), it means there are not word lines required in + * that tile + * @note + * This function requires an input argument which describes number of bitlines + * per tile. Base on the information, the number of word lines are inferred by + * total number of memores / number of bit lines at a given tile location This + * strategy is chosen because in each column, the number of bit lines are + * bounded by the tile which consumes most configuation bits. It may reduces the + * use of word lines. For example, a tile[0][0] has only 8 bits, from which we + * may infer 3 BLs and 3 WLs. However, when tile[0][1] contains 100 bits, which + * will force the number of BLs to be 10. In such case, tile[0][0] only requires + * 1 WL */ -std::map compute_memory_bank_regional_wordline_numbers_per_tile(const ModuleManager& module_manager, - const ModuleId& top_module, - const ConfigRegionId& config_region, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model); +std::map compute_memory_bank_regional_wordline_numbers_per_tile( + const ModuleManager& module_manager, const ModuleId& top_module, + const ConfigRegionId& config_region, const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model); /** * @brief Precompute the BLs and WLs distribution across the FPGA fabric - * The distribution is a matrix which contains the starting index of BL/WL for each column or row + * The distribution is a matrix which contains the starting index of BL/WL for + * each column or row */ -std::map compute_memory_bank_regional_blwl_start_index_per_tile(const std::pair& child_xy_range, - const std::map& num_blwls_per_tile); +std::map compute_memory_bank_regional_blwl_start_index_per_tile( + const std::pair& child_xy_range, + const std::map& num_blwls_per_tile); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/memory_utils.cpp b/openfpga/src/utils/memory_utils.cpp index 8da43d02b..df144e669 100644 --- a/openfpga/src/utils/memory_utils.cpp +++ b/openfpga/src/utils/memory_utils.cpp @@ -1,25 +1,25 @@ /********************************************************************* - * This file includes functions that are used for - * generating ports for memory modules + * This file includes functions that are used for + * generating ports for memory modules *********************************************************************/ /* Headers from vtrutil library */ +#include "memory_utils.h" + +#include "decoder_library_utils.h" +#include "openfpga_naming.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "openfpga_naming.h" -#include "decoder_library_utils.h" -#include "memory_utils.h" - /* begin namespace openfpga */ namespace openfpga { /********************************************************************* - * Create a port-to-port map for a CMOS memory module + * Create a port-to-port map for a CMOS memory module * - * Configuration Chain + * Configuration Chain * ------------------- * - * config_bus (head) config_bus (tail) + * config_bus (head) config_bus (tail) * | ^ * v | * +-------------------------------------+ @@ -30,10 +30,10 @@ namespace openfpga { * sram_out sram_outb * * - * Memory bank + * Memory bank * ----------- * - * config_bus (BL) config_bus (WL) + * config_bus (BL) config_bus (WL) * | | * v v * +-------------------------------------+ @@ -44,55 +44,64 @@ namespace openfpga { * sram_out sram_outb * **********************************************************************/ -static -std::map generate_cmos_mem_module_port2port_map(const BasicPort& config_bus, - const std::vector& mem_output_bus_ports, - const e_config_protocol_type& sram_orgz_type) { +static std::map generate_cmos_mem_module_port2port_map( + const BasicPort& config_bus, + const std::vector& mem_output_bus_ports, + const e_config_protocol_type& sram_orgz_type) { std::map port2port_name_map; switch (sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - /* Nothing to do */ - break; - case CONFIG_MEM_SCAN_CHAIN: { - /* Link the head port of the memory module: - * the LSB of config bus port is the head port index - */ - std::vector config_bus_ports; - config_bus_ports.push_back(BasicPort(generate_local_config_bus_port_name(), config_bus.get_msb(), config_bus.get_msb() + 1)); - BasicPort head_port(config_bus_ports[0].get_name(), config_bus_ports[0].get_lsb(), config_bus_ports[0].get_lsb()); - port2port_name_map[generate_configuration_chain_head_name()] = head_port; + case CONFIG_MEM_STANDALONE: + /* Nothing to do */ + break; + case CONFIG_MEM_SCAN_CHAIN: { + /* Link the head port of the memory module: + * the LSB of config bus port is the head port index + */ + std::vector config_bus_ports; + config_bus_ports.push_back( + BasicPort(generate_local_config_bus_port_name(), config_bus.get_msb(), + config_bus.get_msb() + 1)); + BasicPort head_port(config_bus_ports[0].get_name(), + config_bus_ports[0].get_lsb(), + config_bus_ports[0].get_lsb()); + port2port_name_map[generate_configuration_chain_head_name()] = head_port; - /* Link the tail port of the memory module: - * the MSB of config bus port is the tail port index - */ - BasicPort tail_port(config_bus_ports[0].get_name(), config_bus_ports[0].get_msb(), config_bus_ports[0].get_msb()); - port2port_name_map[generate_configuration_chain_tail_name()] = tail_port; + /* Link the tail port of the memory module: + * the MSB of config bus port is the tail port index + */ + BasicPort tail_port(config_bus_ports[0].get_name(), + config_bus_ports[0].get_msb(), + config_bus_ports[0].get_msb()); + port2port_name_map[generate_configuration_chain_tail_name()] = tail_port; - /* Link the SRAM output ports of the memory module */ - VTR_ASSERT( 2 == mem_output_bus_ports.size() ); - port2port_name_map[generate_configurable_memory_data_out_name()] = mem_output_bus_ports[0]; - port2port_name_map[generate_configurable_memory_inverted_data_out_name()] = mem_output_bus_ports[1]; - break; - } - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: - /* TODO: */ - break; - default: - VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); - exit(1); + /* Link the SRAM output ports of the memory module */ + VTR_ASSERT(2 == mem_output_bus_ports.size()); + port2port_name_map[generate_configurable_memory_data_out_name()] = + mem_output_bus_ports[0]; + port2port_name_map + [generate_configurable_memory_inverted_data_out_name()] = + mem_output_bus_ports[1]; + break; + } + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: + /* TODO: */ + break; + default: + VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); + exit(1); } return port2port_name_map; } /********************************************************************* - * Create a port-to-port map for a ReRAM-based memory module - * Memory bank + * Create a port-to-port map for a ReRAM-based memory module + * Memory bank * ----------- * - * config_bus (BL) config_bus (WL) + * config_bus (BL) config_bus (WL) * | | * v v * +-------------------------------------+ @@ -102,164 +111,176 @@ std::map generate_cmos_mem_module_port2port_map(const Ba * v v * Mem_out Mem_outb **********************************************************************/ -static -std::map generate_rram_mem_module_port2port_map(const BasicPort& config_bus, - const std::vector& mem_output_bus_ports, - const e_config_protocol_type& sram_orgz_type) { +static std::map generate_rram_mem_module_port2port_map( + const BasicPort& config_bus, + const std::vector& mem_output_bus_ports, + const e_config_protocol_type& sram_orgz_type) { std::map port2port_name_map; switch (sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - /* Not supported */ - break; - case CONFIG_MEM_SCAN_CHAIN: { - /* Link the head port of the memory module: - * the LSB of config bus port is the head port index - */ - std::vector config_bus_ports; - config_bus_ports.push_back(BasicPort(generate_local_config_bus_port_name(), config_bus.get_msb(), config_bus.get_msb() + 1)); - BasicPort head_port(config_bus_ports[0].get_name(), config_bus_ports[0].get_lsb(), config_bus_ports[0].get_lsb()); - port2port_name_map[generate_configuration_chain_head_name()] = head_port; + case CONFIG_MEM_STANDALONE: + /* Not supported */ + break; + case CONFIG_MEM_SCAN_CHAIN: { + /* Link the head port of the memory module: + * the LSB of config bus port is the head port index + */ + std::vector config_bus_ports; + config_bus_ports.push_back( + BasicPort(generate_local_config_bus_port_name(), config_bus.get_msb(), + config_bus.get_msb() + 1)); + BasicPort head_port(config_bus_ports[0].get_name(), + config_bus_ports[0].get_lsb(), + config_bus_ports[0].get_lsb()); + port2port_name_map[generate_configuration_chain_head_name()] = head_port; - /* Link the tail port of the memory module: - * the MSB of config bus port is the tail port index - */ - BasicPort tail_port(config_bus_ports[0].get_name(), config_bus_ports[0].get_msb(), config_bus_ports[0].get_msb()); - port2port_name_map[generate_configuration_chain_tail_name()] = tail_port; + /* Link the tail port of the memory module: + * the MSB of config bus port is the tail port index + */ + BasicPort tail_port(config_bus_ports[0].get_name(), + config_bus_ports[0].get_msb(), + config_bus_ports[0].get_msb()); + port2port_name_map[generate_configuration_chain_tail_name()] = tail_port; - /* Link the SRAM output ports of the memory module */ - VTR_ASSERT( 2 == mem_output_bus_ports.size() ); - port2port_name_map[generate_configurable_memory_data_out_name()] = mem_output_bus_ports[0]; - port2port_name_map[generate_configurable_memory_inverted_data_out_name()] = mem_output_bus_ports[1]; - break; - } - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: - /* TODO: link BL/WL/Reserved Ports to the inputs of a memory module */ - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization!\n"); - exit(1); + /* Link the SRAM output ports of the memory module */ + VTR_ASSERT(2 == mem_output_bus_ports.size()); + port2port_name_map[generate_configurable_memory_data_out_name()] = + mem_output_bus_ports[0]; + port2port_name_map + [generate_configurable_memory_inverted_data_out_name()] = + mem_output_bus_ports[1]; + break; + } + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: + /* TODO: link BL/WL/Reserved Ports to the inputs of a memory module */ + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization!\n"); + exit(1); } return port2port_name_map; } /********************************************************************* - * Create a port-to-port map for a memory module - * The content of the port-to-port map will depend not only - * the design technology of the memory cells but also the + * Create a port-to-port map for a memory module + * The content of the port-to-port map will depend not only + * the design technology of the memory cells but also the * configuration styles of FPGA fabric. * Here we will branch on the design technology **********************************************************************/ -std::map generate_mem_module_port2port_map(const BasicPort& config_bus, - const std::vector& mem_output_bus_ports, - const e_circuit_model_design_tech& mem_design_tech, - const e_config_protocol_type& sram_orgz_type) { +std::map generate_mem_module_port2port_map( + const BasicPort& config_bus, + const std::vector& mem_output_bus_ports, + const e_circuit_model_design_tech& mem_design_tech, + const e_config_protocol_type& sram_orgz_type) { std::map port2port_name_map; switch (mem_design_tech) { - case CIRCUIT_MODEL_DESIGN_CMOS: - port2port_name_map = generate_cmos_mem_module_port2port_map(config_bus, mem_output_bus_ports, sram_orgz_type); - break; - case CIRCUIT_MODEL_DESIGN_RRAM: - port2port_name_map = generate_rram_mem_module_port2port_map(config_bus, mem_output_bus_ports, sram_orgz_type); - break; - default: - VTR_LOG_ERROR("Invalid type of memory design technology!\n"); - exit(1); + case CIRCUIT_MODEL_DESIGN_CMOS: + port2port_name_map = generate_cmos_mem_module_port2port_map( + config_bus, mem_output_bus_ports, sram_orgz_type); + break; + case CIRCUIT_MODEL_DESIGN_RRAM: + port2port_name_map = generate_rram_mem_module_port2port_map( + config_bus, mem_output_bus_ports, sram_orgz_type); + break; + default: + VTR_LOG_ERROR("Invalid type of memory design technology!\n"); + exit(1); } return port2port_name_map; } /********************************************************************* - * Update the LSB and MSB of a configuration bus based on the number of - * memory bits of a CMOS memory module. + * Update the LSB and MSB of a configuration bus based on the number of + * memory bits of a CMOS memory module. **********************************************************************/ -static -void update_cmos_mem_module_config_bus(const e_config_protocol_type& sram_orgz_type, - const size_t& num_config_bits, - BasicPort& config_bus) { +static void update_cmos_mem_module_config_bus( + const e_config_protocol_type& sram_orgz_type, const size_t& num_config_bits, + BasicPort& config_bus) { switch (sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - /* Not supported */ - break; - case CONFIG_MEM_SCAN_CHAIN: - /* Scan-chain of a memory module only has a head and a tail. - * LSB and MSB of configuration bus will be shifted to the next head. - */ - VTR_ASSERT(true == config_bus.rotate(1)); - break; - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: - /* In this case, a memory module has a number of BL/WL and BLB/WLB (possibly). - * LSB and MSB of configuration bus will be shifted by the number of BL/WL/BLB/WLB. - */ - VTR_ASSERT(true == config_bus.rotate(num_config_bits)); - break; - default: - VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); - exit(1); + case CONFIG_MEM_STANDALONE: + /* Not supported */ + break; + case CONFIG_MEM_SCAN_CHAIN: + /* Scan-chain of a memory module only has a head and a tail. + * LSB and MSB of configuration bus will be shifted to the next head. + */ + VTR_ASSERT(true == config_bus.rotate(1)); + break; + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: + /* In this case, a memory module has a number of BL/WL and BLB/WLB + * (possibly). LSB and MSB of configuration bus will be shifted by the + * number of BL/WL/BLB/WLB. + */ + VTR_ASSERT(true == config_bus.rotate(num_config_bits)); + break; + default: + VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); + exit(1); } } /********************************************************************* - * Update the LSB and MSB of a configuration bus based on the number of - * memory bits of a ReRAM memory module. + * Update the LSB and MSB of a configuration bus based on the number of + * memory bits of a ReRAM memory module. **********************************************************************/ -static -void update_rram_mem_module_config_bus(const e_config_protocol_type& sram_orgz_type, - BasicPort& config_bus) { +static void update_rram_mem_module_config_bus( + const e_config_protocol_type& sram_orgz_type, BasicPort& config_bus) { switch (sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - /* Not supported */ - break; - case CONFIG_MEM_SCAN_CHAIN: - /* Scan-chain of a memory module only has a head and a tail. - * LSB and MSB of configuration bus will be shifted to the next head. - * TODO: this may be changed later!!! - */ - VTR_ASSERT(true == config_bus.rotate(1)); - break; - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: - /* In this case, a memory module contains unique BL/WL or BLB/WLB, - * which are not shared with other modules - * TODO: this may be changed later!!! - */ - VTR_ASSERT(true == config_bus.rotate(1)); - break; - default: - VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); - exit(1); + case CONFIG_MEM_STANDALONE: + /* Not supported */ + break; + case CONFIG_MEM_SCAN_CHAIN: + /* Scan-chain of a memory module only has a head and a tail. + * LSB and MSB of configuration bus will be shifted to the next head. + * TODO: this may be changed later!!! + */ + VTR_ASSERT(true == config_bus.rotate(1)); + break; + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: + /* In this case, a memory module contains unique BL/WL or BLB/WLB, + * which are not shared with other modules + * TODO: this may be changed later!!! + */ + VTR_ASSERT(true == config_bus.rotate(1)); + break; + default: + VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); + exit(1); } } /********************************************************************* - * Update the LSB and MSB of a configuration bus based on the number of - * memory bits of a module. + * Update the LSB and MSB of a configuration bus based on the number of + * memory bits of a module. * Note that this function is designed to do such simple job, in purpose of * being independent from adding ports or printing ports. - * As such, this function can be re-used in bitstream generation - * when Verilog generation is not needed. + * As such, this function can be re-used in bitstream generation + * when Verilog generation is not needed. * DO NOT update the configuration bus in the function of adding/printing ports **********************************************************************/ -void update_mem_module_config_bus(const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_design_tech, - const size_t& num_config_bits, - BasicPort& config_bus) { +void update_mem_module_config_bus( + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_design_tech& mem_design_tech, + const size_t& num_config_bits, BasicPort& config_bus) { switch (mem_design_tech) { - case CIRCUIT_MODEL_DESIGN_CMOS: - update_cmos_mem_module_config_bus(sram_orgz_type, num_config_bits, config_bus); - break; - case CIRCUIT_MODEL_DESIGN_RRAM: - update_rram_mem_module_config_bus(sram_orgz_type, config_bus); - break; - default: - VTR_LOG_ERROR("Invalid type of memory design technology!\n"); - exit(1); + case CIRCUIT_MODEL_DESIGN_CMOS: + update_cmos_mem_module_config_bus(sram_orgz_type, num_config_bits, + config_bus); + break; + case CIRCUIT_MODEL_DESIGN_RRAM: + update_rram_mem_module_config_bus(sram_orgz_type, config_bus); + break; + default: + VTR_LOG_ERROR("Invalid type of memory design technology!\n"); + exit(1); } } @@ -267,28 +288,28 @@ void update_mem_module_config_bus(const e_config_protocol_type& sram_orgz_type, * Check if the MSB of a configuration bus of a switch block * matches the expected value ********************************************************************/ -bool check_mem_config_bus(const e_config_protocol_type& sram_orgz_type, - const BasicPort& config_bus, +bool check_mem_config_bus(const e_config_protocol_type& sram_orgz_type, + const BasicPort& config_bus, const size_t& local_expected_msb) { switch (sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - /* Not supported */ - return false; - break; - case CONFIG_MEM_SCAN_CHAIN: - /* TODO: comment on why - */ - return (local_expected_msb == config_bus.get_msb()); - break; - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: - /* TODO: comment on why - */ - return (local_expected_msb == config_bus.get_msb()); - break; - default: - VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); - exit(1); + case CONFIG_MEM_STANDALONE: + /* Not supported */ + return false; + break; + case CONFIG_MEM_SCAN_CHAIN: + /* TODO: comment on why + */ + return (local_expected_msb == config_bus.get_msb()); + break; + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: + /* TODO: comment on why + */ + return (local_expected_msb == config_bus.get_msb()); + break; + default: + VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); + exit(1); } /* Reach here, it means something goes wrong, return a false value */ return false; @@ -296,65 +317,69 @@ bool check_mem_config_bus(const e_config_protocol_type& sram_orgz_type, /******************************************************************** * Generate a list of ports that are used for SRAM configuration to a module - * The type and names of added ports strongly depend on the + * The type and names of added ports strongly depend on the * organization of SRAMs. - * 1. Standalone SRAMs: - * two ports will be added, which are regular output and inverted output + * 1. Standalone SRAMs: + * two ports will be added, which are regular output and inverted output * 2. Scan-chain Flip-flops: - * two ports will be added, which are the head of scan-chain + * two ports will be added, which are the head of scan-chain * and the tail of scan-chain - * IMPORTANT: the port size will be forced to 1 in this case + * IMPORTANT: the port size will be forced to 1 in this case * because the head and tail are both 1-bit ports!!! * 3. Memory decoders: * 2-4 ports will be added, depending on the ports available in the SRAM - * Among these, two ports are mandatory: BL and WL + * Among these, two ports are mandatory: BL and WL * The other two ports are optional: BLB and WLB - * Note that the constraints are correletated to the checking rules + * Note that the constraints are correletated to the checking rules * in check_circuit_library() ********************************************************************/ -std::vector generate_sram_port_names(const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type sram_orgz_type) { +std::vector generate_sram_port_names( + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type sram_orgz_type) { std::vector sram_port_names; - /* Prepare a list of port types to be added, the port type will be used to create port names */ - std::vector model_port_types; + /* Prepare a list of port types to be added, the port type will be used to + * create port names */ + std::vector model_port_types; switch (sram_orgz_type) { - case CONFIG_MEM_SCAN_CHAIN: - model_port_types.push_back(CIRCUIT_MODEL_PORT_INPUT); - model_port_types.push_back(CIRCUIT_MODEL_PORT_OUTPUT); - break; - case CONFIG_MEM_STANDALONE: - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: { - std::vector ports_to_search; - ports_to_search.push_back(CIRCUIT_MODEL_PORT_BL); - ports_to_search.push_back(CIRCUIT_MODEL_PORT_WL); - ports_to_search.push_back(CIRCUIT_MODEL_PORT_WLR); - /* Try to find a BL/WL/WLR port and update the port types/module port types to be added */ - for (const auto& port_to_search : ports_to_search) { - std::vector found_port = circuit_lib.model_ports_by_type(sram_model, port_to_search); - if (0 == found_port.size()) { - continue; + case CONFIG_MEM_SCAN_CHAIN: + model_port_types.push_back(CIRCUIT_MODEL_PORT_INPUT); + model_port_types.push_back(CIRCUIT_MODEL_PORT_OUTPUT); + break; + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: { + std::vector ports_to_search; + ports_to_search.push_back(CIRCUIT_MODEL_PORT_BL); + ports_to_search.push_back(CIRCUIT_MODEL_PORT_WL); + ports_to_search.push_back(CIRCUIT_MODEL_PORT_WLR); + /* Try to find a BL/WL/WLR port and update the port types/module port + * types to be added */ + for (const auto& port_to_search : ports_to_search) { + std::vector found_port = + circuit_lib.model_ports_by_type(sram_model, port_to_search); + if (0 == found_port.size()) { + continue; + } + model_port_types.push_back(port_to_search); } - model_port_types.push_back(port_to_search); + break; } - break; - } - case CONFIG_MEM_FRAME_BASED: { - model_port_types.push_back(CIRCUIT_MODEL_PORT_INPUT); - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization !\n"); - exit(1); + case CONFIG_MEM_FRAME_BASED: { + model_port_types.push_back(CIRCUIT_MODEL_PORT_INPUT); + break; + } + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization !\n"); + exit(1); } /* Add ports to the module manager */ for (size_t iport = 0; iport < model_port_types.size(); ++iport) { /* Create a port */ - std::string port_name = generate_sram_port_name(sram_orgz_type, model_port_types[iport]); + std::string port_name = + generate_sram_port_name(sram_orgz_type, model_port_types[iport]); sram_port_names.push_back(port_name); } @@ -363,43 +388,44 @@ std::vector generate_sram_port_names(const CircuitLibrary& circuit_ /******************************************************************** * Generate a list of ports that are used for SRAM configuration to a module - * 1. Standalone SRAMs: - * use the suggested port_size + * 1. Standalone SRAMs: + * use the suggested port_size * 2. Scan-chain Flip-flops: - * IMPORTANT: the port size will be forced to 1 in this case + * IMPORTANT: the port size will be forced to 1 in this case * 3. Memory decoders: - * use the suggested port_size + * use the suggested port_size ********************************************************************/ size_t generate_sram_port_size(const e_config_protocol_type sram_orgz_type, const size_t& num_config_bits) { size_t sram_port_size = num_config_bits; switch (sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - break; - case CONFIG_MEM_SCAN_CHAIN: - /* CCFF head/tail are single-bit ports */ - sram_port_size = 1; - break; - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: - break; - case CONFIG_MEM_FRAME_BASED: - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization!\n"); - exit(1); + case CONFIG_MEM_STANDALONE: + break; + case CONFIG_MEM_SCAN_CHAIN: + /* CCFF head/tail are single-bit ports */ + sram_port_size = 1; + break; + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: + break; + case CONFIG_MEM_FRAME_BASED: + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization!\n"); + exit(1); } return sram_port_size; } /******************************************************************** - * @brief Generate a list of ports that are used for SRAM configuration to a module - * - Standalone SRAMs: use the suggested port_size - * - Scan-chain Flip-flops: the port size will be forced to 1 in this case - * - Memory decoders: use the suggested port_size + * @brief Generate a list of ports that are used for SRAM configuration to a + *module + * - Standalone SRAMs: use the suggested port_size + * - Scan-chain Flip-flops: the port size will be forced to 1 in this case + * - Memory decoders: use the suggested port_size * - QL Memory decoders: Apply square root as BL/WLs will be grouped ********************************************************************/ size_t generate_pb_sram_port_size(const e_config_protocol_type sram_orgz_type, @@ -407,55 +433,56 @@ size_t generate_pb_sram_port_size(const e_config_protocol_type sram_orgz_type, size_t sram_port_size = num_config_bits; switch (sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - break; - case CONFIG_MEM_SCAN_CHAIN: - /* CCFF head/tail are single-bit ports */ - sram_port_size = 1; - break; - case CONFIG_MEM_QL_MEMORY_BANK: - sram_port_size = find_memory_decoder_data_size(num_config_bits); - break; - case CONFIG_MEM_MEMORY_BANK: - break; - case CONFIG_MEM_FRAME_BASED: - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization!\n"); - exit(1); + case CONFIG_MEM_STANDALONE: + break; + case CONFIG_MEM_SCAN_CHAIN: + /* CCFF head/tail are single-bit ports */ + sram_port_size = 1; + break; + case CONFIG_MEM_QL_MEMORY_BANK: + sram_port_size = find_memory_decoder_data_size(num_config_bits); + break; + case CONFIG_MEM_MEMORY_BANK: + break; + case CONFIG_MEM_FRAME_BASED: + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization!\n"); + exit(1); } return sram_port_size; } -size_t estimate_num_configurable_children_to_skip_by_config_protocol(const ConfigProtocol& config_protocol, - size_t curr_region_num_config_child) { +size_t estimate_num_configurable_children_to_skip_by_config_protocol( + const ConfigProtocol& config_protocol, size_t curr_region_num_config_child) { size_t num_child_to_skip = 0; /* Frame-based configuration protocol will have 1 decoder * if there are more than 1 configurable children */ - if ( (CONFIG_MEM_FRAME_BASED == config_protocol.type()) - && (2 <= curr_region_num_config_child)) { + if ((CONFIG_MEM_FRAME_BASED == config_protocol.type()) && + (2 <= curr_region_num_config_child)) { num_child_to_skip = 1; } - + /* Memory configuration protocol will have 2 decoders * at the top-level */ - if (CONFIG_MEM_MEMORY_BANK == config_protocol.type() - || CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) { + if (CONFIG_MEM_MEMORY_BANK == config_protocol.type() || + CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) { VTR_ASSERT(2 <= curr_region_num_config_child); num_child_to_skip = 2; /* - If flatten bus is used, BL/WL may not need decoders - * - If shift registers are used, BL/WLs do not need decoders. And shift registers are not counted as configurable children + * - If shift registers are used, BL/WLs do not need decoders. And shift + * registers are not counted as configurable children */ - if ( BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() - || BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type() ) { + if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() || + BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { num_child_to_skip--; } - if ( BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type() - || BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type() ) { + if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type() || + BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()) { num_child_to_skip--; } } diff --git a/openfpga/src/utils/memory_utils.h b/openfpga/src/utils/memory_utils.h index bf092b81a..59cf08953 100644 --- a/openfpga/src/utils/memory_utils.h +++ b/openfpga/src/utils/memory_utils.h @@ -5,10 +5,11 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "openfpga_port.h" + #include "circuit_types.h" #include "config_protocol.h" #include "module_manager.h" +#include "openfpga_port.h" /******************************************************************** * Function declaration @@ -17,23 +18,24 @@ /* begin namespace openfpga */ namespace openfpga { -std::map generate_mem_module_port2port_map(const BasicPort& config_bus, - const std::vector& mem_output_bus_ports, - const e_circuit_model_design_tech& mem_design_tech, - const e_config_protocol_type& sram_orgz_type); +std::map generate_mem_module_port2port_map( + const BasicPort& config_bus, + const std::vector& mem_output_bus_ports, + const e_circuit_model_design_tech& mem_design_tech, + const e_config_protocol_type& sram_orgz_type); -void update_mem_module_config_bus(const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_design_tech, - const size_t& num_config_bits, - BasicPort& config_bus); +void update_mem_module_config_bus( + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_design_tech& mem_design_tech, + const size_t& num_config_bits, BasicPort& config_bus); -bool check_mem_config_bus(const e_config_protocol_type& sram_orgz_type, - const BasicPort& config_bus, +bool check_mem_config_bus(const e_config_protocol_type& sram_orgz_type, + const BasicPort& config_bus, const size_t& local_expected_msb); -std::vector generate_sram_port_names(const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type sram_orgz_type); +std::vector generate_sram_port_names( + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type sram_orgz_type); size_t generate_sram_port_size(const e_config_protocol_type sram_orgz_type, const size_t& num_config_bits); @@ -42,13 +44,14 @@ size_t generate_pb_sram_port_size(const e_config_protocol_type sram_orgz_type, const size_t& num_config_bits); /** - * @brief Compute the number of configurable children to be skipped for a given configuration protocol - * For some configuration protocol, the decoders are not counted as configurable children - * (they are included in the list for bitstream generator usage) - * The number of decoders depends on the type of configuration protocol. + * @brief Compute the number of configurable children to be skipped for a given + * configuration protocol For some configuration protocol, the decoders are not + * counted as configurable children (they are included in the list for bitstream + * generator usage) The number of decoders depends on the type of configuration + * protocol. */ -size_t estimate_num_configurable_children_to_skip_by_config_protocol(const ConfigProtocol& config_protocol, - size_t curr_region_num_config_child); +size_t estimate_num_configurable_children_to_skip_by_config_protocol( + const ConfigProtocol& config_protocol, size_t curr_region_num_config_child); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index 78015f522..ac625af02 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -1,28 +1,26 @@ /****************************************************************************** - * This files includes most utilized functions + * This files includes most utilized functions * for data structures for module management. ******************************************************************************/ -#include -#include #include +#include +#include /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" /* Headers from openfpgautil library */ -#include "openfpga_port.h" - -#include "openfpga_reserved_words.h" -#include "openfpga_naming.h" -#include "memory_utils.h" -#include "pb_type_utils.h" - #include "build_decoder_modules.h" #include "circuit_library_utils.h" #include "decoder_library_utils.h" +#include "memory_utils.h" #include "module_manager_utils.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" +#include "openfpga_reserved_words.h" +#include "pb_type_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -32,7 +30,7 @@ namespace openfpga { * based on the number of output ports of its child modules * for memory efficiency ******************************************************************************/ -void reserve_module_manager_module_nets(ModuleManager& module_manager, +void reserve_module_manager_module_nets(ModuleManager& module_manager, const ModuleId& parent_module) { size_t num_nets = 0; @@ -47,7 +45,8 @@ void reserve_module_manager_module_nets(ModuleManager& module_manager, /* The number of nets depends on the sizes of input ports of parent module */ for (const auto& port_type : driver_port_types) { - for (const BasicPort& port : module_manager.module_ports_by_type(parent_module, port_type)) { + for (const BasicPort& port : + module_manager.module_ports_by_type(parent_module, port_type)) { num_nets += port.get_width(); } } @@ -56,33 +55,37 @@ void reserve_module_manager_module_nets(ModuleManager& module_manager, std::vector output_port_types; output_port_types.push_back(ModuleManager::MODULE_GPOUT_PORT); output_port_types.push_back(ModuleManager::MODULE_OUTPUT_PORT); - - for (const ModuleId& child_module : module_manager.child_modules(parent_module)) { - /* The number of nets depends on the sizes of output ports of + + for (const ModuleId& child_module : + module_manager.child_modules(parent_module)) { + /* The number of nets depends on the sizes of output ports of * each instanciated child module */ - size_t num_instances = module_manager.num_instance(parent_module, child_module); + size_t num_instances = + module_manager.num_instance(parent_module, child_module); /* Sum up the port sizes for all the output ports */ size_t total_output_port_sizes = 0; for (const auto& port_type : output_port_types) { - for (const BasicPort& port : module_manager.module_ports_by_type(child_module, port_type)) { + for (const BasicPort& port : + module_manager.module_ports_by_type(child_module, port_type)) { total_output_port_sizes += port.get_width(); } } num_nets += total_output_port_sizes * num_instances; } - + module_manager.reserve_module_nets(parent_module, num_nets); } /****************************************************************************** - * Count the 'actual' number of configurable children for a module in module manager - * A 'true' configurable children should have a number of configurable children as well + * Count the 'actual' number of configurable children for a module in module + *manager A 'true' configurable children should have a number of configurable + *children as well ******************************************************************************/ -size_t count_module_manager_module_configurable_children(const ModuleManager& module_manager, - const ModuleId& module) { +size_t count_module_manager_module_configurable_children( + const ModuleManager& module_manager, const ModuleId& module) { size_t num_config_children = 0; for (const ModuleId& child : module_manager.configurable_children(module)) { @@ -95,27 +98,29 @@ size_t count_module_manager_module_configurable_children(const ModuleManager& mo } /****************************************************************************** - * Find the module id and instance id in module manager with a given instance name - * This function will exhaustively search all the child module under a given parent - * module + * Find the module id and instance id in module manager with a given instance + *name This function will exhaustively search all the child module under a given + *parent module ******************************************************************************/ -std::pair find_module_manager_instance_module_info(const ModuleManager& module_manager, - const ModuleId& parent, - const std::string& instance_name) { +std::pair find_module_manager_instance_module_info( + const ModuleManager& module_manager, const ModuleId& parent, + const std::string& instance_name) { /* Deposit invalid values as default */ std::pair instance_info(ModuleId::INVALID(), 0); - + /* Search all the child module and see we have a match */ for (const ModuleId& child : module_manager.child_modules(parent)) { - size_t child_instance = module_manager.instance_id(parent, child, instance_name); - if (true == module_manager.valid_module_instance_id(parent, child, child_instance)) { + size_t child_instance = + module_manager.instance_id(parent, child, instance_name); + if (true == module_manager.valid_module_instance_id(parent, child, + child_instance)) { instance_info.first = child; instance_info.second = child_instance; return instance_info; } } - - return instance_info; + + return instance_info; } /****************************************************************************** @@ -124,15 +129,15 @@ std::pair find_module_manager_instance_module_info(const Modul * This function add a module with a given customized name * as well as add the ports of circuit model to the module manager ******************************************************************************/ -ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, - const std::string& module_name) { - ModuleId module = module_manager.add_module(module_name); +ModuleId add_circuit_model_to_module_manager( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, const std::string& module_name) { + ModuleId module = module_manager.add_module(module_name); VTR_ASSERT(ModuleId::INVALID() != module); /* Identify module usage based on circuit type: * LUT, SRAM, CCFF, I/O have specific usages - * Others will be classified as hard IPs + * Others will be classified as hard IPs */ if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)) { module_manager.set_module_usage(module, ModuleManager::MODULE_LUT); @@ -151,29 +156,38 @@ ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager, } /* Add ports */ - /* Find global ports and add one by one - * Non-I/O Global input ports will be considered as global port to be shorted wired in the context of module manager - * I/O Global output ports will be considered as general purpose output port in the context of module manager - * I/O Global inout ports will be considered as general purpose i/o port in the context of module manager + /* Find global ports and add one by one + * Non-I/O Global input ports will be considered as global port to be shorted + * wired in the context of module manager I/O Global output ports will be + * considered as general purpose output port in the context of module manager + * I/O Global inout ports will be considered as general purpose i/o port in + * the context of module manager */ - for (const auto& port : circuit_lib.model_global_ports(circuit_model, false)) { - BasicPort port_info(circuit_lib.port_prefix(port), circuit_lib.port_size(port)); + for (const auto& port : + circuit_lib.model_global_ports(circuit_model, false)) { + BasicPort port_info(circuit_lib.port_prefix(port), + circuit_lib.port_size(port)); ModulePortId module_port = ModulePortId::INVALID(); - if ( (CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(port)) - && (false == circuit_lib.port_is_io(port)) ) { - module_port = module_manager.add_port(module, port_info, ModuleManager::MODULE_GLOBAL_PORT); + if ((CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(port)) && + (false == circuit_lib.port_is_io(port))) { + module_port = module_manager.add_port(module, port_info, + ModuleManager::MODULE_GLOBAL_PORT); } else if (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(port)) { - module_port = module_manager.add_port(module, port_info, ModuleManager::MODULE_GLOBAL_PORT); - } else if ( (CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(port)) - && (true == circuit_lib.port_is_io(port)) ) { - module_port = module_manager.add_port(module, port_info, ModuleManager::MODULE_GPIN_PORT); + module_port = module_manager.add_port(module, port_info, + ModuleManager::MODULE_GLOBAL_PORT); + } else if ((CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(port)) && + (true == circuit_lib.port_is_io(port))) { + module_port = module_manager.add_port(module, port_info, + ModuleManager::MODULE_GPIN_PORT); } else if (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port)) { VTR_ASSERT(true == circuit_lib.port_is_io(port)); - module_port = module_manager.add_port(module, port_info, ModuleManager::MODULE_GPOUT_PORT); - } else if ( (CIRCUIT_MODEL_PORT_INOUT == circuit_lib.port_type(port)) - && (true == circuit_lib.port_is_io(port)) ) { - module_port = module_manager.add_port(module, port_info, ModuleManager::MODULE_GPIO_PORT); + module_port = module_manager.add_port(module, port_info, + ModuleManager::MODULE_GPOUT_PORT); + } else if ((CIRCUIT_MODEL_PORT_INOUT == circuit_lib.port_type(port)) && + (true == circuit_lib.port_is_io(port))) { + module_port = module_manager.add_port(module, port_info, + ModuleManager::MODULE_GPIO_PORT); } /* Specify if the port can be mapped to an data signal */ @@ -186,23 +200,31 @@ ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager, /* Find other ports and add one by one */ /* Create a type-to-type map for ports */ - std::map port_type2type_map; - port_type2type_map[CIRCUIT_MODEL_PORT_INOUT] = ModuleManager::MODULE_INOUT_PORT; - port_type2type_map[CIRCUIT_MODEL_PORT_INPUT] = ModuleManager::MODULE_INPUT_PORT; - port_type2type_map[CIRCUIT_MODEL_PORT_CLOCK] = ModuleManager::MODULE_INPUT_PORT; - port_type2type_map[CIRCUIT_MODEL_PORT_SRAM] = ModuleManager::MODULE_INPUT_PORT; + std::map + port_type2type_map; + port_type2type_map[CIRCUIT_MODEL_PORT_INOUT] = + ModuleManager::MODULE_INOUT_PORT; + port_type2type_map[CIRCUIT_MODEL_PORT_INPUT] = + ModuleManager::MODULE_INPUT_PORT; + port_type2type_map[CIRCUIT_MODEL_PORT_CLOCK] = + ModuleManager::MODULE_INPUT_PORT; + port_type2type_map[CIRCUIT_MODEL_PORT_SRAM] = + ModuleManager::MODULE_INPUT_PORT; port_type2type_map[CIRCUIT_MODEL_PORT_BL] = ModuleManager::MODULE_INPUT_PORT; port_type2type_map[CIRCUIT_MODEL_PORT_BLB] = ModuleManager::MODULE_INPUT_PORT; port_type2type_map[CIRCUIT_MODEL_PORT_WL] = ModuleManager::MODULE_INPUT_PORT; port_type2type_map[CIRCUIT_MODEL_PORT_WLB] = ModuleManager::MODULE_INPUT_PORT; port_type2type_map[CIRCUIT_MODEL_PORT_WLR] = ModuleManager::MODULE_INPUT_PORT; - port_type2type_map[CIRCUIT_MODEL_PORT_OUTPUT] = ModuleManager::MODULE_OUTPUT_PORT; + port_type2type_map[CIRCUIT_MODEL_PORT_OUTPUT] = + ModuleManager::MODULE_OUTPUT_PORT; /* Input ports (ignore all the global ports when searching the circuit_lib */ for (const auto& kv : port_type2type_map) { - for (const auto& port : circuit_lib.model_ports_by_type(circuit_model, kv.first, true)) { - BasicPort port_info(circuit_lib.port_prefix(port), circuit_lib.port_size(port)); - module_manager.add_port(module, port_info, kv.second); + for (const auto& port : + circuit_lib.model_ports_by_type(circuit_model, kv.first, true)) { + BasicPort port_info(circuit_lib.port_prefix(port), + circuit_lib.port_size(port)); + module_manager.add_port(module, port_info, kv.second); } } @@ -218,10 +240,12 @@ ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager, * * This function is a wrapper of a more customizable function in the same name ******************************************************************************/ -ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model) { - - return add_circuit_model_to_module_manager(module_manager, circuit_lib, circuit_model, circuit_lib.model_name(circuit_model)); +ModuleId add_circuit_model_to_module_manager( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model) { + return add_circuit_model_to_module_manager( + module_manager, circuit_lib, circuit_model, + circuit_lib.model_name(circuit_model)); } /******************************************************************** @@ -230,7 +254,7 @@ ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager, * The reserved SRAM ports are mainly designed for RRAM-based FPGA, * which are shared across modules. * Note that different modules may require different size of reserved - * SRAM ports but their LSB must all start from 0 + * SRAM ports but their LSB must all start from 0 * +---------+ * reserved_sram_port[0:X] --->| ModuleA | * +---------+ @@ -240,40 +264,44 @@ ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager, * +---------+ * ********************************************************************/ -void add_reserved_sram_ports_to_module_manager(ModuleManager& module_manager, +void add_reserved_sram_ports_to_module_manager(ModuleManager& module_manager, const ModuleId& module_id, const size_t& port_size) { /* Add a reserved BLB port to the module */ - std::string blb_port_name = generate_reserved_sram_port_name(CIRCUIT_MODEL_PORT_BLB); - BasicPort blb_module_port(blb_port_name, port_size); + std::string blb_port_name = + generate_reserved_sram_port_name(CIRCUIT_MODEL_PORT_BLB); + BasicPort blb_module_port(blb_port_name, port_size); /* Add generated ports to the ModuleManager */ - module_manager.add_port(module_id, blb_module_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(module_id, blb_module_port, + ModuleManager::MODULE_INPUT_PORT); /* Add a reserved BLB port to the module */ - std::string wl_port_name = generate_reserved_sram_port_name(CIRCUIT_MODEL_PORT_WL); - BasicPort wl_module_port(wl_port_name, port_size); + std::string wl_port_name = + generate_reserved_sram_port_name(CIRCUIT_MODEL_PORT_WL); + BasicPort wl_module_port(wl_port_name, port_size); /* Add generated ports to the ModuleManager */ - module_manager.add_port(module_id, wl_module_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(module_id, wl_module_port, + ModuleManager::MODULE_INPUT_PORT); } /******************************************************************** * Add a list of ports that are used for formal verification to a module * in the module manager * - * The formal verification port will appear only when a pre-processing flag is defined - * This function will add the pre-processing flag along with the port + * The formal verification port will appear only when a pre-processing flag is + *defined This function will add the pre-processing flag along with the port ********************************************************************/ -void add_formal_verification_sram_ports_to_module_manager(ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const std::string& preproc_flag, - const size_t& port_size) { +void add_formal_verification_sram_ports_to_module_manager( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const std::string& preproc_flag, const size_t& port_size) { /* Create a port */ - std::string port_name = generate_formal_verification_sram_port_name(circuit_lib, sram_model); - BasicPort module_port(port_name, port_size); + std::string port_name = + generate_formal_verification_sram_port_name(circuit_lib, sram_model); + BasicPort module_port(port_name, port_size); /* Add generated ports to the ModuleManager */ - ModulePortId port_id = module_manager.add_port(module_id, module_port, ModuleManager::MODULE_INPUT_PORT); + ModulePortId port_id = module_manager.add_port( + module_id, module_port, ModuleManager::MODULE_INPUT_PORT); /* Add pre-processing flag if defined */ module_manager.set_port_preproc_flag(module_id, port_id, preproc_flag); } @@ -281,169 +309,189 @@ void add_formal_verification_sram_ports_to_module_manager(ModuleManager& module_ /******************************************************************** * Add a list of ports that are used for SRAM configuration to a module * in the module manager - * The type and names of added ports strongly depend on the + * The type and names of added ports strongly depend on the * organization of SRAMs. - * 1. Standalone SRAMs: - * two ports will be added, which are BL and WL + * 1. Standalone SRAMs: + * two ports will be added, which are BL and WL * 2. Scan-chain Flip-flops: - * two ports will be added, which are the head of scan-chain + * two ports will be added, which are the head of scan-chain * and the tail of scan-chain - * IMPORTANT: the port size will be forced to 1 in this case + * IMPORTANT: the port size will be forced to 1 in this case * because the head and tail are both 1-bit ports!!! * 3. Memory decoders: * 2-4 ports will be added, depending on the ports available in the SRAM - * Among these, two ports are mandatory: BL and WL + * Among these, two ports are mandatory: BL and WL * The other two ports are optional: BLB and WLB - * Note that the constraints are correletated to the checking rules + * Note that the constraints are correletated to the checking rules * in check_circuit_library() * 4. Frame-based memory: * - An Enable signal - * - An address port, whose size depends on the number of config bits + * - An address port, whose size depends on the number of config bits * and the maximum size of address ports of configurable children * - An data_in port (single-bit) ********************************************************************/ -void add_sram_ports_to_module_manager(ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type sram_orgz_type, - const size_t& num_config_bits) { - std::vector sram_port_names = generate_sram_port_names(circuit_lib, sram_model, sram_orgz_type); - size_t sram_port_size = generate_sram_port_size(sram_orgz_type, num_config_bits); +void add_sram_ports_to_module_manager( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type sram_orgz_type, const size_t& num_config_bits) { + std::vector sram_port_names = + generate_sram_port_names(circuit_lib, sram_model, sram_orgz_type); + size_t sram_port_size = + generate_sram_port_size(sram_orgz_type, num_config_bits); /* Add ports to the module manager */ switch (sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: { - for (const std::string& sram_port_name : sram_port_names) { - /* Add generated ports to the ModuleManager */ - BasicPort sram_port(sram_port_name, sram_port_size); - module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_INPUT_PORT); - } - break; - } - case CONFIG_MEM_SCAN_CHAIN: { - /* Note that configuration chain tail is an output while head is an input - * IMPORTANT: this is co-designed with function generate_sram_port_names() - * If the return vector is changed, the following codes MUST be adapted! - */ - VTR_ASSERT(2 == sram_port_names.size()); - size_t port_counter = 0; - for (const std::string& sram_port_name : sram_port_names) { - /* Add generated ports to the ModuleManager */ - BasicPort sram_port(sram_port_name, sram_port_size); - if (0 == port_counter) { - module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_INPUT_PORT); - } else { - VTR_ASSERT(1 == port_counter); - module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_OUTPUT_PORT); + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: { + for (const std::string& sram_port_name : sram_port_names) { + /* Add generated ports to the ModuleManager */ + BasicPort sram_port(sram_port_name, sram_port_size); + module_manager.add_port(module_id, sram_port, + ModuleManager::MODULE_INPUT_PORT); } - port_counter++; + break; } - break; - } - case CONFIG_MEM_FRAME_BASED: { - BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); - module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); + case CONFIG_MEM_SCAN_CHAIN: { + /* Note that configuration chain tail is an output while head is an input + * IMPORTANT: this is co-designed with function generate_sram_port_names() + * If the return vector is changed, the following codes MUST be adapted! + */ + VTR_ASSERT(2 == sram_port_names.size()); + size_t port_counter = 0; + for (const std::string& sram_port_name : sram_port_names) { + /* Add generated ports to the ModuleManager */ + BasicPort sram_port(sram_port_name, sram_port_size); + if (0 == port_counter) { + module_manager.add_port(module_id, sram_port, + ModuleManager::MODULE_INPUT_PORT); + } else { + VTR_ASSERT(1 == port_counter); + module_manager.add_port(module_id, sram_port, + ModuleManager::MODULE_OUTPUT_PORT); + } + port_counter++; + } + break; + } + case CONFIG_MEM_FRAME_BASED: { + BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); + module_manager.add_port(module_id, en_port, + ModuleManager::MODULE_INPUT_PORT); - BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), num_config_bits); - module_manager.add_port(module_id, addr_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), + num_config_bits); + module_manager.add_port(module_id, addr_port, + ModuleManager::MODULE_INPUT_PORT); - BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), 1); - module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), 1); + module_manager.add_port(module_id, din_port, + ModuleManager::MODULE_INPUT_PORT); - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization !\n"); - exit(1); + break; + } + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization !\n"); + exit(1); } } /******************************************************************** - * @brief Add a list of ports that are used for SRAM configuration to module + * @brief Add a list of ports that are used for SRAM configuration to module * in the module manager * @note - * This function is only applicable to programmable blocks, which are + * This function is only applicable to programmable blocks, which are * - Grid * - CBX/CBY * - SB - * @note - * The major difference between this function and the add_sram_ports_to_module_manager() - * is the size of sram ports to be added when QL memory bank is selected - * This function will merge/group BL/WLs by considering a memory bank organization - * at block-level + * @note + * The major difference between this function and the + *add_sram_ports_to_module_manager() is the size of sram ports to be added when + *QL memory bank is selected This function will merge/group BL/WLs by + *considering a memory bank organization at block-level ********************************************************************/ -void add_pb_sram_ports_to_module_manager(ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type sram_orgz_type, - const size_t& num_config_bits) { - std::vector sram_port_names = generate_sram_port_names(circuit_lib, sram_model, sram_orgz_type); - size_t sram_port_size = generate_pb_sram_port_size(sram_orgz_type, num_config_bits); +void add_pb_sram_ports_to_module_manager( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type sram_orgz_type, const size_t& num_config_bits) { + std::vector sram_port_names = + generate_sram_port_names(circuit_lib, sram_model, sram_orgz_type); + size_t sram_port_size = + generate_pb_sram_port_size(sram_orgz_type, num_config_bits); /* Add ports to the module manager */ switch (sram_orgz_type) { - case CONFIG_MEM_QL_MEMORY_BANK: - for (const std::string& sram_port_name : sram_port_names) { - /* Add generated ports to the ModuleManager */ - BasicPort sram_port(sram_port_name, sram_port_size); - /* For WL and WLR ports, we need to fine-tune it */ - if ( (CIRCUIT_MODEL_PORT_WL == circuit_lib.port_type(circuit_lib.model_port(sram_model, sram_port_name))) - || (CIRCUIT_MODEL_PORT_WLR == circuit_lib.port_type(circuit_lib.model_port(sram_model, sram_port_name))) ) { - sram_port.set_width(find_memory_wl_decoder_data_size(num_config_bits, sram_port_size)); + case CONFIG_MEM_QL_MEMORY_BANK: + for (const std::string& sram_port_name : sram_port_names) { + /* Add generated ports to the ModuleManager */ + BasicPort sram_port(sram_port_name, sram_port_size); + /* For WL and WLR ports, we need to fine-tune it */ + if ((CIRCUIT_MODEL_PORT_WL == + circuit_lib.port_type( + circuit_lib.model_port(sram_model, sram_port_name))) || + (CIRCUIT_MODEL_PORT_WLR == + circuit_lib.port_type( + circuit_lib.model_port(sram_model, sram_port_name)))) { + sram_port.set_width( + find_memory_wl_decoder_data_size(num_config_bits, sram_port_size)); + } + module_manager.add_port(module_id, sram_port, + ModuleManager::MODULE_INPUT_PORT); } - module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_INPUT_PORT); - } - break; - case CONFIG_MEM_STANDALONE: - case CONFIG_MEM_MEMORY_BANK: { - for (const std::string& sram_port_name : sram_port_names) { - /* Add generated ports to the ModuleManager */ - BasicPort sram_port(sram_port_name, sram_port_size); - module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_INPUT_PORT); - } - break; - } - case CONFIG_MEM_SCAN_CHAIN: { - /* Note that configuration chain tail is an output while head is an input - * IMPORTANT: this is co-designed with function generate_sram_port_names() - * If the return vector is changed, the following codes MUST be adapted! - */ - VTR_ASSERT(2 == sram_port_names.size()); - size_t port_counter = 0; - for (const std::string& sram_port_name : sram_port_names) { - /* Add generated ports to the ModuleManager */ - BasicPort sram_port(sram_port_name, sram_port_size); - if (0 == port_counter) { - module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_INPUT_PORT); - } else { - VTR_ASSERT(1 == port_counter); - module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_OUTPUT_PORT); + break; + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_MEMORY_BANK: { + for (const std::string& sram_port_name : sram_port_names) { + /* Add generated ports to the ModuleManager */ + BasicPort sram_port(sram_port_name, sram_port_size); + module_manager.add_port(module_id, sram_port, + ModuleManager::MODULE_INPUT_PORT); } - port_counter++; + break; } - break; - } - case CONFIG_MEM_FRAME_BASED: { - BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); - module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); + case CONFIG_MEM_SCAN_CHAIN: { + /* Note that configuration chain tail is an output while head is an input + * IMPORTANT: this is co-designed with function generate_sram_port_names() + * If the return vector is changed, the following codes MUST be adapted! + */ + VTR_ASSERT(2 == sram_port_names.size()); + size_t port_counter = 0; + for (const std::string& sram_port_name : sram_port_names) { + /* Add generated ports to the ModuleManager */ + BasicPort sram_port(sram_port_name, sram_port_size); + if (0 == port_counter) { + module_manager.add_port(module_id, sram_port, + ModuleManager::MODULE_INPUT_PORT); + } else { + VTR_ASSERT(1 == port_counter); + module_manager.add_port(module_id, sram_port, + ModuleManager::MODULE_OUTPUT_PORT); + } + port_counter++; + } + break; + } + case CONFIG_MEM_FRAME_BASED: { + BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); + module_manager.add_port(module_id, en_port, + ModuleManager::MODULE_INPUT_PORT); - BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), num_config_bits); - module_manager.add_port(module_id, addr_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), + num_config_bits); + module_manager.add_port(module_id, addr_port, + ModuleManager::MODULE_INPUT_PORT); - BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), 1); - module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), 1); + module_manager.add_port(module_id, din_port, + ModuleManager::MODULE_INPUT_PORT); - break; - } - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization !\n"); - exit(1); + break; + } + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization !\n"); + exit(1); } } @@ -455,43 +503,57 @@ void add_pb_sram_ports_to_module_manager(ModuleManager& module_manager, * This function will also check that each pb_type port is actually exist * in the linked circuit model *******************************************************************/ -void add_primitive_pb_type_ports_to_module_manager(ModuleManager& module_manager, - const ModuleId& module_id, - t_pb_type* cur_pb_type, - const VprDeviceAnnotation& vpr_device_annotation) { - - /* Find the inout ports required by the primitive pb_type, and add them to the module */ - std::vector pb_type_inout_ports = find_pb_type_ports_match_circuit_model_port_type(cur_pb_type, CIRCUIT_MODEL_PORT_INOUT, vpr_device_annotation); +void add_primitive_pb_type_ports_to_module_manager( + ModuleManager& module_manager, const ModuleId& module_id, + t_pb_type* cur_pb_type, const VprDeviceAnnotation& vpr_device_annotation) { + /* Find the inout ports required by the primitive pb_type, and add them to the + * module */ + std::vector pb_type_inout_ports = + find_pb_type_ports_match_circuit_model_port_type( + cur_pb_type, CIRCUIT_MODEL_PORT_INOUT, vpr_device_annotation); for (auto port : pb_type_inout_ports) { BasicPort module_port(generate_pb_type_port_name(port), port->num_pins); - module_manager.add_port(module_id, module_port, ModuleManager::MODULE_INOUT_PORT); + module_manager.add_port(module_id, module_port, + ModuleManager::MODULE_INOUT_PORT); /* Set the port to be wire-connection */ module_manager.set_port_is_wire(module_id, module_port.get_name(), true); } - /* Find the input ports required by the primitive pb_type, and add them to the module */ - std::vector pb_type_input_ports = find_pb_type_ports_match_circuit_model_port_type(cur_pb_type, CIRCUIT_MODEL_PORT_INPUT, vpr_device_annotation); + /* Find the input ports required by the primitive pb_type, and add them to the + * module */ + std::vector pb_type_input_ports = + find_pb_type_ports_match_circuit_model_port_type( + cur_pb_type, CIRCUIT_MODEL_PORT_INPUT, vpr_device_annotation); for (auto port : pb_type_input_ports) { BasicPort module_port(generate_pb_type_port_name(port), port->num_pins); - module_manager.add_port(module_id, module_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(module_id, module_port, + ModuleManager::MODULE_INPUT_PORT); /* Set the port to be wire-connection */ module_manager.set_port_is_wire(module_id, module_port.get_name(), true); } - /* Find the output ports required by the primitive pb_type, and add them to the module */ - std::vector pb_type_output_ports = find_pb_type_ports_match_circuit_model_port_type(cur_pb_type, CIRCUIT_MODEL_PORT_OUTPUT, vpr_device_annotation); + /* Find the output ports required by the primitive pb_type, and add them to + * the module */ + std::vector pb_type_output_ports = + find_pb_type_ports_match_circuit_model_port_type( + cur_pb_type, CIRCUIT_MODEL_PORT_OUTPUT, vpr_device_annotation); for (auto port : pb_type_output_ports) { BasicPort module_port(generate_pb_type_port_name(port), port->num_pins); - module_manager.add_port(module_id, module_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.add_port(module_id, module_port, + ModuleManager::MODULE_OUTPUT_PORT); /* Set the port to be wire-connection */ module_manager.set_port_is_wire(module_id, module_port.get_name(), true); } - /* Find the clock ports required by the primitive pb_type, and add them to the module */ - std::vector pb_type_clock_ports = find_pb_type_ports_match_circuit_model_port_type(cur_pb_type, CIRCUIT_MODEL_PORT_CLOCK, vpr_device_annotation); + /* Find the clock ports required by the primitive pb_type, and add them to the + * module */ + std::vector pb_type_clock_ports = + find_pb_type_ports_match_circuit_model_port_type( + cur_pb_type, CIRCUIT_MODEL_PORT_CLOCK, vpr_device_annotation); for (auto port : pb_type_clock_ports) { BasicPort module_port(generate_pb_type_port_name(port), port->num_pins); - module_manager.add_port(module_id, module_port, ModuleManager::MODULE_CLOCK_PORT); + module_manager.add_port(module_id, module_port, + ModuleManager::MODULE_CLOCK_PORT); /* Set the port to be wire-connection */ module_manager.set_port_is_wire(module_id, module_port.get_name(), true); } @@ -505,7 +567,7 @@ void add_primitive_pb_type_ports_to_module_manager(ModuleManager& module_manager * We just iterate over all the ports and add it to the module * with the naming convention *******************************************************************/ -void add_pb_type_ports_to_module_manager(ModuleManager& module_manager, +void add_pb_type_ports_to_module_manager(ModuleManager& module_manager, const ModuleId& module_id, t_pb_type* cur_pb_type) { /* Create a type-to-type mapping between module ports and pb_type ports */ @@ -516,24 +578,29 @@ void add_pb_type_ports_to_module_manager(ModuleManager& module_manager, for (int port = 0; port < cur_pb_type->num_ports; ++port) { t_port* pb_type_port = &(cur_pb_type->ports[port]); - BasicPort module_port(generate_pb_type_port_name(pb_type_port), pb_type_port->num_pins); - module_manager.add_port(module_id, module_port, port_type2type_map[pb_type_port->type]); + BasicPort module_port(generate_pb_type_port_name(pb_type_port), + pb_type_port->num_pins); + module_manager.add_port(module_id, module_port, + port_type2type_map[pb_type_port->type]); /* Set the port to be wire-connection */ module_manager.set_port_is_wire(module_id, module_port.get_name(), true); } } /******************************************************************** - * Identify if a net is a local wire inside a module: + * Identify if a net is a local wire inside a module: * A net is a local wire if it connects between two instances, - * It means that any of its source and sink modules should not include current module_id + * It means that any of its source and sink modules should not include current + *module_id *******************************************************************/ -bool module_net_is_local_wire(const ModuleManager& module_manager, - const ModuleId& module_id, const ModuleNetId& module_net) { - /* Check all the sink modules of the net, - * if we have a source module is the current module, this is not local wire +bool module_net_is_local_wire(const ModuleManager& module_manager, + const ModuleId& module_id, + const ModuleNetId& module_net) { + /* Check all the sink modules of the net, + * if we have a source module is the current module, this is not local wire */ - for (ModuleId src_module : module_manager.net_source_modules(module_id, module_net)) { + for (ModuleId src_module : + module_manager.net_source_modules(module_id, module_net)) { if (module_id == src_module) { /* Here, this is not a local wire */ return false; @@ -541,7 +608,8 @@ bool module_net_is_local_wire(const ModuleManager& module_manager, } /* Check all the sink modules of the net */ - for (ModuleId sink_module : module_manager.net_sink_modules(module_id, module_net)) { + for (ModuleId sink_module : + module_manager.net_sink_modules(module_id, module_net)) { if (module_id == sink_module) { /* Here, this is not a local wire */ return false; @@ -552,7 +620,7 @@ bool module_net_is_local_wire(const ModuleManager& module_manager, } /******************************************************************** - * Identify if a net is an output short connection inside a module: + * Identify if a net is an output short connection inside a module: * The short connection is defined as the direct connection * between two outputs port of the module * @@ -566,22 +634,25 @@ bool module_net_is_local_wire(const ModuleManager& module_manager, * +-----------------------------+ *******************************************************************/ -bool module_net_include_output_short_connection(const ModuleManager& module_manager, - const ModuleId& module_id, const ModuleNetId& module_net) { +bool module_net_include_output_short_connection( + const ModuleManager& module_manager, const ModuleId& module_id, + const ModuleNetId& module_net) { /* Check all the sink modules of the net */ size_t contain_num_module_output = 0; - for (ModuleId sink_module : module_manager.net_sink_modules(module_id, module_net)) { + for (ModuleId sink_module : + module_manager.net_sink_modules(module_id, module_net)) { if (module_id == sink_module) { contain_num_module_output++; } } - - /* If we have found more than 1 module outputs, it indicated output short connection! */ + + /* If we have found more than 1 module outputs, it indicated output short + * connection! */ return (1 < contain_num_module_output); } /******************************************************************** - * Identify if a net is a local short connection inside a module: + * Identify if a net is a local short connection inside a module: * The short connection is defined as the direct connection * between an input port of the module and an output port of the module * @@ -594,13 +665,15 @@ bool module_net_include_output_short_connection(const ModuleManager& module_mana * | | * +-----------------------------+ *******************************************************************/ -bool module_net_include_local_short_connection(const ModuleManager& module_manager, - const ModuleId& module_id, const ModuleNetId& module_net) { - /* Check all the sink modules of the net, - * if we have a source module is the current module, this is not local wire +bool module_net_include_local_short_connection( + const ModuleManager& module_manager, const ModuleId& module_id, + const ModuleNetId& module_net) { + /* Check all the sink modules of the net, + * if we have a source module is the current module, this is not local wire */ bool contain_module_input = false; - for (ModuleId src_module : module_manager.net_source_modules(module_id, module_net)) { + for (ModuleId src_module : + module_manager.net_source_modules(module_id, module_net)) { if (module_id == src_module) { contain_module_input = true; break; @@ -609,7 +682,8 @@ bool module_net_include_local_short_connection(const ModuleManager& module_manag /* Check all the sink modules of the net */ bool contain_module_output = false; - for (ModuleId sink_module : module_manager.net_sink_modules(module_id, module_net)) { + for (ModuleId sink_module : + module_manager.net_sink_modules(module_id, module_net)) { if (module_id == sink_module) { contain_module_output = true; break; @@ -620,76 +694,89 @@ bool module_net_include_local_short_connection(const ModuleManager& module_manag } /******************************************************************** - * Add the port-to-port connection between a pb_type and its linked circuit model - * This function is mainly used to create instance of the module for a pb_type + * Add the port-to-port connection between a pb_type and its linked circuit + *model This function is mainly used to create instance of the module for a + *pb_type * * Note: this function SHOULD be called after the pb_type_module is created - * and its child module is created! + * and its child module is created! *******************************************************************/ -void add_primitive_pb_type_module_nets(ModuleManager& module_manager, - const ModuleId& pb_type_module, - const ModuleId& child_module, - const size_t& child_instance_id, - const CircuitLibrary& circuit_lib, - t_pb_type* cur_pb_type, - const VprDeviceAnnotation& vpr_device_annotation) { +void add_primitive_pb_type_module_nets( + ModuleManager& module_manager, const ModuleId& pb_type_module, + const ModuleId& child_module, const size_t& child_instance_id, + const CircuitLibrary& circuit_lib, t_pb_type* cur_pb_type, + const VprDeviceAnnotation& vpr_device_annotation) { for (int iport = 0; iport < cur_pb_type->num_ports; ++iport) { t_port* pb_type_port = &(cur_pb_type->ports[iport]); /* Must have a linked circuit model port */ - VTR_ASSERT( CircuitPortId::INVALID() != vpr_device_annotation.pb_circuit_port(pb_type_port)); + VTR_ASSERT(CircuitPortId::INVALID() != + vpr_device_annotation.pb_circuit_port(pb_type_port)); /* Find the source port in pb_type module */ /* Get the src module port id */ - ModulePortId src_module_port_id = module_manager.find_module_port(pb_type_module, generate_pb_type_port_name(pb_type_port)); + ModulePortId src_module_port_id = module_manager.find_module_port( + pb_type_module, generate_pb_type_port_name(pb_type_port)); VTR_ASSERT(ModulePortId::INVALID() != src_module_port_id); - BasicPort src_port = module_manager.module_port(pb_type_module, src_module_port_id); + BasicPort src_port = + module_manager.module_port(pb_type_module, src_module_port_id); /* Get the des module port id */ - std::string des_module_port_name = circuit_lib.port_prefix(vpr_device_annotation.pb_circuit_port(pb_type_port)); - ModulePortId des_module_port_id = module_manager.find_module_port(child_module, des_module_port_name); + std::string des_module_port_name = circuit_lib.port_prefix( + vpr_device_annotation.pb_circuit_port(pb_type_port)); + ModulePortId des_module_port_id = + module_manager.find_module_port(child_module, des_module_port_name); VTR_ASSERT(ModulePortId::INVALID() != des_module_port_id); - BasicPort des_port = module_manager.module_port(child_module, des_module_port_id); + BasicPort des_port = + module_manager.module_port(child_module, des_module_port_id); /* Port size must match */ VTR_ASSERT(src_port.get_width() == des_port.get_width()); /* For each pin, generate the nets. * For non-output ports (input ports, inout ports and clock ports), - * src_port is the source of the net + * src_port is the source of the net * For output ports * src_port is the sink of the net */ switch (pb_type_port->type) { - case IN_PORT: - case INOUT_PORT: - for (size_t pin_id = 0; pin_id < src_port.pins().size(); ++pin_id) { - ModuleNetId net = module_manager.create_module_net(pb_type_module); - /* Add net source */ - module_manager.add_module_net_source(pb_type_module, net, pb_type_module, 0, src_module_port_id, src_port.pins()[pin_id]); - /* Add net sink */ - module_manager.add_module_net_sink(pb_type_module, net, child_module, child_instance_id, des_module_port_id, des_port.pins()[pin_id]); - } - break; - case OUT_PORT: - for (size_t pin_id = 0; pin_id < src_port.pins().size(); ++pin_id) { - ModuleNetId net = module_manager.create_module_net(pb_type_module); - /* Add net source */ - module_manager.add_module_net_source(pb_type_module, net, child_module, child_instance_id, des_module_port_id, des_port.pins()[pin_id]); - /* Add net sink */ - module_manager.add_module_net_sink(pb_type_module, net, pb_type_module, 0, src_module_port_id, src_port.pins()[pin_id]); - } - break; - default: - VTR_LOG_ERROR("Invalid port of pb_type!\n"); - exit(1); + case IN_PORT: + case INOUT_PORT: + for (size_t pin_id = 0; pin_id < src_port.pins().size(); ++pin_id) { + ModuleNetId net = module_manager.create_module_net(pb_type_module); + /* Add net source */ + module_manager.add_module_net_source( + pb_type_module, net, pb_type_module, 0, src_module_port_id, + src_port.pins()[pin_id]); + /* Add net sink */ + module_manager.add_module_net_sink( + pb_type_module, net, child_module, child_instance_id, + des_module_port_id, des_port.pins()[pin_id]); + } + break; + case OUT_PORT: + for (size_t pin_id = 0; pin_id < src_port.pins().size(); ++pin_id) { + ModuleNetId net = module_manager.create_module_net(pb_type_module); + /* Add net source */ + module_manager.add_module_net_source( + pb_type_module, net, child_module, child_instance_id, + des_module_port_id, des_port.pins()[pin_id]); + /* Add net sink */ + module_manager.add_module_net_sink( + pb_type_module, net, pb_type_module, 0, src_module_port_id, + src_port.pins()[pin_id]); + } + break; + default: + VTR_LOG_ERROR("Invalid port of pb_type!\n"); + exit(1); } - } + } } /******************************************************************** - * Add the port-to-port connection between a logic module - * and a memory module - * Create nets to wire SRAM ports between logic module and memory module + * Add the port-to-port connection between a logic module + * and a memory module + * Create nets to wire SRAM ports between logic module and memory module * * The information about SRAM ports of logic module are stored in the * mem_output_bus_ports, where element [0] denotes the SRAM port while @@ -706,42 +793,42 @@ void add_primitive_pb_type_module_nets(ModuleManager& module_manager, * the SRAM ports of memory module * * Note: this function SHOULD be called after the pb_type_module is created - * and its child module (logic_module and memory_module) is created! + * and its child module (logic_module and memory_module) is created! * * Note: this function only handle either SRAM or SRAMb ports. - * So, this function may be called twice to complete the wiring + * So, this function may be called twice to complete the wiring *******************************************************************/ -static -void add_module_nets_between_logic_and_memory_sram_ports(ModuleManager& module_manager, - const ModuleId& parent_module, - const ModuleId& logic_module, - const size_t& logic_instance_id, - const ModuleId& memory_module, - const size_t& memory_instance_id, - const std::vector& logic_module_sram_port_ids, - const ModulePortId& mem_module_sram_port_id) { +static void add_module_nets_between_logic_and_memory_sram_ports( + ModuleManager& module_manager, const ModuleId& parent_module, + const ModuleId& logic_module, const size_t& logic_instance_id, + const ModuleId& memory_module, const size_t& memory_instance_id, + const std::vector& logic_module_sram_port_ids, + const ModulePortId& mem_module_sram_port_id) { /* Find mem_output_bus ports in logic module */ std::vector logic_module_sram_ports; - for (const ModulePortId& logic_module_sram_port_id : logic_module_sram_port_ids) { - logic_module_sram_ports.push_back(module_manager.module_port(logic_module, logic_module_sram_port_id)); + for (const ModulePortId& logic_module_sram_port_id : + logic_module_sram_port_ids) { + logic_module_sram_ports.push_back( + module_manager.module_port(logic_module, logic_module_sram_port_id)); } - + /* Create a list of virtual ports to align with the SRAM port of logic module * Physical ports: * * logic_module_sram_port[0] logic_module_sram_port[1] * - * LSB[0]------------>MSB[0] LSB------------------>MSB + * LSB[0]------------>MSB[0] LSB------------------>MSB * * memory_sram_port - * LSBY---------------------------------------------->MSBY + * LSBY---------------------------------------------->MSBY * * Virtual ports: * mem_module_sram_port[0] mem_module_sram_port[1] - * LSBY--------------->MSBX MSBX+1------------------>MSBY + * LSBY--------------->MSBX MSBX+1------------------>MSBY * */ - BasicPort mem_module_port = module_manager.module_port(memory_module, mem_module_sram_port_id); + BasicPort mem_module_port = + module_manager.module_port(memory_module, mem_module_sram_port_id); std::vector virtual_mem_module_ports; /* Create a counter for the LSB of virtual ports */ @@ -749,7 +836,8 @@ void add_module_nets_between_logic_and_memory_sram_ports(ModuleManager& module_m for (const BasicPort& logic_module_sram_port : logic_module_sram_ports) { BasicPort virtual_port; virtual_port.set_name(mem_module_port.get_name()); - virtual_port.set_width(port_lsb, port_lsb + logic_module_sram_port.get_width() - 1); + virtual_port.set_width(port_lsb, + port_lsb + logic_module_sram_port.get_width() - 1); virtual_mem_module_ports.push_back(virtual_port); port_lsb = virtual_port.get_msb() + 1; } @@ -757,25 +845,36 @@ void add_module_nets_between_logic_and_memory_sram_ports(ModuleManager& module_m VTR_ASSERT(port_lsb == mem_module_port.get_msb() + 1); /* Wire port to port */ - for (size_t port_index = 0; port_index < logic_module_sram_ports.size(); ++port_index) { + for (size_t port_index = 0; port_index < logic_module_sram_ports.size(); + ++port_index) { /* Create a net for each pin */ - for (size_t pin_id = 0; pin_id < logic_module_sram_ports[port_index].pins().size(); ++pin_id) { + for (size_t pin_id = 0; + pin_id < logic_module_sram_ports[port_index].pins().size(); ++pin_id) { ModuleNetId net = module_manager.create_module_net(parent_module); /* TODO: Give a name to make it clear */ - std::string net_name = module_manager.module_name(logic_module) + std::string("_") + std::to_string(logic_instance_id) + std::string("_") + logic_module_sram_ports[port_index].get_name(); + std::string net_name = + module_manager.module_name(logic_module) + std::string("_") + + std::to_string(logic_instance_id) + std::string("_") + + logic_module_sram_ports[port_index].get_name(); module_manager.set_net_name(parent_module, net, net_name); /* Add net source */ - module_manager.add_module_net_source(parent_module, net, logic_module, logic_instance_id, logic_module_sram_port_ids[port_index], logic_module_sram_ports[port_index].pins()[pin_id]); + module_manager.add_module_net_source( + parent_module, net, logic_module, logic_instance_id, + logic_module_sram_port_ids[port_index], + logic_module_sram_ports[port_index].pins()[pin_id]); /* Add net sink */ - module_manager.add_module_net_sink(parent_module, net, memory_module, memory_instance_id, mem_module_sram_port_id, virtual_mem_module_ports[port_index].pins()[pin_id]); + module_manager.add_module_net_sink( + parent_module, net, memory_module, memory_instance_id, + mem_module_sram_port_id, + virtual_mem_module_ports[port_index].pins()[pin_id]); } } } /******************************************************************** - * Add the port-to-port connection between a logic module - * and a memory module - * Create nets to wire SRAM ports between logic module and memory module + * Add the port-to-port connection between a logic module + * and a memory module + * Create nets to wire SRAM ports between logic module and memory module * * * +---------+ +--------+ @@ -786,87 +885,106 @@ void add_module_nets_between_logic_and_memory_sram_ports(ModuleManager& module_m * +---------+ +--------+ * * Note: this function SHOULD be called after the pb_type_module is created - * and its child module (logic_module and memory_module) is created! + * and its child module (logic_module and memory_module) is created! * *******************************************************************/ -void add_module_nets_between_logic_and_memory_sram_bus(ModuleManager& module_manager, - const ModuleId& parent_module, - const ModuleId& logic_module, - const size_t& logic_instance_id, - const ModuleId& memory_module, - const size_t& memory_instance_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& logic_model) { - +void add_module_nets_between_logic_and_memory_sram_bus( + ModuleManager& module_manager, const ModuleId& parent_module, + const ModuleId& logic_module, const size_t& logic_instance_id, + const ModuleId& memory_module, const size_t& memory_instance_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& logic_model) { /* Connect SRAM port */ /* Find SRAM ports in the circuit model for logic module */ std::vector logic_model_sram_port_names; /* Regular sram port goes first */ - for (CircuitPortId regular_sram_port : find_circuit_regular_sram_ports(circuit_lib, logic_model)) { - logic_model_sram_port_names.push_back(circuit_lib.port_prefix(regular_sram_port)); + for (CircuitPortId regular_sram_port : + find_circuit_regular_sram_ports(circuit_lib, logic_model)) { + logic_model_sram_port_names.push_back( + circuit_lib.port_prefix(regular_sram_port)); } /* Mode-select sram port goes first */ - for (CircuitPortId mode_select_sram_port : find_circuit_mode_select_sram_ports(circuit_lib, logic_model)) { - logic_model_sram_port_names.push_back(circuit_lib.port_prefix(mode_select_sram_port)); + for (CircuitPortId mode_select_sram_port : + find_circuit_mode_select_sram_ports(circuit_lib, logic_model)) { + logic_model_sram_port_names.push_back( + circuit_lib.port_prefix(mode_select_sram_port)); } /* Find the port ids in the memory */ std::vector logic_module_sram_port_ids; - for (const std::string& logic_model_sram_port_name : logic_model_sram_port_names) { + for (const std::string& logic_model_sram_port_name : + logic_model_sram_port_names) { /* Skip non-exist ports */ - if (ModulePortId::INVALID() == module_manager.find_module_port(logic_module, logic_model_sram_port_name)) { + if (ModulePortId::INVALID() == + module_manager.find_module_port(logic_module, + logic_model_sram_port_name)) { continue; } - logic_module_sram_port_ids.push_back(module_manager.find_module_port(logic_module, logic_model_sram_port_name)); + logic_module_sram_port_ids.push_back(module_manager.find_module_port( + logic_module, logic_model_sram_port_name)); } /* Get the SRAM port name of memory model */ - /* This should be a constant expression and it should be the same for all the memory module! */ - std::string memory_model_sram_port_name = generate_configurable_memory_data_out_name(); - /* Find the corresponding ports in memory module */ - ModulePortId mem_module_sram_port_id = module_manager.find_module_port(memory_module, memory_model_sram_port_name); + /* This should be a constant expression and it should be the same for all the + * memory module! */ + std::string memory_model_sram_port_name = + generate_configurable_memory_data_out_name(); + /* Find the corresponding ports in memory module */ + ModulePortId mem_module_sram_port_id = + module_manager.find_module_port(memory_module, memory_model_sram_port_name); /* Do wiring only when we have sram ports */ - if ( (false == logic_module_sram_port_ids.empty()) - || (ModulePortId::INVALID() == mem_module_sram_port_id) ) { - add_module_nets_between_logic_and_memory_sram_ports(module_manager, parent_module, - logic_module, logic_instance_id, - memory_module, memory_instance_id, - logic_module_sram_port_ids, mem_module_sram_port_id); + if ((false == logic_module_sram_port_ids.empty()) || + (ModulePortId::INVALID() == mem_module_sram_port_id)) { + add_module_nets_between_logic_and_memory_sram_ports( + module_manager, parent_module, logic_module, logic_instance_id, + memory_module, memory_instance_id, logic_module_sram_port_ids, + mem_module_sram_port_id); } /* Connect SRAMb port */ /* Find SRAM ports in the circuit model for logic module */ std::vector logic_model_sramb_port_names; /* Regular sram port goes first */ - for (CircuitPortId regular_sram_port : find_circuit_regular_sram_ports(circuit_lib, logic_model)) { - logic_model_sramb_port_names.push_back(circuit_lib.port_prefix(regular_sram_port) + std::string(INV_PORT_POSTFIX)); + for (CircuitPortId regular_sram_port : + find_circuit_regular_sram_ports(circuit_lib, logic_model)) { + logic_model_sramb_port_names.push_back( + circuit_lib.port_prefix(regular_sram_port) + + std::string(INV_PORT_POSTFIX)); } /* Mode-select sram port goes first */ - for (CircuitPortId mode_select_sram_port : find_circuit_mode_select_sram_ports(circuit_lib, logic_model)) { - logic_model_sramb_port_names.push_back(circuit_lib.port_prefix(mode_select_sram_port) + std::string(INV_PORT_POSTFIX)); + for (CircuitPortId mode_select_sram_port : + find_circuit_mode_select_sram_ports(circuit_lib, logic_model)) { + logic_model_sramb_port_names.push_back( + circuit_lib.port_prefix(mode_select_sram_port) + + std::string(INV_PORT_POSTFIX)); } /* Find the port ids in the memory */ std::vector logic_module_sramb_port_ids; - for (const std::string& logic_model_sramb_port_name : logic_model_sramb_port_names) { + for (const std::string& logic_model_sramb_port_name : + logic_model_sramb_port_names) { /* Skip non-exist ports */ - if (ModulePortId::INVALID() == module_manager.find_module_port(logic_module, logic_model_sramb_port_name)) { + if (ModulePortId::INVALID() == + module_manager.find_module_port(logic_module, + logic_model_sramb_port_name)) { continue; } - logic_module_sramb_port_ids.push_back(module_manager.find_module_port(logic_module, logic_model_sramb_port_name)); + logic_module_sramb_port_ids.push_back(module_manager.find_module_port( + logic_module, logic_model_sramb_port_name)); } /* Get the SRAM port name of memory model */ - std::string memory_model_sramb_port_name = generate_configurable_memory_inverted_data_out_name(); - /* Find the corresponding ports in memory module */ - ModulePortId mem_module_sramb_port_id = module_manager.find_module_port(memory_module, memory_model_sramb_port_name); + std::string memory_model_sramb_port_name = + generate_configurable_memory_inverted_data_out_name(); + /* Find the corresponding ports in memory module */ + ModulePortId mem_module_sramb_port_id = module_manager.find_module_port( + memory_module, memory_model_sramb_port_name); /* Do wiring only when we have sramb ports */ - if ( (false == logic_module_sramb_port_ids.empty()) - && (ModulePortId::INVALID() != mem_module_sramb_port_id) ) { - add_module_nets_between_logic_and_memory_sram_ports(module_manager, parent_module, - logic_module, logic_instance_id, - memory_module, memory_instance_id, - logic_module_sramb_port_ids, mem_module_sramb_port_id); + if ((false == logic_module_sramb_port_ids.empty()) && + (ModulePortId::INVALID() != mem_module_sramb_port_id)) { + add_module_nets_between_logic_and_memory_sram_ports( + module_manager, parent_module, logic_module, logic_instance_id, + memory_module, memory_instance_id, logic_module_sramb_port_ids, + mem_module_sramb_port_id); } } @@ -879,34 +997,36 @@ void add_module_nets_between_logic_and_memory_sram_bus(ModuleManager& module_man * | | | * v v v * +--------+ +--------+ +--------+ - * | Memory | | Memory | ... | Memory | + * | Memory | | Memory | ... | Memory | * | Module | | Module | | Module | - * | [0] | | [1] | | [N-1] | + * | [0] | | [1] | | [N-1] | * +--------+ +--------+ +--------+ * ^ ^ ^ * | | | * +------------+----------------------+ * | * WL/WLR - * - * Note: + * + * Note: * - This function will do the connection for only one type of the port, - * either BL or WL. So, you should call this function twice to complete + * either BL or WL. So, you should call this function twice to complete * the configuration bus connection!!! * *********************************************************************/ -void add_module_nets_cmos_flatten_memory_config_bus(ModuleManager& module_manager, - const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type) { +void add_module_nets_cmos_flatten_memory_config_bus( + ModuleManager& module_manager, const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& config_port_type) { /* A counter for the current pin id for the source port of parent module */ size_t cur_src_pin_id = 0; /* Find the port name of parent module */ - std::string src_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - ModuleId net_src_module_id = parent_module; + std::string src_port_name = + generate_sram_port_name(sram_orgz_type, config_port_type); + ModuleId net_src_module_id = parent_module; size_t net_src_instance_id = 0; - ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + ModulePortId net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); /* We may not be able to find WLR port, return now */ if (!net_src_port_id) { @@ -914,32 +1034,42 @@ void add_module_nets_cmos_flatten_memory_config_bus(ModuleManager& module_manage } /* Get the pin id for source port */ - BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); - for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) { + for (size_t mem_index = 0; + mem_index < module_manager.configurable_children(parent_module).size(); + ++mem_index) { ModuleId net_sink_module_id; size_t net_sink_instance_id; ModulePortId net_sink_port_id; /* Find the port name of next memory module */ - std::string sink_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; - net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + std::string sink_port_name = + generate_sram_port_name(sram_orgz_type, config_port_type); + net_sink_module_id = + module_manager.configurable_children(parent_module)[mem_index]; + net_sink_instance_id = + module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); /* Get the pin id for sink port */ - BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); - + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); + /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < net_sink_port.pins().size(); ++pin_id) { /* Create a net and add source and sink to it */ - ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, - net_src_module_id, net_src_instance_id, - net_src_port_id, net_src_port.pins()[cur_src_pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, parent_module, net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[cur_src_pin_id]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ - module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[pin_id]); /* Move to the next src pin */ cur_src_pin_id++; @@ -951,63 +1081,75 @@ void add_module_nets_cmos_flatten_memory_config_bus(ModuleManager& module_manage } /******************************************************************** - * @brief Connect all the Bit Lines (BL) of child memory modules under the + * @brief Connect all the Bit Lines (BL) of child memory modules under the * parent module in a memory bank organization * * BL<0> BL<1> BL * | | | * v v v * +--------+ +--------+ +--------+ - * | Memory | | Memory | ... | Memory | + * | Memory | | Memory | ... | Memory | * | Module | | Module | | Module | - * | [0,0] | | [1,0] | | [i,0] | + * | [0,0] | | [1,0] | | [i,0] | * +--------+ +--------+ +--------+ * | | | * v v v * +--------+ +--------+ +--------+ - * | Memory | | Memory | ... | Memory | + * | Memory | | Memory | ... | Memory | * | Module | | Module | | Module | - * | [0,1] | | [1,1] | | [i,1] | + * | [0,1] | | [1,1] | | [i,1] | * +--------+ +--------+ +--------+ * *********************************************************************/ -void add_module_nets_cmos_memory_bank_bl_config_bus(ModuleManager& module_manager, - const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type) { +void add_module_nets_cmos_memory_bank_bl_config_bus( + ModuleManager& module_manager, const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& config_port_type) { /* A counter for the current pin id for the source port of parent module */ size_t cur_src_pin_id = 0; /* Find the port name of parent module */ - std::string src_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - ModuleId net_src_module_id = parent_module; + std::string src_port_name = + generate_sram_port_name(sram_orgz_type, config_port_type); + ModuleId net_src_module_id = parent_module; size_t net_src_instance_id = 0; - ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + ModulePortId net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); /* Get the pin id for source port */ - BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); - for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) { + for (size_t mem_index = 0; + mem_index < module_manager.configurable_children(parent_module).size(); + ++mem_index) { /* Find the port name of next memory module */ - std::string sink_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - ModuleId net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; - size_t net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; - ModulePortId net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + std::string sink_port_name = + generate_sram_port_name(sram_orgz_type, config_port_type); + ModuleId net_sink_module_id = + module_manager.configurable_children(parent_module)[mem_index]; + size_t net_sink_instance_id = + module_manager.configurable_child_instances(parent_module)[mem_index]; + ModulePortId net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); /* Get the pin id for sink port */ - BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); - + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); + /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < net_sink_port.pins().size(); ++pin_id) { - size_t cur_bl_src_pin_id = cur_src_pin_id % net_src_port.pins().size(); + size_t cur_bl_src_pin_id = cur_src_pin_id % net_src_port.pins().size(); /* Create a net and add source and sink to it */ - ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, - net_src_module_id, net_src_instance_id, - net_src_port_id, net_src_port.pins()[cur_bl_src_pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, parent_module, net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[cur_bl_src_pin_id]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ - module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[pin_id]); /* Move to the next src pin */ cur_src_pin_id++; @@ -1016,13 +1158,13 @@ void add_module_nets_cmos_memory_bank_bl_config_bus(ModuleManager& module_manage } /******************************************************************** - * @brief Connect all the Word Lines (WL) of child memory modules under the + * @brief Connect all the Word Lines (WL) of child memory modules under the * parent module in a memory bank organization * * +--------+ +--------+ +--------+ - * | Memory | | Memory | ... | Memory | + * | Memory | | Memory | ... | Memory | * | Module | | Module | | Module | - * | [0,0] | | [1,0] | | [i,0] | + * | [0,0] | | [1,0] | | [i,0] | * +--------+ +--------+ +--------+ * ^ ^ ^ * | | | @@ -1031,9 +1173,9 @@ void add_module_nets_cmos_memory_bank_bl_config_bus(ModuleManager& module_manage * WL<0>/WLR<0> * * +--------+ +--------+ +--------+ - * | Memory | | Memory | ... | Memory | + * | Memory | | Memory | ... | Memory | * | Module | | Module | | Module | - * | [0,1] | | [1,1] | | [i,1] | + * | [0,1] | | [1,1] | | [i,1] | * +--------+ +--------+ +--------+ * ^ ^ ^ * | | | @@ -1042,21 +1184,25 @@ void add_module_nets_cmos_memory_bank_bl_config_bus(ModuleManager& module_manage * WL<1>/WLR<1> * *********************************************************************/ -void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manager, - const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type) { +void add_module_nets_cmos_memory_bank_wl_config_bus( + ModuleManager& module_manager, const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& config_port_type) { /* A counter for the current pin id for the source port of parent module */ size_t cur_src_pin_id = 0; /* Find the port name of parent module */ - std::string src_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - std::string bl_port_name = generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + std::string src_port_name = + generate_sram_port_name(sram_orgz_type, config_port_type); + std::string bl_port_name = + generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_BL); - ModuleId net_src_module_id = parent_module; + ModuleId net_src_module_id = parent_module; size_t net_src_instance_id = 0; - ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); - ModulePortId net_bl_port_id = module_manager.find_module_port(net_src_module_id, bl_port_name); + ModulePortId net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); + ModulePortId net_bl_port_id = + module_manager.find_module_port(net_src_module_id, bl_port_name); /* We may not be able to find WLR port, return now */ if (!net_src_port_id) { @@ -1064,30 +1210,42 @@ void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manage } /* Get the pin id for source port */ - BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); - BasicPort net_bl_port = module_manager.module_port(net_src_module_id, net_bl_port_id); + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); + BasicPort net_bl_port = + module_manager.module_port(net_src_module_id, net_bl_port_id); - for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) { + for (size_t mem_index = 0; + mem_index < module_manager.configurable_children(parent_module).size(); + ++mem_index) { /* Find the port name of next memory module */ - std::string sink_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - ModuleId net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; - size_t net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; - ModulePortId net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + std::string sink_port_name = + generate_sram_port_name(sram_orgz_type, config_port_type); + ModuleId net_sink_module_id = + module_manager.configurable_children(parent_module)[mem_index]; + size_t net_sink_instance_id = + module_manager.configurable_child_instances(parent_module)[mem_index]; + ModulePortId net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); /* Get the pin id for sink port */ - BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); - + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); + /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < net_sink_port.pins().size(); ++pin_id) { - size_t cur_wl_src_pin_id = std::floor(cur_src_pin_id / net_bl_port.pins().size()); + size_t cur_wl_src_pin_id = + std::floor(cur_src_pin_id / net_bl_port.pins().size()); /* Create a net and add source and sink to it */ - ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, - net_src_module_id, net_src_instance_id, - net_src_port_id, net_src_port.pins()[cur_wl_src_pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, parent_module, net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[cur_wl_src_pin_id]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ - module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[pin_id]); /* Move to the next src pin */ cur_src_pin_id++; @@ -1097,11 +1255,11 @@ void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manage /******************************************************************** * Connect all the memory modules under the parent module in a chain - * + * * +--------+ +--------+ +--------+ * ccff_head --->| Memory |--->| Memory |--->... --->| Memory |----> ccff_tail * | Module | | Module | | Module | - * | [0] | | [1] | | [N-1] | + * | [0] | | [1] | | [N-1] | * +--------+ +--------+ +--------+ * For the 1st memory module: * net source is the configuration chain head of the primitive module @@ -1111,10 +1269,12 @@ void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manage * net source is the configuration chain tail of the previous memory module * net sink is the configuration chain head of the next memory module *********************************************************************/ -void add_module_nets_cmos_memory_chain_config_bus(ModuleManager& module_manager, - const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type) { - for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) { +void add_module_nets_cmos_memory_chain_config_bus( + ModuleManager& module_manager, const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type) { + for (size_t mem_index = 0; + mem_index < module_manager.configurable_children(parent_module).size(); + ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; ModulePortId net_src_port_id; @@ -1125,43 +1285,60 @@ void add_module_nets_cmos_memory_chain_config_bus(ModuleManager& module_manager, if (0 == mem_index) { /* Find the port name of configuration chain head */ - std::string src_port_name = generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_INPUT); - net_src_module_id = parent_module; + std::string src_port_name = + generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_INPUT); + net_src_module_id = parent_module; net_src_instance_id = 0; - net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = generate_configuration_chain_head_name(); - net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; - net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + net_sink_module_id = + module_manager.configurable_children(parent_module)[mem_index]; + net_sink_instance_id = + module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); } else { /* Find the port name of previous memory module */ std::string src_port_name = generate_configuration_chain_tail_name(); - net_src_module_id = module_manager.configurable_children(parent_module)[mem_index - 1]; - net_src_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index - 1]; - net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + net_src_module_id = + module_manager.configurable_children(parent_module)[mem_index - 1]; + net_src_instance_id = module_manager.configurable_child_instances( + parent_module)[mem_index - 1]; + net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = generate_configuration_chain_head_name(); - net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; - net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + net_sink_module_id = + module_manager.configurable_children(parent_module)[mem_index]; + net_sink_instance_id = + module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); } /* Get the pin id for source port */ - BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); /* Get the pin id for sink port */ - BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); /* Port sizes of source and sink should match */ VTR_ASSERT(net_src_port.get_width() == net_sink_port.get_width()); - + /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) { /* Create a net and add source and sink to it */ - ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, parent_module, net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[pin_id]); /* Add net sink */ - module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[pin_id]); } } @@ -1171,29 +1348,40 @@ void add_module_nets_cmos_memory_chain_config_bus(ModuleManager& module_manager, */ /* Find the port name of previous memory module */ std::string src_port_name = generate_configuration_chain_tail_name(); - ModuleId net_src_module_id = module_manager.configurable_children(parent_module).back(); - size_t net_src_instance_id = module_manager.configurable_child_instances(parent_module).back(); - ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + ModuleId net_src_module_id = + module_manager.configurable_children(parent_module).back(); + size_t net_src_instance_id = + module_manager.configurable_child_instances(parent_module).back(); + ModulePortId net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ - std::string sink_port_name = generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_OUTPUT); - ModuleId net_sink_module_id = parent_module; + std::string sink_port_name = + generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_OUTPUT); + ModuleId net_sink_module_id = parent_module; size_t net_sink_instance_id = 0; - ModulePortId net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + ModulePortId net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); /* Get the pin id for source port */ - BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); /* Get the pin id for sink port */ - BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); /* Port sizes of source and sink should match */ VTR_ASSERT(net_src_port.get_width() == net_sink_port.get_width()); - + /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) { /* Create a net and add source and sink to it */ - ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, parent_module, net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[pin_id]); /* Add net sink */ - module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[pin_id]); } } @@ -1205,7 +1393,7 @@ void add_module_nets_cmos_memory_chain_config_bus(ModuleManager& module_manager, * * EN ADDR DATA_IN * | | | - * v v v + * v v v * +-----------------------------+ * | Memory Module | * | [0] | @@ -1216,46 +1404,51 @@ void add_module_nets_cmos_memory_chain_config_bus(ModuleManager& module_manager, * - This function is ONLY applicable to single configurable child case!!! * *********************************************************************/ -static -void add_module_nets_cmos_memory_frame_short_config_bus(ModuleManager& module_manager, - const ModuleId& parent_module) { - std::vector configurable_children = module_manager.configurable_children(parent_module); +static void add_module_nets_cmos_memory_frame_short_config_bus( + ModuleManager& module_manager, const ModuleId& parent_module) { + std::vector configurable_children = + module_manager.configurable_children(parent_module); VTR_ASSERT(1 == configurable_children.size()); - ModuleId child_module = configurable_children[0]; + ModuleId child_module = configurable_children[0]; /* Connect the enable (EN) port of the parent module * to the EN port of memory module */ - ModulePortId parent_en_port = module_manager.find_module_port(parent_module, std::string(DECODER_ENABLE_PORT_NAME)); - ModulePortId child_en_port = module_manager.find_module_port(child_module, std::string(DECODER_ENABLE_PORT_NAME)); - add_module_bus_nets(module_manager, parent_module, - parent_module, 0, parent_en_port, - child_module, 0, child_en_port); + ModulePortId parent_en_port = module_manager.find_module_port( + parent_module, std::string(DECODER_ENABLE_PORT_NAME)); + ModulePortId child_en_port = module_manager.find_module_port( + child_module, std::string(DECODER_ENABLE_PORT_NAME)); + add_module_bus_nets(module_manager, parent_module, parent_module, 0, + parent_en_port, child_module, 0, child_en_port); - /* Connect the address port of the parent module to the child module address port */ - ModulePortId parent_addr_port = module_manager.find_module_port(parent_module, std::string(DECODER_ADDRESS_PORT_NAME)); - ModulePortId child_addr_port = module_manager.find_module_port(child_module, std::string(DECODER_ADDRESS_PORT_NAME)); - add_module_bus_nets(module_manager, parent_module, - parent_module, 0, parent_addr_port, - child_module, 0, child_addr_port); + /* Connect the address port of the parent module to the child module address + * port */ + ModulePortId parent_addr_port = module_manager.find_module_port( + parent_module, std::string(DECODER_ADDRESS_PORT_NAME)); + ModulePortId child_addr_port = module_manager.find_module_port( + child_module, std::string(DECODER_ADDRESS_PORT_NAME)); + add_module_bus_nets(module_manager, parent_module, parent_module, 0, + parent_addr_port, child_module, 0, child_addr_port); - /* Connect the data_in (Din) of parent module to the data_in of the memory module + /* Connect the data_in (Din) of parent module to the data_in of the memory + * module */ - ModulePortId parent_din_port = module_manager.find_module_port(parent_module, std::string(DECODER_DATA_IN_PORT_NAME)); - ModulePortId child_din_port = module_manager.find_module_port(child_module, std::string(DECODER_DATA_IN_PORT_NAME)); - add_module_bus_nets(module_manager, parent_module, - parent_module, 0, parent_din_port, - child_module, 0, child_din_port); + ModulePortId parent_din_port = module_manager.find_module_port( + parent_module, std::string(DECODER_DATA_IN_PORT_NAME)); + ModulePortId child_din_port = module_manager.find_module_port( + child_module, std::string(DECODER_DATA_IN_PORT_NAME)); + add_module_bus_nets(module_manager, parent_module, parent_module, 0, + parent_din_port, child_module, 0, child_din_port); } /******************************************************************** - * This function will - * - Add a frame decoder to the parent module + * This function will + * - Add a frame decoder to the parent module * - If the decoder exists in the library, we use the module * - If the decoder does not exist, we create a new module and use it * - create nets for the following types of connections: - * - Connect the EN signal, first few bits of address of parent module + * - Connect the EN signal, first few bits of address of parent module * to the frame decoder inputs * - Connect the enable (EN) port of memory modules under the parent module * to the frame decoder outputs @@ -1264,7 +1457,7 @@ void add_module_nets_cmos_memory_frame_short_config_bus(ModuleManager& module_ma * * EN ADDR[X - 1: X - log(N)/log2] * | | - * v v + * v v * +--------------------------------------------+ * | Frame-based decoder | * | | @@ -1272,14 +1465,14 @@ void add_module_nets_cmos_memory_frame_short_config_bus(ModuleManager& module_ma * +--------------------------------------------+ * | * +-------------+--------------------+ - * | | | - * Din | Din | Din | + * | | | + * Din | Din | Din | * | | | | | | * v v v v v v * +--------+ +--------+ +--------+ * | Memory | | Memory | ... | Memory | * | Module | | Module | | Module | - * | [0] | | [1] | | [N-1] | + * | [0] | | [1] | | [N-1] | * +--------+ +--------+ +--------+ * ^ ^ ^ * | | | @@ -1289,38 +1482,41 @@ void add_module_nets_cmos_memory_frame_short_config_bus(ModuleManager& module_ma * * Note: * - X is the port size of address port of the parent module - * - the address port of child memory modules may be smaller than + * - the address port of child memory modules may be smaller than * X - log(N)/log2. In such case, we will drop the MSBs until it fit * - This function is only applicable to 2+ configurable children!!! * *********************************************************************/ -static -void add_module_nets_cmos_memory_frame_decoder_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const ModuleId& parent_module) { - std::vector configurable_children = module_manager.configurable_children(parent_module); +static void add_module_nets_cmos_memory_frame_decoder_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const ModuleId& parent_module) { + std::vector configurable_children = + module_manager.configurable_children(parent_module); /* Find the decoder specification */ - size_t addr_size = find_mux_local_decoder_addr_size(configurable_children.size()); + size_t addr_size = + find_mux_local_decoder_addr_size(configurable_children.size()); /* Data input should match the WL (data_in) of a SRAM */ - size_t data_size = configurable_children.size(); + size_t data_size = configurable_children.size(); - /* Search the decoder library and try to find one - * If not found, create a new module and add it to the module manager + /* Search the decoder library and try to find one + * If not found, create a new module and add it to the module manager */ - DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, true, false, false, false); + DecoderId decoder_id = + decoder_lib.find_decoder(addr_size, data_size, true, false, false, false); if (DecoderId::INVALID() == decoder_id) { - decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, false, false, false); + decoder_id = + decoder_lib.add_decoder(addr_size, data_size, true, false, false, false); } VTR_ASSERT(DecoderId::INVALID() != decoder_id); /* Create a module if not existed yet */ - std::string decoder_module_name = generate_memory_decoder_subckt_name(addr_size, data_size); + std::string decoder_module_name = + generate_memory_decoder_subckt_name(addr_size, data_size); ModuleId decoder_module = module_manager.find_module(decoder_module_name); if (ModuleId::INVALID() == decoder_module) { decoder_module = build_frame_memory_decoder_module(module_manager, - decoder_lib, - decoder_id); + decoder_lib, decoder_id); } VTR_ASSERT(ModuleId::INVALID() != decoder_module); @@ -1331,64 +1527,68 @@ void add_module_nets_cmos_memory_frame_decoder_config_bus(ModuleManager& module_ /* Connect the enable (EN) port of memory modules under the parent module * to the frame decoder inputs */ - ModulePortId parent_en_port = module_manager.find_module_port(parent_module, std::string(DECODER_ENABLE_PORT_NAME)); - ModulePortId decoder_en_port = module_manager.find_module_port(decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); - add_module_bus_nets(module_manager, parent_module, - parent_module, 0, parent_en_port, - decoder_module, 0, decoder_en_port); + ModulePortId parent_en_port = module_manager.find_module_port( + parent_module, std::string(DECODER_ENABLE_PORT_NAME)); + ModulePortId decoder_en_port = module_manager.find_module_port( + decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); + add_module_bus_nets(module_manager, parent_module, parent_module, 0, + parent_en_port, decoder_module, 0, decoder_en_port); - /* Connect the address port of the parent module to the frame decoder address port - * Note that we only connect to the first few bits of address port + /* Connect the address port of the parent module to the frame decoder address + * port Note that we only connect to the first few bits of address port */ - ModulePortId parent_addr_port = module_manager.find_module_port(parent_module, std::string(DECODER_ADDRESS_PORT_NAME)); - ModulePortId decoder_addr_port = module_manager.find_module_port(decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort parent_addr_port_info = module_manager.module_port(parent_module, parent_addr_port); - BasicPort decoder_addr_port_info = module_manager.module_port(decoder_module, decoder_addr_port); + ModulePortId parent_addr_port = module_manager.find_module_port( + parent_module, std::string(DECODER_ADDRESS_PORT_NAME)); + ModulePortId decoder_addr_port = module_manager.find_module_port( + decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort parent_addr_port_info = + module_manager.module_port(parent_module, parent_addr_port); + BasicPort decoder_addr_port_info = + module_manager.module_port(decoder_module, decoder_addr_port); for (size_t ipin = 0; ipin < decoder_addr_port_info.get_width(); ++ipin) { - ModuleNetId net = module_manager.module_instance_port_net(parent_module, - parent_module, 0, - parent_addr_port, - parent_addr_port_info.get_msb() - ipin); - if (ModuleNetId::INVALID() == net) { + ModuleNetId net = module_manager.module_instance_port_net( + parent_module, parent_module, 0, parent_addr_port, + parent_addr_port_info.get_msb() - ipin); + if (ModuleNetId::INVALID() == net) { net = module_manager.create_module_net(parent_module); /* Configure the net source */ - module_manager.add_module_net_source(parent_module, net, - parent_module, 0, - parent_addr_port, - parent_addr_port_info.get_msb() - ipin); + module_manager.add_module_net_source( + parent_module, net, parent_module, 0, parent_addr_port, + parent_addr_port_info.get_msb() - ipin); } /* Configure the net sink */ - module_manager.add_module_net_sink(parent_module, net, - decoder_module, 0, + module_manager.add_module_net_sink(parent_module, net, decoder_module, 0, decoder_addr_port, decoder_addr_port_info.get_msb() - ipin); - } + } - /* Connect the address port of the parent module to the address port of configurable children - * Note that we only connect to the last few bits of address port + /* Connect the address port of the parent module to the address port of + * configurable children Note that we only connect to the last few bits of + * address port */ - for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { - ModuleId child_module = configurable_children[mem_index]; - size_t child_instance = module_manager.configurable_child_instances(parent_module)[mem_index]; - ModulePortId child_addr_port = module_manager.find_module_port(child_module, std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort child_addr_port_info = module_manager.module_port(child_module, child_addr_port); + for (size_t mem_index = 0; mem_index < configurable_children.size(); + ++mem_index) { + ModuleId child_module = configurable_children[mem_index]; + size_t child_instance = + module_manager.configurable_child_instances(parent_module)[mem_index]; + ModulePortId child_addr_port = module_manager.find_module_port( + child_module, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort child_addr_port_info = + module_manager.module_port(child_module, child_addr_port); for (size_t ipin = 0; ipin < child_addr_port_info.get_width(); ++ipin) { - ModuleNetId net = module_manager.module_instance_port_net(parent_module, - parent_module, 0, - parent_addr_port, - parent_addr_port_info.get_lsb() + ipin); - if (ModuleNetId::INVALID() == net) { + ModuleNetId net = module_manager.module_instance_port_net( + parent_module, parent_module, 0, parent_addr_port, + parent_addr_port_info.get_lsb() + ipin); + if (ModuleNetId::INVALID() == net) { net = module_manager.create_module_net(parent_module); /* Configure the net source */ - module_manager.add_module_net_source(parent_module, net, - parent_module, 0, - parent_addr_port, - parent_addr_port_info.get_lsb() + ipin); + module_manager.add_module_net_source( + parent_module, net, parent_module, 0, parent_addr_port, + parent_addr_port_info.get_lsb() + ipin); } /* Configure the net sink */ - module_manager.add_module_net_sink(parent_module, net, - child_module, child_instance, - child_addr_port, + module_manager.add_module_net_sink(parent_module, net, child_module, + child_instance, child_addr_port, child_addr_port_info.get_lsb() + ipin); } } @@ -1396,44 +1596,52 @@ void add_module_nets_cmos_memory_frame_decoder_config_bus(ModuleManager& module_ /* Connect the data_in (Din) of parent module to the data_in of the all * the memory modules */ - ModulePortId parent_din_port = module_manager.find_module_port(parent_module, std::string(DECODER_DATA_IN_PORT_NAME)); - for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { - ModuleId child_module = configurable_children[mem_index]; - size_t child_instance = module_manager.configurable_child_instances(parent_module)[mem_index]; - ModulePortId child_din_port = module_manager.find_module_port(child_module, std::string(DECODER_DATA_IN_PORT_NAME)); - add_module_bus_nets(module_manager, parent_module, - parent_module, 0, parent_din_port, - child_module, child_instance, child_din_port); + ModulePortId parent_din_port = module_manager.find_module_port( + parent_module, std::string(DECODER_DATA_IN_PORT_NAME)); + for (size_t mem_index = 0; mem_index < configurable_children.size(); + ++mem_index) { + ModuleId child_module = configurable_children[mem_index]; + size_t child_instance = + module_manager.configurable_child_instances(parent_module)[mem_index]; + ModulePortId child_din_port = module_manager.find_module_port( + child_module, std::string(DECODER_DATA_IN_PORT_NAME)); + add_module_bus_nets(module_manager, parent_module, parent_module, 0, + parent_din_port, child_module, child_instance, + child_din_port); } - /* Connect the data_out port of the decoder module + /* Connect the data_out port of the decoder module * to the enable port of configurable children */ - ModulePortId decoder_dout_port = module_manager.find_module_port(decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); - BasicPort decoder_dout_port_info = module_manager.module_port(decoder_module, decoder_dout_port); - VTR_ASSERT(decoder_dout_port_info.get_width() == configurable_children.size()); - for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { - ModuleId child_module = configurable_children[mem_index]; - size_t child_instance = module_manager.configurable_child_instances(parent_module)[mem_index]; - ModulePortId child_en_port = module_manager.find_module_port(child_module, std::string(DECODER_ENABLE_PORT_NAME)); - BasicPort child_en_port_info = module_manager.module_port(child_module, child_en_port); + ModulePortId decoder_dout_port = module_manager.find_module_port( + decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort decoder_dout_port_info = + module_manager.module_port(decoder_module, decoder_dout_port); + VTR_ASSERT(decoder_dout_port_info.get_width() == + configurable_children.size()); + for (size_t mem_index = 0; mem_index < configurable_children.size(); + ++mem_index) { + ModuleId child_module = configurable_children[mem_index]; + size_t child_instance = + module_manager.configurable_child_instances(parent_module)[mem_index]; + ModulePortId child_en_port = module_manager.find_module_port( + child_module, std::string(DECODER_ENABLE_PORT_NAME)); + BasicPort child_en_port_info = + module_manager.module_port(child_module, child_en_port); for (size_t ipin = 0; ipin < child_en_port_info.get_width(); ++ipin) { - ModuleNetId net = module_manager.module_instance_port_net(parent_module, - decoder_module, 0, - decoder_dout_port, - decoder_dout_port_info.pins()[mem_index]); - if (ModuleNetId::INVALID() == net) { + ModuleNetId net = module_manager.module_instance_port_net( + parent_module, decoder_module, 0, decoder_dout_port, + decoder_dout_port_info.pins()[mem_index]); + if (ModuleNetId::INVALID() == net) { net = module_manager.create_module_net(parent_module); /* Configure the net source */ - module_manager.add_module_net_source(parent_module, net, - decoder_module, 0, - decoder_dout_port, - decoder_dout_port_info.pins()[mem_index]); + module_manager.add_module_net_source( + parent_module, net, decoder_module, 0, decoder_dout_port, + decoder_dout_port_info.pins()[mem_index]); } /* Configure the net sink */ - module_manager.add_module_net_sink(parent_module, net, - child_module, child_instance, - child_en_port, + module_manager.add_module_net_sink(parent_module, net, child_module, + child_instance, child_en_port, child_en_port_info.pins()[ipin]); } } @@ -1446,36 +1654,39 @@ void add_module_nets_cmos_memory_frame_decoder_config_bus(ModuleManager& module_ * Top-level function to add nets for frame-based memories * Add nets depending on the need * - If there is no configurable child, return directly. - * - If there is only one configurable child, short wire the EN, ADDR and DATA_IN to it - * - If there are more than two configurable childern, add a decoder and build interconnection - * between it and the children + * - If there is only one configurable child, short wire the EN, ADDR and + *DATA_IN to it + * - If there are more than two configurable childern, add a decoder and build + *interconnection between it and the children **********************************************************************/ -void add_module_nets_cmos_memory_frame_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const ModuleId& parent_module) { +void add_module_nets_cmos_memory_frame_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const ModuleId& parent_module) { if (0 == module_manager.configurable_children(parent_module).size()) { - return; + return; } - + if (1 == module_manager.configurable_children(parent_module).size()) { - add_module_nets_cmos_memory_frame_short_config_bus(module_manager, parent_module); + add_module_nets_cmos_memory_frame_short_config_bus(module_manager, + parent_module); } else { - VTR_ASSERT (1 < module_manager.configurable_children(parent_module).size()); - add_module_nets_cmos_memory_frame_decoder_config_bus(module_manager, decoder_lib, parent_module); + VTR_ASSERT(1 < module_manager.configurable_children(parent_module).size()); + add_module_nets_cmos_memory_frame_decoder_config_bus( + module_manager, decoder_lib, parent_module); } } /********************************************************************* - * Add the port-to-port connection between all the memory modules + * Add the port-to-port connection between all the memory modules * and their parent module * - * Create nets to wire the control signals of memory module to + * Create nets to wire the control signals of memory module to * the configuration ports of primitive module * - * Configuration Chain + * Configuration Chain * ------------------- * - * config_bus (head) config_bus (tail) + * config_bus (head) config_bus (tail) * | ^ * primitive | | * +---------------------------------------------+ @@ -1490,10 +1701,10 @@ void add_module_nets_cmos_memory_frame_config_bus(ModuleManager& module_manager, * | | * +---------------------------------------------+ * - * Memory bank + * Memory bank * ----------- * - * config_bus (BL) config_bus (WL) + * config_bus (BL) config_bus (WL) * | | * primitive | | * +---------------------------------------------+ @@ -1509,50 +1720,51 @@ void add_module_nets_cmos_memory_frame_config_bus(ModuleManager& module_manager, * +---------------------------------------------+ * **********************************************************************/ -static -void add_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type) { +static void add_module_nets_cmos_memory_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type) { switch (sram_orgz_type) { - case CONFIG_MEM_SCAN_CHAIN: { - add_module_nets_cmos_memory_chain_config_bus(module_manager, parent_module, - sram_orgz_type); - break; - } - case CONFIG_MEM_STANDALONE: - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: - add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, - sram_orgz_type, CIRCUIT_MODEL_PORT_BL); - add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, - sram_orgz_type, CIRCUIT_MODEL_PORT_WL); - add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, - sram_orgz_type, CIRCUIT_MODEL_PORT_WLR); - break; - case CONFIG_MEM_FRAME_BASED: - add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, parent_module); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization!\n"); - exit(1); + case CONFIG_MEM_SCAN_CHAIN: { + add_module_nets_cmos_memory_chain_config_bus( + module_manager, parent_module, sram_orgz_type); + break; + } + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: + add_module_nets_cmos_flatten_memory_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + add_module_nets_cmos_flatten_memory_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + add_module_nets_cmos_flatten_memory_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WLR); + break; + case CONFIG_MEM_FRAME_BASED: + add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, + parent_module); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization!\n"); + exit(1); } } /********************************************************************* - * @brief Add the port-to-port connection between all the memory modules - * and their parent module. This function creates nets to wire the control + * @brief Add the port-to-port connection between all the memory modules + * and their parent module. This function creates nets to wire the control * signals of memory module to the configuration ports of primitive module * * @note This function is only applicable to programmable blocks, which are - * grid, CBX/CBY, SB. Different from the add_pb_module_nets_cmos_memory_config_bus(), - * this function will merge BL/WLs of child module when connect them to the parent module + * grid, CBX/CBY, SB. Different from the + add_pb_module_nets_cmos_memory_config_bus(), + * this function will merge BL/WLs of child module when connect them to the + parent module * - * QL Memory bank + * QL Memory bank * -------------- * - * config_bus (BL) config_bus (WL) + * config_bus (BL) config_bus (WL) * | | * parent | | * +---------------------------------------------+ @@ -1573,50 +1785,49 @@ void add_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, * **********************************************************************/ -static -void add_pb_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type) { +static void add_pb_module_nets_cmos_memory_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type) { switch (sram_orgz_type) { - case CONFIG_MEM_SCAN_CHAIN: { - add_module_nets_cmos_memory_chain_config_bus(module_manager, parent_module, - sram_orgz_type); - break; - } - case CONFIG_MEM_STANDALONE: - case CONFIG_MEM_QL_MEMORY_BANK: - add_module_nets_cmos_memory_bank_bl_config_bus(module_manager, parent_module, - sram_orgz_type, CIRCUIT_MODEL_PORT_BL); - add_module_nets_cmos_memory_bank_wl_config_bus(module_manager, parent_module, - sram_orgz_type, CIRCUIT_MODEL_PORT_WL); - add_module_nets_cmos_memory_bank_wl_config_bus(module_manager, parent_module, - sram_orgz_type, CIRCUIT_MODEL_PORT_WLR); - break; - case CONFIG_MEM_MEMORY_BANK: - add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, - sram_orgz_type, CIRCUIT_MODEL_PORT_BL); - add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, - sram_orgz_type, CIRCUIT_MODEL_PORT_WL); - break; - case CONFIG_MEM_FRAME_BASED: - add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, parent_module); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization!\n"); - exit(1); + case CONFIG_MEM_SCAN_CHAIN: { + add_module_nets_cmos_memory_chain_config_bus( + module_manager, parent_module, sram_orgz_type); + break; + } + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_QL_MEMORY_BANK: + add_module_nets_cmos_memory_bank_bl_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + add_module_nets_cmos_memory_bank_wl_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + add_module_nets_cmos_memory_bank_wl_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WLR); + break; + case CONFIG_MEM_MEMORY_BANK: + add_module_nets_cmos_flatten_memory_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + add_module_nets_cmos_flatten_memory_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + break; + case CONFIG_MEM_FRAME_BASED: + add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, + parent_module); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization!\n"); + exit(1); } } /********************************************************************* * TODO: - * Add the port-to-port connection between a logic module + * Add the port-to-port connection between a logic module * and a memory module inside a primitive module * - * Memory bank + * Memory bank * ----------- - * config_bus (BL) config_bus (WL) shared_config_bugs(shared_BL/WLs) + * config_bus (BL) config_bus (WL) shared_config_bugs(shared_BL/WLs) * | | | | * primitive | | | | * +------------------------------------------------------------+ @@ -1634,10 +1845,10 @@ void add_pb_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, **********************************************************************/ /******************************************************************** - * Add the port-to-port connection between a memory module + * Add the port-to-port connection between a memory module * and the configuration bus of a primitive module * - * Create nets to wire the control signals of memory module to + * Create nets to wire the control signals of memory module to * the configuration ports of primitive module * * Primitive module @@ -1650,120 +1861,128 @@ void add_pb_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, * | +--------+ | * +----------------------------+ * The detailed config ports really depend on the type - * of SRAM organization. + * of SRAM organization. * * The config_bus in the argument is the reserved address of configuration * bus in the parent_module for this memory module * - * The configuration bus connection will depend not only - * the design technology of the memory cells but also the + * The configuration bus connection will depend not only + * the design technology of the memory cells but also the * configuration styles of FPGA fabric. * Here we will branch on the design technology * * Note: this function SHOULD be called after the pb_type_module is created - * and its child module (logic_module and memory_module) is created! + * and its child module (logic_module and memory_module) is created! *******************************************************************/ -void add_module_nets_memory_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_tech) { +void add_module_nets_memory_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_design_tech& mem_tech) { switch (mem_tech) { - case CIRCUIT_MODEL_DESIGN_CMOS: - add_module_nets_cmos_memory_config_bus(module_manager, decoder_lib, - parent_module, - sram_orgz_type); - break; - case CIRCUIT_MODEL_DESIGN_RRAM: - /* TODO: */ - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of memory design technology!\n"); - exit(1); + case CIRCUIT_MODEL_DESIGN_CMOS: + add_module_nets_cmos_memory_config_bus(module_manager, decoder_lib, + parent_module, sram_orgz_type); + break; + case CIRCUIT_MODEL_DESIGN_RRAM: + /* TODO: */ + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of memory design technology!\n"); + exit(1); } } - /******************************************************************** * Add the port-to-port connection between the configuration lines of * a programmable block module (grid, CBX/CBY, SB) and its child module * - * The configuration bus connection will depend not only - * the design technology of the memory cells but also the + * The configuration bus connection will depend not only + * the design technology of the memory cells but also the * configuration styles of FPGA fabric. * Here we will branch on the design technology * * Note: this function SHOULD be called after the pb_type_module is created - * and its child module (logic_module and memory_module) is created! + * and its child module (logic_module and memory_module) is created! *******************************************************************/ -void add_pb_module_nets_memory_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_tech) { +void add_pb_module_nets_memory_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_design_tech& mem_tech) { switch (mem_tech) { - case CIRCUIT_MODEL_DESIGN_CMOS: - add_pb_module_nets_cmos_memory_config_bus(module_manager, decoder_lib, - parent_module, - sram_orgz_type); - break; - case CIRCUIT_MODEL_DESIGN_RRAM: - /* TODO: */ - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of memory design technology!\n"); - exit(1); + case CIRCUIT_MODEL_DESIGN_CMOS: + add_pb_module_nets_cmos_memory_config_bus(module_manager, decoder_lib, + parent_module, sram_orgz_type); + break; + case CIRCUIT_MODEL_DESIGN_RRAM: + /* TODO: */ + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of memory design technology!\n"); + exit(1); } } /******************************************************************** - * Find the size of shared(reserved) configuration ports for module + * Find the size of shared(reserved) configuration ports for module *******************************************************************/ size_t find_module_num_shared_config_bits(const ModuleManager& module_manager, const ModuleId& module_id) { std::vector shared_config_port_names; - shared_config_port_names.push_back(generate_reserved_sram_port_name(CIRCUIT_MODEL_PORT_BLB)); - shared_config_port_names.push_back(generate_reserved_sram_port_name(CIRCUIT_MODEL_PORT_WL)); - size_t num_shared_config_bits = 0; /* By default it has zero configuration bits*/ + shared_config_port_names.push_back( + generate_reserved_sram_port_name(CIRCUIT_MODEL_PORT_BLB)); + shared_config_port_names.push_back( + generate_reserved_sram_port_name(CIRCUIT_MODEL_PORT_WL)); + size_t num_shared_config_bits = + 0; /* By default it has zero configuration bits*/ /* Try to find these ports in the module manager */ for (const std::string& shared_config_port_name : shared_config_port_names) { - ModulePortId module_port_id = module_manager.find_module_port(module_id, shared_config_port_name); + ModulePortId module_port_id = + module_manager.find_module_port(module_id, shared_config_port_name); /* If the port does not exist, go to the next */ - if (false == module_manager.valid_module_port_id(module_id, module_port_id)) { + if (false == + module_manager.valid_module_port_id(module_id, module_port_id)) { continue; } - /* The port exist, find the port size and update the num_config_bits if the size is larger */ - BasicPort module_port = module_manager.module_port(module_id, module_port_id); - num_shared_config_bits = std::max((int)num_shared_config_bits, (int)module_port.get_width()); + /* The port exist, find the port size and update the num_config_bits if the + * size is larger */ + BasicPort module_port = + module_manager.module_port(module_id, module_port_id); + num_shared_config_bits = + std::max((int)num_shared_config_bits, (int)module_port.get_width()); } return num_shared_config_bits; } /******************************************************************** - * Find the size of configuration ports for module + * Find the size of configuration ports for module *******************************************************************/ -size_t find_module_num_config_bits(const ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& sram_orgz_type) { - std::vector config_port_names = generate_sram_port_names(circuit_lib, sram_model, sram_orgz_type); +size_t find_module_num_config_bits( + const ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type& sram_orgz_type) { + std::vector config_port_names = + generate_sram_port_names(circuit_lib, sram_model, sram_orgz_type); size_t num_config_bits = 0; /* By default it has zero configuration bits*/ /* Try to find these ports in the module manager */ for (const std::string& config_port_name : config_port_names) { - ModulePortId module_port_id = module_manager.find_module_port(module_id, config_port_name); + ModulePortId module_port_id = + module_manager.find_module_port(module_id, config_port_name); /* If the port does not exist, go to the next */ - if (false == module_manager.valid_module_port_id(module_id, module_port_id)) { + if (false == + module_manager.valid_module_port_id(module_id, module_port_id)) { continue; } - /* The port exist, find the port size and update the num_config_bits if the size is larger */ - BasicPort module_port = module_manager.module_port(module_id, module_port_id); - num_config_bits = std::max((int)num_config_bits, (int)module_port.get_width()); + /* The port exist, find the port size and update the num_config_bits if the + * size is larger */ + BasicPort module_port = + module_manager.module_port(module_id, module_port_id); + num_config_bits = + std::max((int)num_config_bits, (int)module_port.get_width()); } return num_config_bits; @@ -1771,11 +1990,11 @@ size_t find_module_num_config_bits(const ModuleManager& module_manager, /******************************************************************** * Add General purpose I/O ports to the module: - * In this function, the following tasks are done: + * In this function, the following tasks are done: * 1. find all the I/O ports from the child modules and build a list of it, * 2. Merge all the I/O ports with the same name * 3. add the ports to the pb_module - * 4. add module nets to connect to the GPIO ports of each sub module + * 4. add module nets to connect to the GPIO ports of each sub module * * Module * ----------------------+ @@ -1795,10 +2014,9 @@ size_t find_module_num_config_bits(const ModuleManager& module_manager, * have been added to the pb_module! * Otherwise, some GPIO ports of the sub modules may be missed! *******************************************************************/ -static -void add_module_io_ports_from_child_modules(ModuleManager& module_manager, - const ModuleId& module_id, - const ModuleManager::e_module_port_type& module_port_type) { +static void add_module_io_ports_from_child_modules( + ModuleManager& module_manager, const ModuleId& module_id, + const ModuleManager::e_module_port_type& module_port_type) { std::vector gpio_ports_to_add; std::vector mappable_gpio_ports; @@ -1806,11 +2024,15 @@ void add_module_io_ports_from_child_modules(ModuleManager& module_manager, for (size_t i = 0; i < module_manager.io_children(module_id).size(); ++i) { ModuleId child = module_manager.io_children(module_id)[i]; /* Find all the global ports, whose port type is special */ - for (const ModulePortId& gpio_port_id : module_manager.module_port_ids_by_type(child, module_port_type)) { - const BasicPort& gpio_port = module_manager.module_port(child, gpio_port_id); + for (const ModulePortId& gpio_port_id : + module_manager.module_port_ids_by_type(child, module_port_type)) { + const BasicPort& gpio_port = + module_manager.module_port(child, gpio_port_id); /* If this port is not mergeable, we update the list */ bool is_mergeable = false; - for (size_t i_gpio_port_to_add = 0; i_gpio_port_to_add < gpio_ports_to_add.size(); ++i_gpio_port_to_add) { + for (size_t i_gpio_port_to_add = 0; + i_gpio_port_to_add < gpio_ports_to_add.size(); + ++i_gpio_port_to_add) { BasicPort& gpio_port_to_add = gpio_ports_to_add[i_gpio_port_to_add]; if (false == gpio_port_to_add.mergeable(gpio_port)) { continue; @@ -1819,11 +2041,12 @@ void add_module_io_ports_from_child_modules(ModuleManager& module_manager, /* Mappable I/O property must match! Mismatch rarely happened * but should error out avoid silent bugs! */ - VTR_ASSERT(module_manager.port_is_mappable_io(child, gpio_port_id) == mappable_gpio_ports[i_gpio_port_to_add]); + VTR_ASSERT(module_manager.port_is_mappable_io(child, gpio_port_id) == + mappable_gpio_ports[i_gpio_port_to_add]); /* For mergeable ports, we combine the port * Note: do NOT use the merge() method! * the GPIO ports should be accumulated by the sizes of ports - * not by the LSB/MSB range !!! + * not by the LSB/MSB range !!! */ gpio_port_to_add.combine(gpio_port); break; @@ -1831,33 +2054,39 @@ void add_module_io_ports_from_child_modules(ModuleManager& module_manager, if (false == is_mergeable) { /* Reach here, this is an unique gpio port, update the list */ gpio_ports_to_add.push_back(gpio_port); - /* If the gpio port is a mappable I/O, we should herit from the child module */ - mappable_gpio_ports.push_back(module_manager.port_is_mappable_io(child, gpio_port_id)); + /* If the gpio port is a mappable I/O, we should herit from the child + * module */ + mappable_gpio_ports.push_back( + module_manager.port_is_mappable_io(child, gpio_port_id)); } } - } + } /* Record the port id for each type of GPIO port */ std::vector gpio_port_ids; /* Add the gpio ports for the module */ for (size_t iport = 0; iport < gpio_ports_to_add.size(); ++iport) { const BasicPort& gpio_port_to_add = gpio_ports_to_add[iport]; - ModulePortId port_id = module_manager.add_port(module_id, gpio_port_to_add, module_port_type); + ModulePortId port_id = + module_manager.add_port(module_id, gpio_port_to_add, module_port_type); gpio_port_ids.push_back(port_id); - if (true == mappable_gpio_ports[iport]) { + if (true == mappable_gpio_ports[iport]) { module_manager.set_port_is_mappable_io(module_id, port_id, true); } - } + } /* Set up a counter for each type of GPIO port */ std::vector gpio_port_lsb(gpio_ports_to_add.size(), 0); - /* Add module nets to connect the GPIOs of the module to the GPIOs of the sub module */ + /* Add module nets to connect the GPIOs of the module to the GPIOs of the sub + * module */ for (size_t i = 0; i < module_manager.io_children(module_id).size(); ++i) { ModuleId child = module_manager.io_children(module_id)[i]; size_t child_instance = module_manager.io_child_instances(module_id)[i]; /* Find all the global ports, whose port type is special */ - for (ModulePortId child_gpio_port_id : module_manager.module_port_ids_by_type(child, module_port_type)) { - BasicPort child_gpio_port = module_manager.module_port(child, child_gpio_port_id); + for (ModulePortId child_gpio_port_id : + module_manager.module_port_ids_by_type(child, module_port_type)) { + BasicPort child_gpio_port = + module_manager.module_port(child, child_gpio_port_id); /* Find the port with the same name! */ for (size_t iport = 0; iport < gpio_ports_to_add.size(); ++iport) { if (false == gpio_ports_to_add[iport].mergeable(child_gpio_port)) { @@ -1865,22 +2094,31 @@ void add_module_io_ports_from_child_modules(ModuleManager& module_manager, } /* For each pin of the child port, create a net and do wiring */ for (const size_t& pin_id : child_gpio_port.pins()) { - /* Reach here, it means this is the port we want, create a net and configure its source and sink */ + /* Reach here, it means this is the port we want, create a net and + * configure its source and sink */ /* - For GPIO and GPIN ports - * the source of the net is the current module + * the source of the net is the current module * the sink of the net is the child module * - For GPOUT ports * the source of the net is the child module - * the sink of the net is the current module + * the sink of the net is the current module */ - if ( (ModuleManager::MODULE_GPIO_PORT == module_port_type) - || (ModuleManager::MODULE_GPIN_PORT == module_port_type) ) { - ModuleNetId net = create_module_source_pin_net(module_manager, module_id, module_id, 0, gpio_port_ids[iport], gpio_port_lsb[iport]); - module_manager.add_module_net_sink(module_id, net, child, child_instance, child_gpio_port_id, pin_id); + if ((ModuleManager::MODULE_GPIO_PORT == module_port_type) || + (ModuleManager::MODULE_GPIN_PORT == module_port_type)) { + ModuleNetId net = create_module_source_pin_net( + module_manager, module_id, module_id, 0, gpio_port_ids[iport], + gpio_port_lsb[iport]); + module_manager.add_module_net_sink(module_id, net, child, + child_instance, + child_gpio_port_id, pin_id); } else { VTR_ASSERT(ModuleManager::MODULE_GPOUT_PORT == module_port_type); - ModuleNetId net = create_module_source_pin_net(module_manager, module_id, child, child_instance, child_gpio_port_id, pin_id); - module_manager.add_module_net_sink(module_id, net, module_id, 0, gpio_port_ids[iport], gpio_port_lsb[iport]); + ModuleNetId net = create_module_source_pin_net( + module_manager, module_id, child, child_instance, + child_gpio_port_id, pin_id); + module_manager.add_module_net_sink(module_id, net, module_id, 0, + gpio_port_ids[iport], + gpio_port_lsb[iport]); } /* Update the LSB counter */ gpio_port_lsb[iport]++; @@ -1899,31 +2137,36 @@ void add_module_io_ports_from_child_modules(ModuleManager& module_manager, /******************************************************************** * Add GPIO ports to the module: - * In this function, the following tasks are done: + * In this function, the following tasks are done: * 1. find all the GPIO ports from the child modules and build a list of it, * 2. Merge all the GPIO ports with the same name * 3. add the ports to the pb_module - * 4. add module nets to connect to the GPIO ports of each sub module + * 4. add module nets to connect to the GPIO ports of each sub module * * Note: This function should be call ONLY after all the sub modules (instances) * have been added to the pb_module! * Otherwise, some GPIO ports of the sub modules may be missed! *******************************************************************/ -void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, +void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, const ModuleId& module_id) { - add_module_io_ports_from_child_modules(module_manager, module_id, ModuleManager::MODULE_GPIO_PORT); + add_module_io_ports_from_child_modules(module_manager, module_id, + ModuleManager::MODULE_GPIO_PORT); - add_module_io_ports_from_child_modules(module_manager, module_id, ModuleManager::MODULE_GPIN_PORT); + add_module_io_ports_from_child_modules(module_manager, module_id, + ModuleManager::MODULE_GPIN_PORT); - add_module_io_ports_from_child_modules(module_manager, module_id, ModuleManager::MODULE_GPOUT_PORT); + add_module_io_ports_from_child_modules(module_manager, module_id, + ModuleManager::MODULE_GPOUT_PORT); } /******************************************************************** * Add global input ports to the module: - * In this function, the following tasks are done: - * 1. find all the global input ports from the child modules and build a list of it, + * In this function, the following tasks are done: + * 1. find all the global input ports from the child modules and build a list of + *it, * 2. add the input ports to the pb_module - * 3. add the module nets to connect the pb_module global ports to those of child modules + * 3. add the module nets to connect the pb_module global ports to those of + *child modules * * Module * +-------------------------- @@ -1941,8 +2184,8 @@ void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, * have been added to the pb_module! * 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) { +void add_module_global_input_ports_from_child_modules( + ModuleManager& module_manager, const ModuleId& module_id) { std::vector global_ports_to_add; /* Iterate over the child modules */ @@ -1950,9 +2193,12 @@ void add_module_global_input_ports_from_child_modules(ModuleManager& module_mana /* Iterate over the child instances */ for (size_t i = 0; i < module_manager.num_instance(module_id, child); ++i) { /* Find all the global ports, whose port type is special */ - for (BasicPort global_port : module_manager.module_ports_by_type(child, ModuleManager::MODULE_GLOBAL_PORT)) { - /* Search in the global port list to be added, if this is unique, we update the list */ - std::vector::iterator it = std::find(global_ports_to_add.begin(), global_ports_to_add.end(), global_port); + for (BasicPort global_port : module_manager.module_ports_by_type( + child, ModuleManager::MODULE_GLOBAL_PORT)) { + /* Search in the global port list to be added, if this is unique, we + * update the list */ + std::vector::iterator it = std::find( + global_ports_to_add.begin(), global_ports_to_add.end(), global_port); if (it != global_ports_to_add.end()) { continue; } @@ -1960,156 +2206,188 @@ void add_module_global_input_ports_from_child_modules(ModuleManager& module_mana global_ports_to_add.push_back(global_port); } } - } + } /* Record the port id for each type of global port */ std::vector global_port_ids; /* Add the global ports for the module */ for (const BasicPort& global_port_to_add : global_ports_to_add) { - ModulePortId port_id = module_manager.add_port(module_id, global_port_to_add, ModuleManager::MODULE_GLOBAL_PORT); + ModulePortId port_id = module_manager.add_port( + module_id, global_port_to_add, ModuleManager::MODULE_GLOBAL_PORT); global_port_ids.push_back(port_id); - } + } /* Count the number of sinks for each global port */ std::map port_sink_count; for (const ModuleId& child : module_manager.child_modules(module_id)) { /* Find all the global ports, whose port type is special */ - for (ModulePortId child_global_port_id : module_manager.module_port_ids_by_type(child, ModuleManager::MODULE_GLOBAL_PORT)) { - BasicPort child_global_port = module_manager.module_port(child, child_global_port_id); + for (ModulePortId child_global_port_id : + module_manager.module_port_ids_by_type( + child, ModuleManager::MODULE_GLOBAL_PORT)) { + BasicPort child_global_port = + module_manager.module_port(child, child_global_port_id); /* 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); + std::vector::iterator it = + std::find(global_ports_to_add.begin(), global_ports_to_add.end(), + child_global_port); VTR_ASSERT(it != global_ports_to_add.end()); - ModulePortId module_global_port_id = global_port_ids[it - global_ports_to_add.begin()]; + ModulePortId module_global_port_id = + global_port_ids[it - global_ports_to_add.begin()]; - port_sink_count[module_global_port_id] += module_manager.num_instance(module_id, child); + port_sink_count[module_global_port_id] += + module_manager.num_instance(module_id, child); } } - /* Add module nets to connect the global ports of the module to the global ports of the sub module */ + /* Add module nets to connect the global ports of the module to the global + * ports of the sub module */ /* Iterate over the child modules */ for (const ModuleId& child : module_manager.child_modules(module_id)) { /* Iterate over the child instances */ - for (const size_t& child_instance : module_manager.child_module_instances(module_id, child)) { + for (const size_t& child_instance : + module_manager.child_module_instances(module_id, child)) { /* Find all the global ports, whose port type is special */ - for (ModulePortId child_global_port_id : module_manager.module_port_ids_by_type(child, ModuleManager::MODULE_GLOBAL_PORT)) { - BasicPort child_global_port = module_manager.module_port(child, child_global_port_id); + for (ModulePortId child_global_port_id : + module_manager.module_port_ids_by_type( + child, ModuleManager::MODULE_GLOBAL_PORT)) { + BasicPort child_global_port = + module_manager.module_port(child, child_global_port_id); /* 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); + std::vector::iterator it = + std::find(global_ports_to_add.begin(), global_ports_to_add.end(), + child_global_port); VTR_ASSERT(it != global_ports_to_add.end()); - ModulePortId module_global_port_id = global_port_ids[it - global_ports_to_add.begin()]; - BasicPort module_global_port = module_manager.module_port(module_id, module_global_port_id); + ModulePortId module_global_port_id = + global_port_ids[it - global_ports_to_add.begin()]; + BasicPort module_global_port = + module_manager.module_port(module_id, module_global_port_id); /* The global ports should match in size */ - VTR_ASSERT(module_global_port.get_width() == child_global_port.get_width()); + VTR_ASSERT(module_global_port.get_width() == + child_global_port.get_width()); /* For each pin of the child port, create a net and do wiring */ - for (size_t pin_id = 0; pin_id < child_global_port.pins().size(); ++pin_id) { - /* Reach here, it means this is the port we want, create a net and configure its source and sink */ - ModuleNetId net = create_module_source_pin_net(module_manager, module_id, module_id, 0, module_global_port_id, module_global_port.pins()[pin_id]); - module_manager.reserve_module_net_sinks(module_id, net, port_sink_count[module_global_port_id]); - module_manager.add_module_net_sink(module_id, net, child, child_instance, child_global_port_id, child_global_port.pins()[pin_id]); + for (size_t pin_id = 0; pin_id < child_global_port.pins().size(); + ++pin_id) { + /* Reach here, it means this is the port we want, create a net and + * configure its source and sink */ + ModuleNetId net = create_module_source_pin_net( + module_manager, module_id, module_id, 0, module_global_port_id, + module_global_port.pins()[pin_id]); + module_manager.reserve_module_net_sinks( + module_id, net, port_sink_count[module_global_port_id]); + module_manager.add_module_net_sink( + module_id, net, child, child_instance, child_global_port_id, + child_global_port.pins()[pin_id]); /* We finish for this child gpio port */ } } } - } + } } /******************************************************************** * Add global ports to the module: - * In this function, we will add global input ports and global output ports - * which are collected from the child modules + * In this function, we will add global input ports and global output ports + * which are collected from the child modules * * - Input ports: the input ports will be uniquified by names * Ports with the same name will be merged to the same pin * See details inside the function * * - Output ports: the output ports will be uniquified by names - * Different from the input ports, output ports - * with the same name will be merged but will have indepedent pins - * See details inside the function + * Different from the input ports, output ports + * with the same name will be merged but will have indepedent + *pins See details inside the function * * Note: This function should be call ONLY after all the sub modules (instances) * 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, +void add_module_global_ports_from_child_modules(ModuleManager& module_manager, const ModuleId& module_id) { /* Input ports */ add_module_global_input_ports_from_child_modules(module_manager, module_id); } /******************************************************************** - * Find the number of shared configuration bits for a module + * Find the number of shared configuration bits for a module * by selected the maximum number of shared configuration bits of child modules * * Note: This function should be call ONLY after all the sub modules (instances) * have been added to the pb_module! * Otherwise, some global ports of the sub modules may be missed! *******************************************************************/ -size_t find_module_num_shared_config_bits_from_child_modules(ModuleManager& module_manager, - const ModuleId& module_id) { +size_t find_module_num_shared_config_bits_from_child_modules( + ModuleManager& module_manager, const ModuleId& module_id) { size_t num_shared_config_bits = 0; /* Iterate over the child modules */ for (const ModuleId& child : module_manager.child_modules(module_id)) { - num_shared_config_bits = std::max((int)num_shared_config_bits, (int)find_module_num_shared_config_bits(module_manager, child)); - } + num_shared_config_bits = + std::max((int)num_shared_config_bits, + (int)find_module_num_shared_config_bits(module_manager, child)); + } return num_shared_config_bits; } /******************************************************************** - * Find the number of configuration bits for a module + * Find the number of configuration bits for a module * by summing up the number of configuration bits of child modules * * Note: This function should be call ONLY after all the sub modules (instances) * have been added to the pb_module! * Otherwise, some global ports of the sub modules may be missed! *******************************************************************/ -size_t find_module_num_config_bits_from_child_modules(ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& sram_orgz_type) { +size_t find_module_num_config_bits_from_child_modules( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type& sram_orgz_type) { size_t num_config_bits = 0; switch (sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - case CONFIG_MEM_SCAN_CHAIN: - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: { - /* For scan-chain, standalone and memory bank configuration protocol - * The number of configuration bits is the sum of configuration bits - * per configurable children - */ - for (const ModuleId& child : module_manager.configurable_children(module_id)) { - num_config_bits += find_module_num_config_bits(module_manager, child, circuit_lib, sram_model, sram_orgz_type); - } - break; - } - case CONFIG_MEM_FRAME_BASED: { - /* For frame-based configuration protocol - * The number of configuration bits is the sum of - * - the maximum of configuration bits among configurable children - * - and the number of configurable children - */ - for (const ModuleId& child : module_manager.configurable_children(module_id)) { - size_t temp_num_config_bits = find_module_num_config_bits(module_manager, child, circuit_lib, sram_model, sram_orgz_type); - num_config_bits = std::max((int)temp_num_config_bits, (int)num_config_bits); - } - - /* If there are more than 2 configurable children, we need a decoder - * Otherwise, we can just short wire the address port to the children - */ - if (1 < module_manager.configurable_children(module_id).size()) { - num_config_bits += find_mux_local_decoder_addr_size(module_manager.configurable_children(module_id).size()); + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_SCAN_CHAIN: + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: { + /* For scan-chain, standalone and memory bank configuration protocol + * The number of configuration bits is the sum of configuration bits + * per configurable children + */ + for (const ModuleId& child : + module_manager.configurable_children(module_id)) { + num_config_bits += find_module_num_config_bits( + module_manager, child, circuit_lib, sram_model, sram_orgz_type); + } + break; } + case CONFIG_MEM_FRAME_BASED: { + /* For frame-based configuration protocol + * The number of configuration bits is the sum of + * - the maximum of configuration bits among configurable children + * - and the number of configurable children + */ + for (const ModuleId& child : + module_manager.configurable_children(module_id)) { + size_t temp_num_config_bits = find_module_num_config_bits( + module_manager, child, circuit_lib, sram_model, sram_orgz_type); + num_config_bits = + std::max((int)temp_num_config_bits, (int)num_config_bits); + } - break; - } - default: - VTR_LOG_ERROR("Invalid type of SRAM organization !\n"); - exit(1); + /* If there are more than 2 configurable children, we need a decoder + * Otherwise, we can just short wire the address port to the children + */ + if (1 < module_manager.configurable_children(module_id).size()) { + num_config_bits += find_mux_local_decoder_addr_size( + module_manager.configurable_children(module_id).size()); + } + + break; + } + default: + VTR_LOG_ERROR("Invalid type of SRAM organization !\n"); + exit(1); } return num_config_bits; @@ -2128,14 +2406,14 @@ ModuleNetId create_module_source_pin_net(ModuleManager& module_manager, const size_t& src_instance_id, const ModulePortId& src_module_port_id, const size_t& src_pin_id) { - ModuleNetId net = module_manager.module_instance_port_net(cur_module_id, - src_module_id, src_instance_id, - src_module_port_id, src_pin_id); - if (ModuleNetId::INVALID() == net) { + ModuleNetId net = module_manager.module_instance_port_net( + cur_module_id, src_module_id, src_instance_id, src_module_port_id, + src_pin_id); + if (ModuleNetId::INVALID() == net) { net = module_manager.create_module_net(cur_module_id); - module_manager.add_module_net_source(cur_module_id, net, - src_module_id, src_instance_id, - src_module_port_id, src_pin_id); + module_manager.add_module_net_source(cur_module_id, net, src_module_id, + src_instance_id, src_module_port_id, + src_pin_id); } return net; @@ -2143,7 +2421,7 @@ ModuleNetId create_module_source_pin_net(ModuleManager& module_manager, /******************************************************************** * Add a bus of nets to a module (cur_module_id) - * Note: + * Note: * - both src and des module should exist in the module manager * - src_module should be the cur_module or a child of it * - des_module should be the cur_module or a child of it @@ -2151,67 +2429,70 @@ ModuleNetId create_module_source_pin_net(ModuleManager& module_manager, * - src port size should match the des port size * *******************************************************************/ -void add_module_bus_nets(ModuleManager& module_manager, - const ModuleId& cur_module_id, - const ModuleId& src_module_id, - const size_t& src_instance_id, - const ModulePortId& src_module_port_id, - const ModuleId& des_module_id, - const size_t& des_instance_id, - const ModulePortId& des_module_port_id) { - +void add_module_bus_nets( + ModuleManager& module_manager, const ModuleId& cur_module_id, + const ModuleId& src_module_id, const size_t& src_instance_id, + const ModulePortId& src_module_port_id, const ModuleId& des_module_id, + const size_t& des_instance_id, const ModulePortId& des_module_port_id) { VTR_ASSERT(true == module_manager.valid_module_id(cur_module_id)); VTR_ASSERT(true == module_manager.valid_module_id(src_module_id)); VTR_ASSERT(true == module_manager.valid_module_id(des_module_id)); - VTR_ASSERT(true == module_manager.valid_module_port_id(src_module_id, src_module_port_id)); - VTR_ASSERT(true == module_manager.valid_module_port_id(des_module_id, des_module_port_id)); + VTR_ASSERT(true == module_manager.valid_module_port_id(src_module_id, + src_module_port_id)); + VTR_ASSERT(true == module_manager.valid_module_port_id(des_module_id, + des_module_port_id)); if (src_module_id == cur_module_id) { VTR_ASSERT(0 == src_instance_id); } else { - VTR_ASSERT(src_instance_id < module_manager.num_instance(cur_module_id, src_module_id)); + VTR_ASSERT(src_instance_id < + module_manager.num_instance(cur_module_id, src_module_id)); } if (des_module_id == cur_module_id) { VTR_ASSERT(0 == des_instance_id); } else { - VTR_ASSERT(des_instance_id < module_manager.num_instance(cur_module_id, des_module_id)); + VTR_ASSERT(des_instance_id < + module_manager.num_instance(cur_module_id, des_module_id)); } - const BasicPort& src_port = module_manager.module_port(src_module_id, src_module_port_id); - const BasicPort& des_port = module_manager.module_port(des_module_id, des_module_port_id); + const BasicPort& src_port = + module_manager.module_port(src_module_id, src_module_port_id); + const BasicPort& des_port = + module_manager.module_port(des_module_id, des_module_port_id); if (src_port.get_width() != des_port.get_width()) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Unmatched port size: src_port %s is %lu while des_port %s is %lu!\n", - src_port.get_name().c_str(), - src_port.get_width(), - des_port.get_name().c_str(), - des_port.get_width()); + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Unmatched port size: src_port %s is %lu while des_port %s is %lu!\n", + src_port.get_name().c_str(), src_port.get_width(), + des_port.get_name().c_str(), des_port.get_width()); exit(1); } /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < src_port.pins().size(); ++pin_id) { - ModuleNetId net = create_module_source_pin_net(module_manager, cur_module_id, - src_module_id, src_instance_id, - src_module_port_id, src_port.pins()[pin_id]); + ModuleNetId net = create_module_source_pin_net( + module_manager, cur_module_id, src_module_id, src_instance_id, + src_module_port_id, src_port.pins()[pin_id]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Configure the net sink */ - module_manager.add_module_net_sink(cur_module_id, net, des_module_id, des_instance_id, des_module_port_id, des_port.pins()[pin_id]); + module_manager.add_module_net_sink(cur_module_id, net, des_module_id, + des_instance_id, des_module_port_id, + des_port.pins()[pin_id]); } } /******************************************************************** * TODO: - * Add the port-to-port connection between a logic module + * Add the port-to-port connection between a logic module * and a memory module inside a primitive module * - * Create nets to wire the formal verification ports of - * primitive module to SRAM ports of logic module - * + * Create nets to wire the formal verification ports of + * primitive module to SRAM ports of logic module + * * Primitive module * * formal_port_sram diff --git a/openfpga/src/utils/module_manager_utils.h b/openfpga/src/utils/module_manager_utils.h index 151773b71..f6ec40b0c 100644 --- a/openfpga/src/utils/module_manager_utils.h +++ b/openfpga/src/utils/module_manager_utils.h @@ -1,5 +1,5 @@ /****************************************************************************** - * This files includes declarations for most utilized functions + * This files includes declarations for most utilized functions * for data structures for module management. ******************************************************************************/ #ifndef MODULE_MANAGER_UTILS_H @@ -8,8 +8,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include #include +#include /* Headers from readarch library */ #include "physical_types.h" @@ -18,9 +18,8 @@ #include "openfpga_port.h" /* Headers from readarchopenfpga library */ -#include "circuit_types.h" #include "circuit_library.h" - +#include "circuit_types.h" #include "decoder_library.h" #include "module_manager.h" #include "vpr_device_annotation.h" @@ -32,149 +31,140 @@ /* begin namespace openfpga */ namespace openfpga { -constexpr std::array MODULE_IO_PORT_TYPES = {ModuleManager::MODULE_GPIN_PORT, ModuleManager::MODULE_GPOUT_PORT, ModuleManager::MODULE_GPIO_PORT}; +constexpr std::array + MODULE_IO_PORT_TYPES = {ModuleManager::MODULE_GPIN_PORT, + ModuleManager::MODULE_GPOUT_PORT, + ModuleManager::MODULE_GPIO_PORT}; -void reserve_module_manager_module_nets(ModuleManager& module_manager, +void reserve_module_manager_module_nets(ModuleManager& module_manager, const ModuleId& module); -size_t count_module_manager_module_configurable_children(const ModuleManager& module_manager, - const ModuleId& module); +size_t count_module_manager_module_configurable_children( + const ModuleManager& module_manager, const ModuleId& module); -std::pair find_module_manager_instance_module_info(const ModuleManager& module_manager, - const ModuleId& parent, - const std::string& instance_name); +std::pair find_module_manager_instance_module_info( + const ModuleManager& module_manager, const ModuleId& parent, + const std::string& instance_name); -ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, - const std::string& module_name); +ModuleId add_circuit_model_to_module_manager( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, const std::string& module_name); -ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model); +ModuleId add_circuit_model_to_module_manager( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model); -void add_reserved_sram_ports_to_module_manager(ModuleManager& module_manager, +void add_reserved_sram_ports_to_module_manager(ModuleManager& module_manager, const ModuleId& module_id, const size_t& port_size); -void add_formal_verification_sram_ports_to_module_manager(ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const std::string& preproc_flag, - const size_t& port_size); +void add_formal_verification_sram_ports_to_module_manager( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const std::string& preproc_flag, const size_t& port_size); -void add_sram_ports_to_module_manager(ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type sram_orgz_type, - const size_t& num_config_bits); +void add_sram_ports_to_module_manager( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type sram_orgz_type, const size_t& num_config_bits); -void add_pb_sram_ports_to_module_manager(ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type sram_orgz_type, - const size_t& num_config_bits); +void add_pb_sram_ports_to_module_manager( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type sram_orgz_type, const size_t& num_config_bits); -void add_primitive_pb_type_ports_to_module_manager(ModuleManager& module_manager, - const ModuleId& module_id, - t_pb_type* cur_pb_type, - const VprDeviceAnnotation& vpr_device_annotation); +void add_primitive_pb_type_ports_to_module_manager( + ModuleManager& module_manager, const ModuleId& module_id, + t_pb_type* cur_pb_type, const VprDeviceAnnotation& vpr_device_annotation); -void add_pb_type_ports_to_module_manager(ModuleManager& module_manager, +void add_pb_type_ports_to_module_manager(ModuleManager& module_manager, const ModuleId& module_id, t_pb_type* cur_pb_type); -bool module_net_is_local_wire(const ModuleManager& module_manager, - const ModuleId& module_id, const ModuleNetId& module_net); +bool module_net_is_local_wire(const ModuleManager& module_manager, + const ModuleId& module_id, + const ModuleNetId& module_net); -bool module_net_include_output_short_connection(const ModuleManager& module_manager, - const ModuleId& module_id, const ModuleNetId& module_net); +bool module_net_include_output_short_connection( + const ModuleManager& module_manager, const ModuleId& module_id, + const ModuleNetId& module_net); -bool module_net_include_local_short_connection(const ModuleManager& module_manager, - const ModuleId& module_id, const ModuleNetId& module_net); +bool module_net_include_local_short_connection( + const ModuleManager& module_manager, const ModuleId& module_id, + const ModuleNetId& module_net); -void add_primitive_pb_type_module_nets(ModuleManager& module_manager, - const ModuleId& pb_type_module, - const ModuleId& child_module, - const size_t& child_instance_id, - const CircuitLibrary& circuit_lib, - t_pb_type* cur_pb_type, - const VprDeviceAnnotation& vpr_device_annotation); +void add_primitive_pb_type_module_nets( + ModuleManager& module_manager, const ModuleId& pb_type_module, + const ModuleId& child_module, const size_t& child_instance_id, + const CircuitLibrary& circuit_lib, t_pb_type* cur_pb_type, + const VprDeviceAnnotation& vpr_device_annotation); -void add_module_nets_between_logic_and_memory_sram_bus(ModuleManager& module_manager, - const ModuleId& parent_module, - const ModuleId& logic_module, - const size_t& logic_instance_id, - const ModuleId& memory_module, - const size_t& memory_instance_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& logic_model); +void add_module_nets_between_logic_and_memory_sram_bus( + ModuleManager& module_manager, const ModuleId& parent_module, + const ModuleId& logic_module, const size_t& logic_instance_id, + const ModuleId& memory_module, const size_t& memory_instance_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& logic_model); -void add_module_nets_cmos_flatten_memory_config_bus(ModuleManager& module_manager, - const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type); +void add_module_nets_cmos_flatten_memory_config_bus( + ModuleManager& module_manager, const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& config_port_type); -void add_module_nets_cmos_memory_bank_bl_config_bus(ModuleManager& module_manager, - const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type); +void add_module_nets_cmos_memory_bank_bl_config_bus( + ModuleManager& module_manager, const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& config_port_type); -void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manager, - const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type); +void add_module_nets_cmos_memory_bank_wl_config_bus( + ModuleManager& module_manager, const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& config_port_type); -void add_module_nets_cmos_memory_chain_config_bus(ModuleManager& module_manager, - const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type); +void add_module_nets_cmos_memory_chain_config_bus( + ModuleManager& module_manager, const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type); -void add_module_nets_cmos_memory_frame_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const ModuleId& parent_module); +void add_module_nets_cmos_memory_frame_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const ModuleId& parent_module); -void add_module_nets_memory_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_tech); +void add_module_nets_memory_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_design_tech& mem_tech); -void add_pb_module_nets_memory_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_tech); +void add_pb_module_nets_memory_config_bus( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_design_tech& mem_tech); size_t find_module_num_shared_config_bits(const ModuleManager& module_manager, const ModuleId& module_id); -size_t find_module_num_config_bits(const ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& sram_orgz_type); +size_t find_module_num_config_bits( + const ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type& sram_orgz_type); -void add_module_global_input_ports_from_child_modules(ModuleManager& module_manager, - const ModuleId& module_id); +void add_module_global_input_ports_from_child_modules( + ModuleManager& module_manager, const ModuleId& module_id); -void add_module_global_output_ports_from_child_modules(ModuleManager& module_manager, - const ModuleId& module_id); +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, +void add_module_global_ports_from_child_modules(ModuleManager& module_manager, const ModuleId& module_id); -void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, +void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, const ModuleId& module_id); -size_t find_module_num_shared_config_bits_from_child_modules(ModuleManager& module_manager, - const ModuleId& module_id); +size_t find_module_num_shared_config_bits_from_child_modules( + ModuleManager& module_manager, const ModuleId& module_id); -size_t find_module_num_config_bits_from_child_modules(ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& sram_orgz_type); +size_t find_module_num_config_bits_from_child_modules( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type& sram_orgz_type); ModuleNetId create_module_source_pin_net(ModuleManager& module_manager, const ModuleId& cur_module_id, @@ -183,14 +173,11 @@ ModuleNetId create_module_source_pin_net(ModuleManager& module_manager, const ModulePortId& src_module_port_id, const size_t& src_pin_id); -void add_module_bus_nets(ModuleManager& module_manager, - const ModuleId& cur_module_id, - const ModuleId& src_module_id, - const size_t& src_instance_id, - const ModulePortId& src_module_port_id, - const ModuleId& des_module_id, - const size_t& des_instance_id, - const ModulePortId& des_module_port_id); +void add_module_bus_nets( + ModuleManager& module_manager, const ModuleId& cur_module_id, + const ModuleId& src_module_id, const size_t& src_instance_id, + const ModulePortId& src_module_port_id, const ModuleId& des_module_id, + const size_t& des_instance_id, const ModulePortId& des_module_port_id); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/mux_utils.cpp b/openfpga/src/utils/mux_utils.cpp index e4b679df6..f80dba0f7 100644 --- a/openfpga/src/utils/mux_utils.cpp +++ b/openfpga/src/utils/mux_utils.cpp @@ -1,17 +1,16 @@ /************************************************** - * This file includes a series of most utilized functions - * that are used to implement a multiplexer + * This file includes a series of most utilized functions + * that are used to implement a multiplexer *************************************************/ -#include #include +#include /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" /* Headers from readarchopenfpga library */ #include "circuit_types.h" - #include "decoder_library_utils.h" #include "mux_utils.h" @@ -20,7 +19,7 @@ namespace openfpga { /* Validate the number of inputs for a multiplexer implementation, * the minimum supported size is 2 - * otherwise, there is no need for a MUX + * otherwise, there is no need for a MUX */ bool valid_mux_implementation_num_inputs(const size_t& mux_size) { return (2 <= mux_size); @@ -28,19 +27,21 @@ bool valid_mux_implementation_num_inputs(const size_t& mux_size) { /************************************************** * Find the actual number of datapath inputs for a multiplexer implementation - * 1. if there are no requirements on constant inputs, mux_size is the actual one + * 1. if there are no requirements on constant inputs, mux_size is the actual + *one * 2. if there exist constant inputs, mux_size should minus 1 * This function is mainly used to recover the number of datapath inputs - * for MUXGraphs which is a generic representation without labelling datapath inputs + * for MUXGraphs which is a generic representation without labelling datapath + *inputs *************************************************/ size_t find_mux_num_datapath_inputs(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, const size_t& mux_size) { /* Should be either MUX or LUT - * LUTs do have an tree-like MUX, but there is no need for a constant input! + * LUTs do have an tree-like MUX, but there is no need for a constant input! */ - VTR_ASSERT ((CIRCUIT_MODEL_MUX == circuit_lib.model_type(circuit_model)) - || (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)) ); + VTR_ASSERT((CIRCUIT_MODEL_MUX == circuit_lib.model_type(circuit_model)) || + (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model))); if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)) { return mux_size; @@ -54,17 +55,18 @@ size_t find_mux_num_datapath_inputs(const CircuitLibrary& circuit_lib, /************************************************** * Find the actual number of inputs for a multiplexer implementation - * 1. if there are no requirements on constant inputs, mux_size is the actual one + * 1. if there are no requirements on constant inputs, mux_size is the actual + *one * 2. if there exist constant inputs, mux_size should plus 1 *************************************************/ size_t find_mux_implementation_num_inputs(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, const size_t& mux_size) { /* Should be either MUX or LUT - * LUTs do have an tree-like MUX, but there is no need for a constant input! + * LUTs do have an tree-like MUX, but there is no need for a constant input! */ - VTR_ASSERT ((CIRCUIT_MODEL_MUX == circuit_lib.model_type(circuit_model)) - || (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)) ); + VTR_ASSERT((CIRCUIT_MODEL_MUX == circuit_lib.model_type(circuit_model)) || + (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model))); if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)) { return mux_size; @@ -78,26 +80,28 @@ size_t find_mux_implementation_num_inputs(const CircuitLibrary& circuit_lib, /************************************************** * Find the structure for a multiplexer implementation - * 1. In most cases, the structure should follow the + * 1. In most cases, the structure should follow the * mux_structure defined by users in the CircuitLibrary - * 2. However, a special case may apply when mux_size is 2 + * 2. However, a special case may apply when mux_size is 2 * In such case, we will force a TREE structure - * regardless of users' specification as this is the - * most efficient structure + * regardless of users' specification as this is the + * most efficient structure *************************************************/ -enum e_circuit_model_structure find_mux_implementation_structure(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const size_t& mux_size) { +enum e_circuit_model_structure find_mux_implementation_structure( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const size_t& mux_size) { /* Ensure the mux size is valid ! */ VTR_ASSERT(valid_mux_implementation_num_inputs(mux_size)); - /* Branch on the mux sizes */ + /* Branch on the mux sizes */ if (2 == mux_size) { /* Tree-like is the best structure of CMOS MUX2 */ - if (CIRCUIT_MODEL_DESIGN_CMOS == circuit_lib.design_tech_type(circuit_model)) { + if (CIRCUIT_MODEL_DESIGN_CMOS == + circuit_lib.design_tech_type(circuit_model)) { return CIRCUIT_MODEL_STRUCTURE_TREE; } - VTR_ASSERT_SAFE(CIRCUIT_MODEL_DESIGN_RRAM == circuit_lib.design_tech_type(circuit_model)); + VTR_ASSERT_SAFE(CIRCUIT_MODEL_DESIGN_RRAM == + circuit_lib.design_tech_type(circuit_model)); /* One-level is the best structure of RRAM MUX2 */ return CIRCUIT_MODEL_STRUCTURE_ONELEVEL; } @@ -109,10 +113,10 @@ enum e_circuit_model_structure find_mux_implementation_structure(const CircuitLi * Find the number of levels for a tree-like multiplexer implementation *************************************************/ size_t find_treelike_mux_num_levels(const size_t& mux_size) { - /* Do log2(mux_size), have a basic number */ - size_t level = (size_t)(log((double)mux_size)/log(2.)); + /* Do log2(mux_size), have a basic number */ + size_t level = (size_t)(log((double)mux_size) / log(2.)); /* Fix the error, i.e. mux_size=5, level = 2, we have to complete */ - while (mux_size > pow(2.,(double)level)) { + while (mux_size > pow(2., (double)level)) { level++; } @@ -120,23 +124,23 @@ size_t find_treelike_mux_num_levels(const size_t& mux_size) { } /************************************************** - * Find the number of inputs for majority of branches + * Find the number of inputs for majority of branches * in a multi-level multiplexer implementation *************************************************/ size_t find_multilevel_mux_branch_num_inputs(const size_t& mux_size, const size_t& mux_level) { /* Special Case: mux_size = 2 */ if (2 == mux_size) { - return mux_size; + return mux_size; } - + if (1 == mux_level) { return mux_size; - } + } if (2 == mux_level) { size_t num_input_per_unit = (size_t)sqrt(mux_size); - while ( num_input_per_unit * num_input_per_unit < mux_size) { + while (num_input_per_unit * num_input_per_unit < mux_size) { num_input_per_unit++; } return num_input_per_unit; @@ -151,36 +155,36 @@ size_t find_multilevel_mux_branch_num_inputs(const size_t& mux_size, if (!valid_mux_implementation_num_inputs(num_input_per_unit)) { VTR_LOG_ERROR("Number of inputs of each basis should be at least 2!\n"); - exit(1); + exit(1); } - + return num_input_per_unit; } /************************************************** * Build a location map for intermediate buffers * that may appear at the multiplexing structure of a LUT - * Here is a tricky thing: - * By default, the first and last stage should not exist any intermediate buffers - * For example: - * There are 5 stages in a 4-stage multiplexer is available for buffering - * but only 3 stages [1,2,3] are intermedate buffers - * and these are users' specification - * + * Here is a tricky thing: + * By default, the first and last stage should not exist any intermediate + *buffers For example: There are 5 stages in a 4-stage multiplexer is available + *for buffering but only 3 stages [1,2,3] are intermedate buffers and these are + *users' specification + * * +-------+ +-------+ +-------+ +-------+ - * location | stage | location | stage | location | stage | location | stage | location - * [0] | [0] | [1] | [1] | [2] | [2] | [3] | [3] | [5] + * location | stage | location | stage | location | stage | location | stage | + *location [0] | [0] | [1] | [1] | [2] | [2] | [3] | + *[3] | [5] * +-------+ +-------+ +-------+ +-------+ * * We will check if the length of location map matches the number of * multiplexer levels. And then complete a location map * for the given multiplexers *************************************************/ -std::vector build_mux_intermediate_buffer_location_map(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const size_t& num_mux_levels) { +std::vector build_mux_intermediate_buffer_location_map( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const size_t& num_mux_levels) { /* Deposite a default location map */ - std::vector location_map(num_mux_levels, false); + std::vector location_map(num_mux_levels, false); std::string location_map_str; /* ONLY for LUTs: intermediate buffers may exist if specified */ @@ -189,8 +193,9 @@ std::vector build_mux_intermediate_buffer_location_map(const CircuitLibrar } /* Get location map when the flag of intermediate buffer is on */ - if (true == circuit_lib.is_lut_intermediate_buffered(circuit_model)) { - location_map_str = circuit_lib.lut_intermediate_buffer_location_map(circuit_model); + if (true == circuit_lib.is_lut_intermediate_buffered(circuit_model)) { + location_map_str = + circuit_lib.lut_intermediate_buffer_location_map(circuit_model); } /* If no location map is specified, we can return here */ @@ -208,7 +213,7 @@ std::vector build_mux_intermediate_buffer_location_map(const CircuitLibrar location_map[i + 1] = true; } } - + return location_map; } @@ -224,49 +229,48 @@ size_t find_mux_num_reserved_config_bits(const CircuitLibrary& circuit_lib, return 0; } - std::vector mux_branch_sizes = mux_graph.branch_sizes(); + std::vector mux_branch_sizes = mux_graph.branch_sizes(); /* For tree-like multiplexers: they have two shared configuration bits */ - if ( (1 == mux_branch_sizes.size()) - && (2 == mux_branch_sizes[0]) ) { + if ((1 == mux_branch_sizes.size()) && (2 == mux_branch_sizes[0])) { return mux_branch_sizes[0]; } /* One-level multiplexer */ - if ( 1 == mux_graph.num_levels() ) { + if (1 == mux_graph.num_levels()) { return mux_graph.num_inputs(); } - /* Multi-level multiplexers: TODO: This should be better tested and clarified - * Now the multi-level multiplexers are treated as cascaded one-level multiplexers - * Use the maximum branch sizes and multiply it by the number of levels + /* Multi-level multiplexers: TODO: This should be better tested and clarified + * Now the multi-level multiplexers are treated as cascaded one-level + * multiplexers Use the maximum branch sizes and multiply it by the number of + * levels */ - std::vector::iterator max_mux_branch_size = std::max_element(mux_branch_sizes.begin(), mux_branch_sizes.end()); + std::vector::iterator max_mux_branch_size = + std::max_element(mux_branch_sizes.begin(), mux_branch_sizes.end()); return mux_graph.num_levels() * (*max_mux_branch_size); } /************************************************** * Find the number of configuration bits for a CMOS multiplexer - * In general, the number of configuration bits is + * In general, the number of configuration bits is * the number of memory bits for a mux_graph - * However, when local decoders are used, + * However, when local decoders are used, * the number of configuration bits are reduced to log2(X) *************************************************/ -static -size_t find_cmos_mux_num_config_bits(const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const MuxGraph& mux_graph, - const e_config_protocol_type& sram_orgz_type) { - size_t num_config_bits = 0; +static size_t find_cmos_mux_num_config_bits( + const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, + const MuxGraph& mux_graph, const e_config_protocol_type& sram_orgz_type) { + size_t num_config_bits = 0; switch (sram_orgz_type) { - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: - case CONFIG_MEM_SCAN_CHAIN: - case CONFIG_MEM_STANDALONE: - case CONFIG_MEM_FRAME_BASED: - num_config_bits = mux_graph.num_memory_bits(); - break; - default: - VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); - exit(1); + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: + case CONFIG_MEM_SCAN_CHAIN: + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_FRAME_BASED: + num_config_bits = mux_graph.num_memory_bits(); + break; + default: + VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); + exit(1); } if (false == circuit_lib.mux_use_local_encoder(mux_model)) { @@ -276,51 +280,50 @@ size_t find_cmos_mux_num_config_bits(const CircuitLibrary& circuit_lib, num_config_bits = 0; /* Multiplexer local encoders are applied to memory bits at each stage */ for (const auto& lvl : mux_graph.levels()) { - num_config_bits += find_mux_local_decoder_addr_size(mux_graph.num_memory_bits_at_level(lvl)); - } + num_config_bits += + find_mux_local_decoder_addr_size(mux_graph.num_memory_bits_at_level(lvl)); + } return num_config_bits; } /************************************************** * Find the number of configuration bits for a RRAM multiplexer - * In general, the number of configuration bits is + * In general, the number of configuration bits is * the number of levels for a mux_graph * This is due to only the last BL/WL of the multiplexer is * independent from each other - * However, when local decoders are used, + * However, when local decoders are used, * the number of configuration bits should be consider all the - * shared(reserved) configuration bits and independent bits + * shared(reserved) configuration bits and independent bits *************************************************/ -static -size_t find_rram_mux_num_config_bits(const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const MuxGraph& mux_graph, - const e_config_protocol_type& sram_orgz_type) { - size_t num_config_bits = 0; +static size_t find_rram_mux_num_config_bits( + const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, + const MuxGraph& mux_graph, const e_config_protocol_type& sram_orgz_type) { + size_t num_config_bits = 0; switch (sram_orgz_type) { - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: - /* In memory bank, by intensively share the Bit/Word Lines, - * we only need 1 additional BL and WL for each MUX level. - */ - num_config_bits = mux_graph.num_levels(); - break; - case CONFIG_MEM_SCAN_CHAIN: - case CONFIG_MEM_STANDALONE: - /* Currently we DO NOT SUPPORT THESE, given an invalid number */ - num_config_bits = size_t(-1); - break; - default: - VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); - exit(1); + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: + /* In memory bank, by intensively share the Bit/Word Lines, + * we only need 1 additional BL and WL for each MUX level. + */ + num_config_bits = mux_graph.num_levels(); + break; + case CONFIG_MEM_SCAN_CHAIN: + case CONFIG_MEM_STANDALONE: + /* Currently we DO NOT SUPPORT THESE, given an invalid number */ + num_config_bits = size_t(-1); + break; + default: + VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); + exit(1); } if (true == circuit_lib.mux_use_local_encoder(mux_model)) { - /* TODO: this is a to-do work for ReRAM-based multiplexers and FPGAs - * The number of states of a local decoder only depends on how many + /* TODO: this is a to-do work for ReRAM-based multiplexers and FPGAs + * The number of states of a local decoder only depends on how many * memory bits that the multiplexer will have - * This may NOT be correct!!! + * This may NOT be correct!!! */ return find_mux_local_decoder_addr_size(mux_graph.num_memory_bits()); } @@ -329,7 +332,7 @@ size_t find_rram_mux_num_config_bits(const CircuitLibrary& circuit_lib, } /************************************************** - * Find the number of configuration bits for + * Find the number of configuration bits for * a routing multiplexer * Two cases are considered here. * They are placed in different branches (sub-functions) @@ -337,21 +340,23 @@ size_t find_rram_mux_num_config_bits(const CircuitLibrary& circuit_lib, *************************************************/ size_t find_mux_num_config_bits(const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, - const MuxGraph& mux_graph, + const MuxGraph& mux_graph, const e_config_protocol_type& sram_orgz_type) { size_t num_config_bits = size_t(-1); switch (circuit_lib.design_tech_type(mux_model)) { - case CIRCUIT_MODEL_DESIGN_CMOS: - num_config_bits = find_cmos_mux_num_config_bits(circuit_lib, mux_model, mux_graph, sram_orgz_type); - break; - case CIRCUIT_MODEL_DESIGN_RRAM: - num_config_bits = find_rram_mux_num_config_bits(circuit_lib, mux_model, mux_graph, sram_orgz_type); - break; - default: - VTR_LOG_ERROR("Invalid design_technology of MUX(name: %s)\n", - circuit_lib.model_name(mux_model).c_str()); - exit(1); + case CIRCUIT_MODEL_DESIGN_CMOS: + num_config_bits = find_cmos_mux_num_config_bits( + circuit_lib, mux_model, mux_graph, sram_orgz_type); + break; + case CIRCUIT_MODEL_DESIGN_RRAM: + num_config_bits = find_rram_mux_num_config_bits( + circuit_lib, mux_model, mux_graph, sram_orgz_type); + break; + default: + VTR_LOG_ERROR("Invalid design_technology of MUX(name: %s)\n", + circuit_lib.model_name(mux_model).c_str()); + exit(1); } return num_config_bits; @@ -360,22 +365,22 @@ size_t find_mux_num_config_bits(const CircuitLibrary& circuit_lib, /************************************************** * Find the number of shared configuration bits for a CMOS multiplexer * Currently, all the supported CMOS multiplexers - * do NOT require any shared configuration bits + * do NOT require any shared configuration bits *************************************************/ -static -size_t find_cmos_mux_num_shared_config_bits(const e_config_protocol_type& sram_orgz_type) { - size_t num_shared_config_bits = 0; +static size_t find_cmos_mux_num_shared_config_bits( + const e_config_protocol_type& sram_orgz_type) { + size_t num_shared_config_bits = 0; switch (sram_orgz_type) { - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: - case CONFIG_MEM_SCAN_CHAIN: - case CONFIG_MEM_STANDALONE: - num_shared_config_bits = 0; - break; - default: - VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); - exit(1); + case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_MEMORY_BANK: + case CONFIG_MEM_SCAN_CHAIN: + case CONFIG_MEM_STANDALONE: + num_shared_config_bits = 0; + break; + default: + VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); + exit(1); } return num_shared_config_bits; @@ -384,42 +389,41 @@ size_t find_cmos_mux_num_shared_config_bits(const e_config_protocol_type& sram_o /************************************************** * Find the number of shared configuration bits for a ReRAM multiplexer *************************************************/ -static -size_t find_rram_mux_num_shared_config_bits(const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const MuxGraph& mux_graph, - const e_config_protocol_type& sram_orgz_type) { - size_t num_shared_config_bits = 0; +static size_t find_rram_mux_num_shared_config_bits( + const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, + const MuxGraph& mux_graph, const e_config_protocol_type& sram_orgz_type) { + size_t num_shared_config_bits = 0; switch (sram_orgz_type) { - case CONFIG_MEM_QL_MEMORY_BANK: { - /* In memory bank, the number of shared configuration bits is - * the sum of largest branch size at each level - */ - for (auto lvl : mux_graph.node_levels()) { - /* Find the maximum branch size: - * Note that branch_sizes() returns a sorted vector - * The last one is the maximum + case CONFIG_MEM_QL_MEMORY_BANK: { + /* In memory bank, the number of shared configuration bits is + * the sum of largest branch size at each level */ - num_shared_config_bits += mux_graph.branch_sizes(lvl).back(); + for (auto lvl : mux_graph.node_levels()) { + /* Find the maximum branch size: + * Note that branch_sizes() returns a sorted vector + * The last one is the maximum + */ + num_shared_config_bits += mux_graph.branch_sizes(lvl).back(); + } + break; } - break; - } - case CONFIG_MEM_SCAN_CHAIN: - case CONFIG_MEM_STANDALONE: - /* Currently we DO NOT SUPPORT THESE, given an invalid number */ - num_shared_config_bits = size_t(-1); - break; - default: - VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); - exit(1); + case CONFIG_MEM_SCAN_CHAIN: + case CONFIG_MEM_STANDALONE: + /* Currently we DO NOT SUPPORT THESE, given an invalid number */ + num_shared_config_bits = size_t(-1); + break; + default: + VTR_LOG_ERROR("Invalid type of SRAM organization!\n"); + exit(1); } if (true == circuit_lib.mux_use_local_encoder(mux_model)) { - /* TODO: this is a to-do work for ReRAM-based multiplexers and FPGAs - * The number of states of a local decoder only depends on how many + /* TODO: this is a to-do work for ReRAM-based multiplexers and FPGAs + * The number of states of a local decoder only depends on how many * memory bits that the multiplexer will have - * This may NOT be correct!!! - * If local encoders are introduced, zero shared configuration bits are required + * This may NOT be correct!!! + * If local encoders are introduced, zero shared configuration bits are + * required */ return 0; } @@ -428,7 +432,7 @@ size_t find_rram_mux_num_shared_config_bits(const CircuitLibrary& circuit_lib, } /************************************************** - * Find the number of shared configuration bits for + * Find the number of shared configuration bits for * a routing multiplexer * Two cases are considered here. * They are placed in different branches (sub-functions) @@ -437,23 +441,24 @@ size_t find_rram_mux_num_shared_config_bits(const CircuitLibrary& circuit_lib, * Note: currently, shared configuration bits are demanded * by ReRAM-based multiplexers only *************************************************/ -size_t find_mux_num_shared_config_bits(const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const MuxGraph& mux_graph, - const e_config_protocol_type& sram_orgz_type) { +size_t find_mux_num_shared_config_bits( + const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, + const MuxGraph& mux_graph, const e_config_protocol_type& sram_orgz_type) { size_t num_shared_config_bits = size_t(-1); switch (circuit_lib.design_tech_type(mux_model)) { - case CIRCUIT_MODEL_DESIGN_CMOS: - num_shared_config_bits = find_cmos_mux_num_shared_config_bits(sram_orgz_type); - break; - case CIRCUIT_MODEL_DESIGN_RRAM: - num_shared_config_bits = find_rram_mux_num_shared_config_bits(circuit_lib, mux_model, mux_graph, sram_orgz_type); - break; - default: - VTR_LOG_ERROR("Invalid design_technology of MUX(name: %s)\n", - circuit_lib.model_name(mux_model).c_str()); - exit(1); + case CIRCUIT_MODEL_DESIGN_CMOS: + num_shared_config_bits = + find_cmos_mux_num_shared_config_bits(sram_orgz_type); + break; + case CIRCUIT_MODEL_DESIGN_RRAM: + num_shared_config_bits = find_rram_mux_num_shared_config_bits( + circuit_lib, mux_model, mux_graph, sram_orgz_type); + break; + default: + VTR_LOG_ERROR("Invalid design_technology of MUX(name: %s)\n", + circuit_lib.model_name(mux_model).c_str()); + exit(1); } return num_shared_config_bits; diff --git a/openfpga/src/utils/mux_utils.h b/openfpga/src/utils/mux_utils.h index cf2ce95ad..333c0a593 100644 --- a/openfpga/src/utils/mux_utils.h +++ b/openfpga/src/utils/mux_utils.h @@ -27,18 +27,18 @@ size_t find_mux_implementation_num_inputs(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, const size_t& mux_size); -enum e_circuit_model_structure find_mux_implementation_structure(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const size_t& mux_size); +enum e_circuit_model_structure find_mux_implementation_structure( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const size_t& mux_size); size_t find_treelike_mux_num_levels(const size_t& mux_size); size_t find_multilevel_mux_branch_num_inputs(const size_t& mux_size, const size_t& mux_level); -std::vector build_mux_intermediate_buffer_location_map(const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model, - const size_t& num_mux_levels); +std::vector build_mux_intermediate_buffer_location_map( + const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, + const size_t& num_mux_levels); size_t find_mux_num_reserved_config_bits(const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, @@ -46,13 +46,12 @@ size_t find_mux_num_reserved_config_bits(const CircuitLibrary& circuit_lib, size_t find_mux_num_config_bits(const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, - const MuxGraph& mux_graph, + const MuxGraph& mux_graph, const e_config_protocol_type& sram_orgz_type); -size_t find_mux_num_shared_config_bits(const CircuitLibrary& circuit_lib, - const CircuitModelId& mux_model, - const MuxGraph& mux_graph, - const e_config_protocol_type& sram_orgz_type); +size_t find_mux_num_shared_config_bits( + const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, + const MuxGraph& mux_graph, const e_config_protocol_type& sram_orgz_type); } /* End namespace openfpga*/ diff --git a/openfpga/src/utils/openfpga_atom_netlist_utils.cpp b/openfpga/src/utils/openfpga_atom_netlist_utils.cpp index 9539a7c91..2bcd89a54 100644 --- a/openfpga/src/utils/openfpga_atom_netlist_utils.cpp +++ b/openfpga/src/utils/openfpga_atom_netlist_utils.cpp @@ -1,34 +1,36 @@ /*************************************************************************************** - * This file includes most utilized functions that are used to acquire data from + * This file includes most utilized functions that are used to acquire data from * VPR atom netlist (users' netlist to implement) ***************************************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from vtrutil library */ #include "atom_netlist_utils.h" - -#include "openfpga_reserved_words.h" #include "openfpga_atom_netlist_utils.h" +#include "openfpga_reserved_words.h" /* begin namespace openfpga */ namespace openfpga { /*************************************************************************************** - * Find the names of all the atom blocks that drive clock nets - * This function will find if the block has been renamed due to contain sensitive characters - * that violates the Verilog syntax + * Find the names of all the atom blocks that drive clock nets + * This function will find if the block has been renamed due to contain + *sensitive characters that violates the Verilog syntax ***************************************************************************************/ -std::vector find_atom_netlist_clock_port_names(const AtomNetlist& atom_nlist, - const VprNetlistAnnotation& netlist_annotation) { +std::vector find_atom_netlist_clock_port_names( + const AtomNetlist& atom_nlist, + const VprNetlistAnnotation& netlist_annotation) { std::vector clock_names; - std::set clock_pins = find_netlist_logical_clock_drivers(atom_nlist); + std::set clock_pins = + find_netlist_logical_clock_drivers(atom_nlist); for (const AtomPinId& clock_pin : clock_pins) { - const AtomBlockId& atom_blk = atom_nlist.port_block(atom_nlist.pin_port(clock_pin)); + const AtomBlockId& atom_blk = + atom_nlist.port_block(atom_nlist.pin_port(clock_pin)); std::string block_name = atom_nlist.block_name(atom_blk); if (true == netlist_annotation.is_block_renamed(atom_blk)) { block_name = netlist_annotation.block_name(atom_blk); @@ -40,7 +42,7 @@ std::vector find_atom_netlist_clock_port_names(const AtomNetlist& a } /******************************************************************** - * Remove the prefix that is added to the name of a output block (by VPR) + * Remove the prefix that is added to the name of a output block (by VPR) *******************************************************************/ std::string remove_atom_block_name_prefix(const std::string& block_name) { /* VPR added a prefix of "out_" to the output ports of input benchmark */ @@ -58,7 +60,7 @@ std::string remove_atom_block_name_prefix(const std::string& block_name) { } } } - + return ret_block_name; } diff --git a/openfpga/src/utils/openfpga_atom_netlist_utils.h b/openfpga/src/utils/openfpga_atom_netlist_utils.h index 3ddad6a93..f25845c83 100644 --- a/openfpga/src/utils/openfpga_atom_netlist_utils.h +++ b/openfpga/src/utils/openfpga_atom_netlist_utils.h @@ -4,8 +4,9 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include #include +#include + #include "atom_netlist.h" #include "vpr_netlist_annotation.h" @@ -16,8 +17,9 @@ /* begin namespace openfpga */ namespace openfpga { -std::vector find_atom_netlist_clock_port_names(const AtomNetlist& atom_nlist, - const VprNetlistAnnotation& netlist_annotation); +std::vector find_atom_netlist_clock_port_names( + const AtomNetlist& atom_nlist, + const VprNetlistAnnotation& netlist_annotation); std::string remove_atom_block_name_prefix(const std::string& block_name); diff --git a/openfpga/src/utils/openfpga_device_grid_utils.cpp b/openfpga/src/utils/openfpga_device_grid_utils.cpp index 938e39db0..5a234b60d 100644 --- a/openfpga/src/utils/openfpga_device_grid_utils.cpp +++ b/openfpga/src/utils/openfpga_device_grid_utils.cpp @@ -1,15 +1,15 @@ /*************************************************************************************** - * This file includes most utilized functions that are used to acquire data from + * This file includes most utilized functions that are used to acquire data from * VPR DeviceGrid ***************************************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" -#include "vtr_assert.h" -#include "vtr_time.h" - #include "openfpga_device_grid_utils.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + /* begin namespace openfpga */ namespace openfpga { @@ -26,34 +26,35 @@ namespace openfpga { * i.e., the top-left, top-right, bottom-left and bottom-right * * Note: - * - This function offers a standard sequence to walk through the + * - This function offers a standard sequence to walk through the * grids on the perimeter of an FPGA device * When sequence matters, this function should be used to ensure * consistency between functions. *******************************************************************/ -std::map>> generate_perimeter_grid_coordinates(const DeviceGrid& grids) { +std::map>> +generate_perimeter_grid_coordinates(const DeviceGrid& grids) { /* Search the border side */ /* Create the coordinate range for each side of FPGA fabric */ std::vector fpga_sides{TOP, RIGHT, BOTTOM, LEFT}; std::map>> io_coordinates; /* TOP side*/ - for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { io_coordinates[TOP].push_back(vtr::Point(ix, grids.height() - 1)); - } + } /* RIGHT side */ - for (size_t iy = grids.height() - 2; iy > 0; --iy) { + for (size_t iy = grids.height() - 2; iy > 0; --iy) { io_coordinates[RIGHT].push_back(vtr::Point(grids.width() - 1, iy)); - } + } /* BOTTOM side*/ - for (size_t ix = grids.width() - 2; ix > 0; --ix) { + for (size_t ix = grids.width() - 2; ix > 0; --ix) { io_coordinates[BOTTOM].push_back(vtr::Point(ix, 0)); - } + } /* LEFT side */ - for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { io_coordinates[LEFT].push_back(vtr::Point(0, iy)); } diff --git a/openfpga/src/utils/openfpga_device_grid_utils.h b/openfpga/src/utils/openfpga_device_grid_utils.h index ae6fa2949..4b49be150 100644 --- a/openfpga/src/utils/openfpga_device_grid_utils.h +++ b/openfpga/src/utils/openfpga_device_grid_utils.h @@ -4,9 +4,10 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include -#include #include +#include +#include + #include "device_grid.h" #include "vtr_geometry.h" @@ -20,7 +21,8 @@ namespace openfpga { /* A constant array to walk through FPGA border sides clockwise*/ constexpr std::array FPGA_SIDES_CLOCKWISE{TOP, RIGHT, BOTTOM, LEFT}; -std::map>> generate_perimeter_grid_coordinates(const DeviceGrid& grids); +std::map>> +generate_perimeter_grid_coordinates(const DeviceGrid& grids); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/openfpga_physical_tile_utils.cpp b/openfpga/src/utils/openfpga_physical_tile_utils.cpp index 95942ccaf..8003d7123 100644 --- a/openfpga/src/utils/openfpga_physical_tile_utils.cpp +++ b/openfpga/src/utils/openfpga_physical_tile_utils.cpp @@ -1,50 +1,52 @@ /*************************************************************************************** - * This file includes most utilized functions that are used to acquire data from - * VPR t_physical_tile_type + * This file includes most utilized functions that are used to acquire data from + * VPR t_physical_tile_type ***************************************************************************************/ /* Headers from vtrutil library */ -#include "vtr_log.h" #include "vtr_assert.h" +#include "vtr_log.h" #include "vtr_time.h" /* Headers from openfpgautil library */ -#include "openfpga_side_manager.h" - #include "openfpga_device_grid_utils.h" #include "openfpga_physical_tile_utils.h" +#include "openfpga_side_manager.h" /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * Give a given pin index, find the side where this pin is located + * Give a given pin index, find the side where this pin is located * on the physical tile * Note: * - Need to check if the pin_width_offset and pin_height_offset * are properly set in VPR!!! *******************************************************************/ -std::vector find_physical_tile_pin_side(t_physical_tile_type_ptr physical_tile, - const int& physical_pin, - const e_side& border_side) { +std::vector find_physical_tile_pin_side( + t_physical_tile_type_ptr physical_tile, const int& physical_pin, + const e_side& border_side) { std::vector pin_sides; for (const e_side& side_cand : {TOP, RIGHT, BOTTOM, LEFT}) { int pin_width_offset = physical_tile->pin_width_offset[physical_pin]; int pin_height_offset = physical_tile->pin_height_offset[physical_pin]; - if (true == physical_tile->pinloc[pin_width_offset][pin_height_offset][side_cand][physical_pin]) { + if (true == physical_tile->pinloc[pin_width_offset][pin_height_offset] + [side_cand][physical_pin]) { pin_sides.push_back(side_cand); - } + } } /* For regular grid, we should have pin only one side! - * I/O grids: VPR creates the grid with duplicated pins on every side - * but the expected side (only used side) will be opposite side of the border side! + * I/O grids: VPR creates the grid with duplicated pins on every side + * but the expected side (only used side) will be opposite side of the border + * side! */ if (NUM_SIDES == border_side) { VTR_ASSERT(1 == pin_sides.size()); } else { SideManager side_manager(border_side); - VTR_ASSERT(pin_sides.end() != std::find(pin_sides.begin(), pin_sides.end(), side_manager.get_opposite())); + VTR_ASSERT(pin_sides.end() != std::find(pin_sides.begin(), pin_sides.end(), + side_manager.get_opposite())); pin_sides.clear(); pin_sides.push_back(side_manager.get_opposite()); } @@ -53,35 +55,34 @@ std::vector find_physical_tile_pin_side(t_physical_tile_type_ptr physica } /******************************************************************** - * Find the Fc of a pin in physical tile + * Find the Fc of a pin in physical tile *******************************************************************/ -float find_physical_tile_pin_Fc(t_physical_tile_type_ptr type, - const int& pin) { +float find_physical_tile_pin_Fc(t_physical_tile_type_ptr type, const int& pin) { for (const t_fc_specification& fc_spec : type->fc_specs) { - if (fc_spec.pins.end() != std::find(fc_spec.pins.begin(), fc_spec.pins.end(), pin)) { - return fc_spec.fc_value; + if (fc_spec.pins.end() != + std::find(fc_spec.pins.begin(), fc_spec.pins.end(), pin)) { + return fc_spec.fc_value; } } /* Every pin should have a Fc, give a wrong value */ - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Fail to find the Fc for %s.pin[%lu]\n", - type->name, pin); + VTR_LOGF_ERROR(__FILE__, __LINE__, "Fail to find the Fc for %s.pin[%lu]\n", + type->name, pin); exit(1); -} +} /******************************************************************** * Find sides/locations of a I/O physical tile in the context of a FPGA fabric - * The I/O grid may locate at + * The I/O grid may locate at * - one or more border of a FPGA (TOP, RIGHT, BOTTOM, LEFT) - * We will collect each side that the I/O locates + * We will collect each side that the I/O locates * - the center of a FPGA * We will add NUM_SIDEs for these I/Os *******************************************************************/ -std::set find_physical_io_tile_located_sides(const DeviceGrid& grids, - t_physical_tile_type_ptr physical_tile) { +std::set find_physical_io_tile_located_sides( + const DeviceGrid& grids, t_physical_tile_type_ptr physical_tile) { std::set io_sides; bool center_io = false; - + /* Search the core part */ for (size_t ix = 1; ix < grids.width() - 1; ++ix) { for (size_t iy = 1; iy < grids.height() - 1; ++iy) { @@ -90,16 +91,17 @@ std::set find_physical_io_tile_located_sides(const DeviceGrid& grids, io_sides.insert(NUM_SIDES); center_io = true; break; - } + } } if (true == center_io) { break; } - } + } /* Search the border side */ /* Create the coordinate range for each side of FPGA fabric */ - std::map>> io_coordinates = generate_perimeter_grid_coordinates( grids); + std::map>> io_coordinates = + generate_perimeter_grid_coordinates(grids); for (const e_side& fpga_side : FPGA_SIDES_CLOCKWISE) { for (const vtr::Point& io_coordinate : io_coordinates[fpga_side]) { @@ -107,7 +109,7 @@ std::set find_physical_io_tile_located_sides(const DeviceGrid& grids, if (physical_tile == grids[io_coordinate.x()][io_coordinate.y()].type) { io_sides.insert(fpga_side); break; - } + } } } diff --git a/openfpga/src/utils/openfpga_physical_tile_utils.h b/openfpga/src/utils/openfpga_physical_tile_utils.h index b30ac4b76..4a9ce4cd8 100644 --- a/openfpga/src/utils/openfpga_physical_tile_utils.h +++ b/openfpga/src/utils/openfpga_physical_tile_utils.h @@ -4,9 +4,10 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include -#include #include +#include +#include + #include "device_grid.h" #include "physical_types.h" @@ -17,15 +18,14 @@ /* begin namespace openfpga */ namespace openfpga { -std::vector find_physical_tile_pin_side(t_physical_tile_type_ptr physical_tile, - const int& physical_pin, - const e_side& border_side); +std::vector find_physical_tile_pin_side( + t_physical_tile_type_ptr physical_tile, const int& physical_pin, + const e_side& border_side); -float find_physical_tile_pin_Fc(t_physical_tile_type_ptr type, - const int& pin); +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); +std::set find_physical_io_tile_located_sides( + const DeviceGrid& grids, t_physical_tile_type_ptr physical_tile); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/pb_graph_utils.cpp b/openfpga/src/utils/pb_graph_utils.cpp index a3d6a999e..4b80bd596 100644 --- a/openfpga/src/utils/pb_graph_utils.cpp +++ b/openfpga/src/utils/pb_graph_utils.cpp @@ -3,34 +3,39 @@ * and pb_graph_pin data structure in the OpenFPGA context *******************************************************************/ /* Headers from vtrutil library */ +#include "pb_graph_utils.h" + #include "vtr_assert.h" #include "vtr_log.h" -#include "pb_graph_utils.h" - /* begin namespace openfpga */ namespace openfpga { /******************************************************************** - * This function aims to find out all the pb_graph_pins that drive + * This function aims to find out all the pb_graph_pins that drive * a given pb_graph pin w.r.t. a given interconnect definition *******************************************************************/ -std::vector pb_graph_pin_inputs(t_pb_graph_pin* pb_graph_pin, - t_interconnect* selected_interconnect) { +std::vector pb_graph_pin_inputs( + t_pb_graph_pin* pb_graph_pin, t_interconnect* selected_interconnect) { std::vector inputs; - /* Search the input edges only, stats on the size of MUX we may need (fan-in) */ + /* Search the input edges only, stats on the size of MUX we may need (fan-in) + */ for (int iedge = 0; iedge < pb_graph_pin->num_input_edges; ++iedge) { /* We care the only edges in the selected mode */ - if (selected_interconnect != pb_graph_pin->input_edges[iedge]->interconnect) { + if (selected_interconnect != + pb_graph_pin->input_edges[iedge]->interconnect) { continue; } - for (int ipin = 0; ipin < pb_graph_pin->input_edges[iedge]->num_input_pins; ++ipin) { + for (int ipin = 0; ipin < pb_graph_pin->input_edges[iedge]->num_input_pins; + ++ipin) { /* Ensure that the pin is unique in the list */ - if (inputs.end() != std::find(inputs.begin(), inputs.end(), pb_graph_pin->input_edges[iedge]->input_pins[ipin])) { + if (inputs.end() != + std::find(inputs.begin(), inputs.end(), + pb_graph_pin->input_edges[iedge]->input_pins[ipin])) { continue; } - /* Unique pin, push to the vector */ + /* Unique pin, push to the vector */ inputs.push_back(pb_graph_pin->input_edges[iedge]->input_pins[ipin]); } } @@ -42,14 +47,16 @@ std::vector pb_graph_pin_inputs(t_pb_graph_pin* pb_graph_pin, * This function aims to find out the interconnect that drives * a given pb_graph pin when operating in a select mode *******************************************************************/ -t_interconnect* pb_graph_pin_interc(t_pb_graph_pin* pb_graph_pin, +t_interconnect* pb_graph_pin_interc(t_pb_graph_pin* pb_graph_pin, t_mode* selected_mode) { t_interconnect* interc = nullptr; - /* Search the input edges only, stats on the size of MUX we may need (fan-in) */ + /* Search the input edges only, stats on the size of MUX we may need (fan-in) + */ for (int iedge = 0; iedge < pb_graph_pin->num_input_edges; ++iedge) { /* We care the only edges in the selected mode */ - if (selected_mode != pb_graph_pin->input_edges[iedge]->interconnect->parent_mode) { + if (selected_mode != + pb_graph_pin->input_edges[iedge]->interconnect->parent_mode) { continue; } /* There should be one unique interconnect to be found! */ @@ -59,8 +66,8 @@ t_interconnect* pb_graph_pin_interc(t_pb_graph_pin* pb_graph_pin, interc = pb_graph_pin->input_edges[iedge]->interconnect; } } - - return interc; -} + + return interc; +} } /* end namespace openfpga */ diff --git a/openfpga/src/utils/pb_graph_utils.h b/openfpga/src/utils/pb_graph_utils.h index 8c1c3064a..209f87b9f 100644 --- a/openfpga/src/utils/pb_graph_utils.h +++ b/openfpga/src/utils/pb_graph_utils.h @@ -6,6 +6,7 @@ *******************************************************************/ #include #include + #include "physical_types.h" /******************************************************************** @@ -15,11 +16,11 @@ /* begin namespace openfpga */ namespace openfpga { -std::vector pb_graph_pin_inputs(t_pb_graph_pin* pb_graph_pin, - t_interconnect* selected_interconnect); +std::vector pb_graph_pin_inputs( + t_pb_graph_pin* pb_graph_pin, t_interconnect* selected_interconnect); -t_interconnect* pb_graph_pin_interc(t_pb_graph_pin* pb_graph_pin, - t_mode* selected_mode); +t_interconnect* pb_graph_pin_interc(t_pb_graph_pin* pb_graph_pin, + t_mode* selected_mode); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/pb_type_utils.cpp b/openfpga/src/utils/pb_type_utils.cpp index c9fed784c..cb89a4fc8 100644 --- a/openfpga/src/utils/pb_type_utils.cpp +++ b/openfpga/src/utils/pb_type_utils.cpp @@ -5,27 +5,26 @@ #include /* Headers from vtrutil library */ +#include "pb_type_utils.h" #include "vtr_assert.h" #include "vtr_log.h" -#include "pb_type_utils.h" - /* begin namespace openfpga */ namespace openfpga { -/************************************************************************ +/************************************************************************ * A pb_type is considered to be primitive when it has zero modes * However, this not always true. An exception is the LUT_CLASS - * VPR added two modes by default to a LUT pb_type. Therefore, + * VPR added two modes by default to a LUT pb_type. Therefore, * for LUT_CLASS, it is a primitive when it is binded to a blif model * - * Note: + * Note: * - if VPR changes its mode organization for LUT pb_type * this code should be adapted as well! ************************************************************************/ bool is_primitive_pb_type(t_pb_type* pb_type) { if (LUT_CLASS == pb_type->class_type) { - /* The only primitive LUT we recognize is the one which have + /* The only primitive LUT we recognize is the one which have * a first mode of LUT is wire, the second is the regular LUT * VPR contructed two modes under a regular LUT, and these children * are labelled as LUT_CLASS as well. OpenFPGA does not consider @@ -34,8 +33,9 @@ bool is_primitive_pb_type(t_pb_type* pb_type) { if (0 == pb_type->num_modes) { return false; } - VTR_ASSERT( (std::string("wire") == std::string(pb_type->modes[0].name)) - && (std::string(pb_type->name) == std::string(pb_type->modes[1].name))); + VTR_ASSERT( + (std::string("wire") == std::string(pb_type->modes[0].name)) && + (std::string(pb_type->name) == std::string(pb_type->modes[1].name))); return true; } else if (MEMORY_CLASS == pb_type->class_type) { /* The only primitive memory we recognize is the one which has a mode @@ -47,48 +47,50 @@ bool is_primitive_pb_type(t_pb_type* pb_type) { if (0 == pb_type->num_modes) { return false; } - VTR_ASSERT( (std::string("memory_slice") == std::string(pb_type->modes[0].name)) - || (std::string("memory_slice_1bit") == std::string(pb_type->modes[0].name))); + VTR_ASSERT( + (std::string("memory_slice") == std::string(pb_type->modes[0].name)) || + (std::string("memory_slice_1bit") == + std::string(pb_type->modes[0].name))); return true; - } return 0 == pb_type->num_modes; } -/************************************************************************ +/************************************************************************ * A pb_type is the root pb_type when it has no parent mode ************************************************************************/ -bool is_root_pb_type(t_pb_type* pb_type) { - return pb_type->parent_mode == nullptr; +bool is_root_pb_type(t_pb_type* pb_type) { + return pb_type->parent_mode == nullptr; } -/************************************************************************ +/************************************************************************ * With a given mode name, find the mode pointer ************************************************************************/ t_mode* find_pb_type_mode(t_pb_type* pb_type, const char* mode_name) { for (int i = 0; i < pb_type->num_modes; ++i) { if (std::string(mode_name) == std::string(pb_type->modes[i].name)) { - return &(pb_type->modes[i]); + return &(pb_type->modes[i]); } } /* Note found, return a nullptr */ return nullptr; } -/************************************************************************ +/************************************************************************ * With a given pb_type name, find the pb_type pointer ************************************************************************/ t_pb_type* find_mode_child_pb_type(t_mode* mode, const char* child_name) { for (int i = 0; i < mode->num_pb_type_children; ++i) { - if (std::string(child_name) == std::string(mode->pb_type_children[i].name)) { - return &(mode->pb_type_children[i]); + if (std::string(child_name) == + std::string(mode->pb_type_children[i].name)) { + return &(mode->pb_type_children[i]); } } /* Note found, return a nullptr */ return nullptr; } -/************************************************************************ +/************************************************************************ * With a given pb_type, provide a list of its ports ************************************************************************/ std::vector pb_type_ports(t_pb_type* pb_type) { @@ -99,7 +101,7 @@ std::vector pb_type_ports(t_pb_type* pb_type) { return ports; } -/************************************************************************ +/************************************************************************ * Find a port for a pb_type with a given name * If not found, return null pointer ************************************************************************/ @@ -114,13 +116,14 @@ t_port* find_pb_type_port(t_pb_type* pb_type, const std::string& port_name) { /******************************************************************** * This function will traverse pb_type graph from its top to find - * a pb_type with a given name as well as its hierarchy + * a pb_type with a given name as well as its hierarchy *******************************************************************/ -t_pb_type* try_find_pb_type_with_given_path(t_pb_type* top_pb_type, - const std::vector& target_pb_type_names, - const std::vector& target_pb_mode_names) { +t_pb_type* try_find_pb_type_with_given_path( + t_pb_type* top_pb_type, const std::vector& target_pb_type_names, + const std::vector& target_pb_mode_names) { /* Ensure that number of parent names and modes matches */ - VTR_ASSERT_SAFE(target_pb_type_names.size() == target_pb_mode_names.size() + 1); + VTR_ASSERT_SAFE(target_pb_type_names.size() == + target_pb_mode_names.size() + 1); t_pb_type* cur_pb_type = top_pb_type; @@ -134,8 +137,8 @@ t_pb_type* try_find_pb_type_with_given_path(t_pb_type* top_pb_type, } /* We start from the first element of the parent names and parent modes. - * If the pb_type does not match in name, we fail - * If we cannot find a mode match the name, we fail + * If the pb_type does not match in name, we fail + * If we cannot find a mode match the name, we fail */ for (size_t i = 0; i < target_pb_type_names.size() - 1; ++i) { /* If this level does not match, search fail */ @@ -143,12 +146,14 @@ t_pb_type* try_find_pb_type_with_given_path(t_pb_type* top_pb_type, return nullptr; } /* Find if the mode matches */ - t_mode* cur_mode = find_pb_type_mode(cur_pb_type, target_pb_mode_names[i].c_str()); + t_mode* cur_mode = + find_pb_type_mode(cur_pb_type, target_pb_mode_names[i].c_str()); if (nullptr == cur_mode) { return nullptr; } /* Go to the next level of pb_type */ - cur_pb_type = find_mode_child_pb_type(cur_mode, target_pb_type_names[i + 1].c_str()); + cur_pb_type = + find_mode_child_pb_type(cur_mode, target_pb_type_names[i + 1].c_str()); if (nullptr == cur_pb_type) { return nullptr; } @@ -179,12 +184,14 @@ std::vector pb_mode_interconnects(t_mode* pb_mode) { * of pb_type with a given name. * If not found, return null pointer *******************************************************************/ -t_interconnect* find_pb_mode_interconnect(t_mode* pb_mode, const char* interc_name) { +t_interconnect* find_pb_mode_interconnect(t_mode* pb_mode, + const char* interc_name) { for (int i = 0; i < pb_mode->num_interconnect; ++i) { - if (std::string(interc_name) == std::string(pb_mode->interconnect[i].name)) { + if (std::string(interc_name) == + std::string(pb_mode->interconnect[i].name)) { return &(pb_mode->interconnect[i]); } - } + } /* Reach here, it means we find nothing */ return nullptr; @@ -201,28 +208,29 @@ t_interconnect* find_pb_mode_interconnect(t_mode* pb_mode, const char* interc_na e_interconnect pb_interconnect_physical_type(t_interconnect* pb_interc, const size_t& num_inputs) { /* Check */ - VTR_ASSERT(nullptr != pb_interc); + VTR_ASSERT(nullptr != pb_interc); - /* Initialize the interconnection type that will be implemented in SPICE netlist*/ + /* Initialize the interconnection type that will be implemented in SPICE + * netlist*/ switch (pb_interc->type) { - case DIRECT_INTERC: - return DIRECT_INTERC; - break; - case COMPLETE_INTERC: - if (1 == num_inputs) { + case DIRECT_INTERC: return DIRECT_INTERC; - } else { - VTR_ASSERT(1 < num_inputs); + break; + case COMPLETE_INTERC: + if (1 == num_inputs) { + return DIRECT_INTERC; + } else { + VTR_ASSERT(1 < num_inputs); + return MUX_INTERC; + } + break; + case MUX_INTERC: return MUX_INTERC; - } - break; - case MUX_INTERC: - return MUX_INTERC; - break; - default: - VTR_LOG_ERROR("Invalid type for interconnection '%s'!\n", - pb_interc->name); - exit(1); + break; + default: + VTR_LOG_ERROR("Invalid type for interconnection '%s'!\n", + pb_interc->name); + exit(1); } return NUM_INTERC_TYPES; @@ -233,21 +241,23 @@ e_interconnect pb_interconnect_physical_type(t_interconnect* pb_interc, * that will be used to implement the physical design: * - MUX_INTERC -> CIRCUIT_MODEL_MUX * - DIRECT_INTERC -> CIRCUIT_MODEL_WIRE - * - * Note: + * + * Note: * - COMPLETE_INTERC should not appear here! * - We assume the interconnect type is the physical type - * after interconnect physical type annotation is done! + * after interconnect physical type annotation is done! *******************************************************************/ -e_circuit_model_type pb_interconnect_require_circuit_model_type(const e_interconnect& pb_interc_type) { +e_circuit_model_type pb_interconnect_require_circuit_model_type( + const e_interconnect& pb_interc_type) { /* A map from interconnect type to circuit model type */ std::map type_mapping; type_mapping[MUX_INTERC] = CIRCUIT_MODEL_MUX; type_mapping[DIRECT_INTERC] = CIRCUIT_MODEL_WIRE; - VTR_ASSERT((MUX_INTERC == pb_interc_type) || (DIRECT_INTERC == pb_interc_type)); - - return type_mapping.at(pb_interc_type); + VTR_ASSERT((MUX_INTERC == pb_interc_type) || + (DIRECT_INTERC == pb_interc_type)); + + return type_mapping.at(pb_interc_type); } /******************************************************************** @@ -256,10 +266,12 @@ e_circuit_model_type pb_interconnect_require_circuit_model_type(const e_intercon * We start from the view of a circuit port here. * This is due to circuit port has more types than a pb_type port * as it is designed for physical implementation - * As such, a few types of circuit port may be directed the same type of pb_type port - * This is done to make the mapping much simpler than doing in the opposite direction + * As such, a few types of circuit port may be directed the same type of pb_type + *port This is done to make the mapping much simpler than doing in the opposite + *direction *******************************************************************/ -enum PORTS circuit_port_require_pb_port_type(const e_circuit_model_port_type& circuit_port_type) { +enum PORTS circuit_port_require_pb_port_type( + const e_circuit_model_port_type& circuit_port_type) { std::map type_mapping; /* These circuit model ports may be founed in the pb_type ports */ @@ -268,66 +280,69 @@ enum PORTS circuit_port_require_pb_port_type(const e_circuit_model_port_type& ci type_mapping[CIRCUIT_MODEL_PORT_INOUT] = INOUT_PORT; type_mapping[CIRCUIT_MODEL_PORT_CLOCK] = IN_PORT; - /* Other circuit model ports should not be found when mapping to the pb_type ports */ + /* Other circuit model ports should not be found when mapping to the pb_type + * ports */ if (type_mapping.end() == type_mapping.find(circuit_port_type)) { return ERR_PORT; } - + return type_mapping.at(circuit_port_type); } /******************************************************************** * Return a list of ports of a pb_type which matches the ports defined - * in its linked circuit model - * This function will only care if the port type matches + * in its linked circuit model + * This function will only care if the port type matches *******************************************************************/ -std::vector find_pb_type_ports_match_circuit_model_port_type(t_pb_type* pb_type, - const e_circuit_model_port_type& port_type, - const VprDeviceAnnotation& vpr_device_annotation) { +std::vector find_pb_type_ports_match_circuit_model_port_type( + t_pb_type* pb_type, const e_circuit_model_port_type& port_type, + const VprDeviceAnnotation& vpr_device_annotation) { std::vector ports; for (int iport = 0; iport < pb_type->num_ports; ++iport) { /* Check the circuit_port id of the port ? */ - VTR_ASSERT(CircuitPortId::INVALID() != vpr_device_annotation.pb_circuit_port(&(pb_type->ports[iport]))); + VTR_ASSERT(CircuitPortId::INVALID() != + vpr_device_annotation.pb_circuit_port(&(pb_type->ports[iport]))); switch (port_type) { - case CIRCUIT_MODEL_PORT_INPUT: - if ( (IN_PORT == pb_type->ports[iport].type) - && (0 == pb_type->ports[iport].is_clock) ) { - ports.push_back(&pb_type->ports[iport]); - } - break; - case CIRCUIT_MODEL_PORT_OUTPUT: - if ( (OUT_PORT == pb_type->ports[iport].type) - && (0 == pb_type->ports[iport].is_clock) ) { - ports.push_back(&pb_type->ports[iport]); - } - break; - case CIRCUIT_MODEL_PORT_INOUT: - if ( (INOUT_PORT == pb_type->ports[iport].type) - && (0 == pb_type->ports[iport].is_clock) ) { - ports.push_back(&pb_type->ports[iport]); - } - break; - case CIRCUIT_MODEL_PORT_CLOCK: - if ( (IN_PORT == pb_type->ports[iport].type) - && (1 == pb_type->ports[iport].is_clock) ) { - ports.push_back(&pb_type->ports[iport]); - } - break; - /* Configuration ports are not in pb_type definition */ - default: - VTR_LOG_ERROR("Invalid type for port!\n"); - exit(1); + case CIRCUIT_MODEL_PORT_INPUT: + if ((IN_PORT == pb_type->ports[iport].type) && + (0 == pb_type->ports[iport].is_clock)) { + ports.push_back(&pb_type->ports[iport]); + } + break; + case CIRCUIT_MODEL_PORT_OUTPUT: + if ((OUT_PORT == pb_type->ports[iport].type) && + (0 == pb_type->ports[iport].is_clock)) { + ports.push_back(&pb_type->ports[iport]); + } + break; + case CIRCUIT_MODEL_PORT_INOUT: + if ((INOUT_PORT == pb_type->ports[iport].type) && + (0 == pb_type->ports[iport].is_clock)) { + ports.push_back(&pb_type->ports[iport]); + } + break; + case CIRCUIT_MODEL_PORT_CLOCK: + if ((IN_PORT == pb_type->ports[iport].type) && + (1 == pb_type->ports[iport].is_clock)) { + ports.push_back(&pb_type->ports[iport]); + } + break; + /* Configuration ports are not in pb_type definition */ + default: + VTR_LOG_ERROR("Invalid type for port!\n"); + exit(1); } } - + return ports; } /********************************************************************* * Generate the full hierarchy for a pb_type * The final name will be in the following format: - * []. ... + * []. ... + * * * TODO: This function should be part of the VPR libarchfpga parser **********************************************************************/ @@ -338,19 +353,22 @@ std::string generate_pb_type_hierarchy_path(t_pb_type* cur_pb_type) { /* Backward trace until we meet the top-level pb_type */ while (1) { - /* If there is no parent mode, this is a top-level pb_type, quit the loop here */ + /* If there is no parent mode, this is a top-level pb_type, quit the loop + * here */ t_mode* parent_mode = parent_pb_type->parent_mode; if (NULL == parent_mode) { break; } - + /* Add the mode name to the full hierarchy */ - hie_name = std::string("[") + std::string(parent_mode->name) + std::string("].") + hie_name; + hie_name = std::string("[") + std::string(parent_mode->name) + + std::string("].") + hie_name; /* Backtrace to the upper level */ parent_pb_type = parent_mode->parent_pb_type; - /* If there is no parent pb_type, this is a top-level pb_type, quit the loop here */ + /* If there is no parent pb_type, this is a top-level pb_type, quit the loop + * here */ if (NULL == parent_pb_type) { break; } diff --git a/openfpga/src/utils/pb_type_utils.h b/openfpga/src/utils/pb_type_utils.h index 83ba9000b..b4cd1cc88 100644 --- a/openfpga/src/utils/pb_type_utils.h +++ b/openfpga/src/utils/pb_type_utils.h @@ -6,9 +6,10 @@ *******************************************************************/ #include #include + +#include "circuit_library.h" #include "physical_types.h" #include "vpr_device_annotation.h" -#include "circuit_library.h" /******************************************************************** * Function declaration @@ -26,7 +27,7 @@ namespace openfpga { constexpr int VPR_PB_TYPE_WIRE_MODE = 0; constexpr int VPR_PB_TYPE_LUT_MODE = 1; -bool is_primitive_pb_type(t_pb_type* pb_type); +bool is_primitive_pb_type(t_pb_type* pb_type); bool is_root_pb_type(t_pb_type* pb_type); @@ -38,24 +39,27 @@ std::vector pb_type_ports(t_pb_type* pb_type); t_port* find_pb_type_port(t_pb_type* pb_type, const std::string& port_name); -t_pb_type* try_find_pb_type_with_given_path(t_pb_type* top_pb_type, - const std::vector& target_pb_type_names, - const std::vector& target_pb_mode_names); +t_pb_type* try_find_pb_type_with_given_path( + t_pb_type* top_pb_type, const std::vector& target_pb_type_names, + const std::vector& target_pb_mode_names); std::vector pb_mode_interconnects(t_mode* pb_mode); -t_interconnect* find_pb_mode_interconnect(t_mode* pb_mode, const char* interc_name); +t_interconnect* find_pb_mode_interconnect(t_mode* pb_mode, + const char* interc_name); e_interconnect pb_interconnect_physical_type(t_interconnect* pb_interc, const size_t& num_inputs); -e_circuit_model_type pb_interconnect_require_circuit_model_type(const e_interconnect& pb_interc_type); +e_circuit_model_type pb_interconnect_require_circuit_model_type( + const e_interconnect& pb_interc_type); -enum PORTS circuit_port_require_pb_port_type(const e_circuit_model_port_type& circuit_port_type); +enum PORTS circuit_port_require_pb_port_type( + const e_circuit_model_port_type& circuit_port_type); -std::vector find_pb_type_ports_match_circuit_model_port_type(t_pb_type* pb_type, - const e_circuit_model_port_type& port_type, - const VprDeviceAnnotation& vpr_device_annotation); +std::vector find_pb_type_ports_match_circuit_model_port_type( + t_pb_type* pb_type, const e_circuit_model_port_type& port_type, + const VprDeviceAnnotation& vpr_device_annotation); std::string generate_pb_type_hierarchy_path(t_pb_type* cur_pb_type); diff --git a/openfpga/src/utils/physical_pb_utils.cpp b/openfpga/src/utils/physical_pb_utils.cpp index 2b366c305..12d5572e3 100644 --- a/openfpga/src/utils/physical_pb_utils.cpp +++ b/openfpga/src/utils/physical_pb_utils.cpp @@ -9,10 +9,9 @@ #include "vtr_log.h" /* Headers from openfpgautil library */ -#include "openfpga_tokenizer.h" - -#include "openfpga_naming.h" #include "lut_utils.h" +#include "openfpga_naming.h" +#include "openfpga_tokenizer.h" #include "pb_type_utils.h" #include "physical_pb_utils.h" @@ -20,15 +19,14 @@ namespace openfpga { /************************************************************************ - * Allocate an empty physical pb graph based on pb_graph + * Allocate an empty physical pb graph based on pb_graph * This function should start with an empty physical pb object!!! * Suggest to check this before executing this function * VTR_ASSERT(true == phy_pb.empty()); ***********************************************************************/ -static -void rec_alloc_physical_pb_from_pb_graph(PhysicalPb& phy_pb, - const t_pb_graph_node* pb_graph_node, - const VprDeviceAnnotation& device_annotation) { +static void rec_alloc_physical_pb_from_pb_graph( + PhysicalPb& phy_pb, const t_pb_graph_node* pb_graph_node, + const VprDeviceAnnotation& device_annotation) { t_pb_type* pb_type = pb_graph_node->pb_type; t_mode* physical_mode = device_annotation.physical_mode(pb_type); @@ -39,106 +37,114 @@ void rec_alloc_physical_pb_from_pb_graph(PhysicalPb& phy_pb, /* Finish for primitive node */ if (true == is_primitive_pb_type(pb_type)) { /* Deposite mode bits here */ - phy_pb.set_mode_bits(cur_phy_pb_id, device_annotation.pb_type_mode_bits(pb_type)); + phy_pb.set_mode_bits(cur_phy_pb_id, + device_annotation.pb_type_mode_bits(pb_type)); return; - } + } /* Find the physical mode */ VTR_ASSERT(nullptr != physical_mode); - /* Go to the leaf nodes first. This aims to build all the primitive nodes first - * and then we build the parents and create links + /* Go to the leaf nodes first. This aims to build all the primitive nodes + * first and then we build the parents and create links */ for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) { - for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; ++jpb) { - rec_alloc_physical_pb_from_pb_graph(phy_pb, - &(pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), - device_annotation); + for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; + ++jpb) { + rec_alloc_physical_pb_from_pb_graph( + phy_pb, + &(pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), + device_annotation); } } } /************************************************************************ - * Build all the relationships between parent and children - * inside a physical pb graph + * Build all the relationships between parent and children + * inside a physical pb graph * This function must be executed after rec_alloc_physical_pb_from_pb_graph()!!! ***********************************************************************/ -static -void rec_build_physical_pb_children_from_pb_graph(PhysicalPb& phy_pb, - const t_pb_graph_node* pb_graph_node, - const VprDeviceAnnotation& device_annotation) { +static void rec_build_physical_pb_children_from_pb_graph( + PhysicalPb& phy_pb, const t_pb_graph_node* pb_graph_node, + const VprDeviceAnnotation& device_annotation) { t_pb_type* pb_type = pb_graph_node->pb_type; /* Finish for primitive node */ if (true == is_primitive_pb_type(pb_type)) { return; - } + } t_mode* physical_mode = device_annotation.physical_mode(pb_type); VTR_ASSERT(nullptr != physical_mode); - /* Please use the openfpga naming function so that you can build the link to module manager */ + /* Please use the openfpga naming function so that you can build the link to + * module manager */ PhysicalPbId parent_pb_id = phy_pb.find_pb(pb_graph_node); VTR_ASSERT(true == phy_pb.valid_pb_id(parent_pb_id)); /* Add all the children */ for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) { - for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; ++jpb) { - PhysicalPbId child_pb_id = phy_pb.find_pb(&(pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb])); + for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; + ++jpb) { + PhysicalPbId child_pb_id = phy_pb.find_pb( + &(pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb])); VTR_ASSERT(true == phy_pb.valid_pb_id(child_pb_id)); - phy_pb.add_child(parent_pb_id, child_pb_id, &(physical_mode->pb_type_children[ipb])); + phy_pb.add_child(parent_pb_id, child_pb_id, + &(physical_mode->pb_type_children[ipb])); } } - /* Go to the leaf nodes first. This aims to build all the primitive nodes first - * and then we build the parents and create links + /* Go to the leaf nodes first. This aims to build all the primitive nodes + * first and then we build the parents and create links */ for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) { - for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; ++jpb) { - rec_build_physical_pb_children_from_pb_graph(phy_pb, - &(pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), - device_annotation); + for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; + ++jpb) { + rec_build_physical_pb_children_from_pb_graph( + phy_pb, + &(pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), + device_annotation); } } } /************************************************************************ - * Allocate an empty physical pb graph based on pb_graph + * Allocate an empty physical pb graph based on pb_graph * This function should start with an empty physical pb object!!! * Suggest to check this before executing this function * VTR_ASSERT(true == phy_pb.empty()); ***********************************************************************/ -void alloc_physical_pb_from_pb_graph(PhysicalPb& phy_pb, - const t_pb_graph_node* pb_graph_head, - const VprDeviceAnnotation& device_annotation) { +void alloc_physical_pb_from_pb_graph( + PhysicalPb& phy_pb, const t_pb_graph_node* pb_graph_head, + const VprDeviceAnnotation& device_annotation) { VTR_ASSERT(true == phy_pb.empty()); rec_alloc_physical_pb_from_pb_graph(phy_pb, pb_graph_head, device_annotation); - rec_build_physical_pb_children_from_pb_graph(phy_pb, pb_graph_head, device_annotation); + rec_build_physical_pb_children_from_pb_graph(phy_pb, pb_graph_head, + device_annotation); } /************************************************************************ - * Update a mapping net from a pin of an operating primitive pb to a + * Update a mapping net from a pin of an operating primitive pb to a * physical pb data base ***********************************************************************/ -static -void update_primitive_physical_pb_pin_atom_net(PhysicalPb& phy_pb, - const PhysicalPbId& primitive_pb, - const t_pb_graph_pin* pb_graph_pin, - const t_pb_routes& pb_route, - const VprDeviceAnnotation& device_annotation) { +static void update_primitive_physical_pb_pin_atom_net( + PhysicalPb& phy_pb, const PhysicalPbId& primitive_pb, + const t_pb_graph_pin* pb_graph_pin, const t_pb_routes& pb_route, + const VprDeviceAnnotation& device_annotation) { int node_index = pb_graph_pin->pin_count_in_cluster; if (pb_route.count(node_index)) { /* The pin is mapped to a net, find the original pin in the atom netlist */ AtomNetId atom_net = pb_route[node_index].atom_net_id; VTR_ASSERT(atom_net); - + /* Find the physical pb_graph_pin */ - t_pb_graph_pin* physical_pb_graph_pin = device_annotation.physical_pb_graph_pin(pb_graph_pin); + t_pb_graph_pin* physical_pb_graph_pin = + device_annotation.physical_pb_graph_pin(pb_graph_pin); VTR_ASSERT(nullptr != physical_pb_graph_pin); - /* Print info to help debug + /* Print info to help debug bool verbose = true; VTR_LOGV(verbose, "\nSynchronize net '%lu' to physical pb_graph_pin '%s.%s[%d]'\n", @@ -149,12 +155,15 @@ void update_primitive_physical_pb_pin_atom_net(PhysicalPb& phy_pb, */ /* Check if the pin has been mapped to a net. - * If yes, the atom net must be the same + * If yes, the atom net must be the same */ - if (AtomNetId::INVALID() == phy_pb.pb_graph_pin_atom_net(primitive_pb, physical_pb_graph_pin)) { - phy_pb.set_pb_graph_pin_atom_net(primitive_pb, physical_pb_graph_pin, atom_net); + if (AtomNetId::INVALID() == + phy_pb.pb_graph_pin_atom_net(primitive_pb, physical_pb_graph_pin)) { + phy_pb.set_pb_graph_pin_atom_net(primitive_pb, physical_pb_graph_pin, + atom_net); } else { - VTR_ASSERT(atom_net == phy_pb.pb_graph_pin_atom_net(primitive_pb, physical_pb_graph_pin)); + VTR_ASSERT(atom_net == phy_pb.pb_graph_pin_atom_net( + primitive_pb, physical_pb_graph_pin)); } } } @@ -162,113 +171,119 @@ void update_primitive_physical_pb_pin_atom_net(PhysicalPb& phy_pb, /************************************************************************ * Synchronize mapping nets from an operating primitive pb to a physical pb ***********************************************************************/ -static -void synchronize_primitive_physical_pb_atom_nets(PhysicalPb& phy_pb, - const PhysicalPbId& primitive_pb, - const t_pb_graph_node* pb_graph_node, - const t_pb_routes& pb_route, - const AtomContext& atom_ctx, - const AtomBlockId& atom_blk, - const VprDeviceAnnotation& device_annotation) { +static void synchronize_primitive_physical_pb_atom_nets( + PhysicalPb& phy_pb, const PhysicalPbId& primitive_pb, + const t_pb_graph_node* pb_graph_node, const t_pb_routes& pb_route, + const AtomContext& atom_ctx, const AtomBlockId& atom_blk, + const VprDeviceAnnotation& device_annotation) { /* Iterate over all the ports: input, output and clock */ for (int iport = 0; iport < pb_graph_node->num_input_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) { - /* Port exists (some LUTs may have no input and hence no port in the atom netlist) */ - t_model_ports* model_port = pb_graph_node->input_pins[iport][ipin].port->model_port; + /* Port exists (some LUTs may have no input and hence no port in the atom + * netlist) */ + t_model_ports* model_port = + pb_graph_node->input_pins[iport][ipin].port->model_port; if (nullptr == model_port) { continue; - } + } - AtomPortId atom_port = atom_ctx.nlist.find_atom_port(atom_blk, model_port); - if (!atom_port) { + AtomPortId atom_port = + atom_ctx.nlist.find_atom_port(atom_blk, model_port); + if (!atom_port) { continue; } /* Find the atom nets mapped to the pin - * Note that some inputs may not be used, we set them to be open by default + * Note that some inputs may not be used, we set them to be open by + * default */ - update_primitive_physical_pb_pin_atom_net(phy_pb, primitive_pb, - &(pb_graph_node->input_pins[iport][ipin]), - pb_route, device_annotation); + update_primitive_physical_pb_pin_atom_net( + phy_pb, primitive_pb, &(pb_graph_node->input_pins[iport][ipin]), + pb_route, device_annotation); } } for (int iport = 0; iport < pb_graph_node->num_output_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ++ipin) { - /* Port exists (some LUTs may have no input and hence no port in the atom netlist) */ - t_model_ports* model_port = pb_graph_node->output_pins[iport][ipin].port->model_port; + /* Port exists (some LUTs may have no input and hence no port in the atom + * netlist) */ + t_model_ports* model_port = + pb_graph_node->output_pins[iport][ipin].port->model_port; if (nullptr == model_port) { continue; - } + } - AtomPortId atom_port = atom_ctx.nlist.find_atom_port(atom_blk, model_port); - if (!atom_port) { + AtomPortId atom_port = + atom_ctx.nlist.find_atom_port(atom_blk, model_port); + if (!atom_port) { continue; } /* Find the atom nets mapped to the pin - * Note that some inputs may not be used, we set them to be open by default + * Note that some inputs may not be used, we set them to be open by + * default */ - update_primitive_physical_pb_pin_atom_net(phy_pb, primitive_pb, - &(pb_graph_node->output_pins[iport][ipin]), - pb_route, device_annotation); + update_primitive_physical_pb_pin_atom_net( + phy_pb, primitive_pb, &(pb_graph_node->output_pins[iport][ipin]), + pb_route, device_annotation); } } for (int iport = 0; iport < pb_graph_node->num_clock_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_clock_pins[iport]; ++ipin) { - /* Port exists (some LUTs may have no input and hence no port in the atom netlist) */ - t_model_ports* model_port = pb_graph_node->clock_pins[iport][ipin].port->model_port; + /* Port exists (some LUTs may have no input and hence no port in the atom + * netlist) */ + t_model_ports* model_port = + pb_graph_node->clock_pins[iport][ipin].port->model_port; if (nullptr == model_port) { continue; - } + } - AtomPortId atom_port = atom_ctx.nlist.find_atom_port(atom_blk, model_port); - if (!atom_port) { + AtomPortId atom_port = + atom_ctx.nlist.find_atom_port(atom_blk, model_port); + if (!atom_port) { continue; } /* Find the atom nets mapped to the pin - * Note that some inputs may not be used, we set them to be open by default + * Note that some inputs may not be used, we set them to be open by + * default */ - update_primitive_physical_pb_pin_atom_net(phy_pb, primitive_pb, - &(pb_graph_node->clock_pins[iport][ipin]), - pb_route, device_annotation); + update_primitive_physical_pb_pin_atom_net( + phy_pb, primitive_pb, &(pb_graph_node->clock_pins[iport][ipin]), + pb_route, device_annotation); } } } /************************************************************************ - * Reach this function, the primitive pb should be + * Reach this function, the primitive pb should be * - linked to a LUT pb_type * - operating in the wire mode of a LUT * * Note: this function will not check the prequistics here * Users must be responsible for this!!! * - * This function will find the physical pb_graph_pin for each output + * This function will find the physical pb_graph_pin for each output * of the pb_graph node and mark in the physical_pb database * as driven by an wired LUT ***********************************************************************/ -static -void mark_physical_pb_wired_lut_outputs(PhysicalPb& phy_pb, - const PhysicalPbId& primitive_pb, - const t_pb_graph_node* pb_graph_node, - const VprDeviceAnnotation& device_annotation, - const bool& verbose) { - +static void mark_physical_pb_wired_lut_outputs( + PhysicalPb& phy_pb, const PhysicalPbId& primitive_pb, + const t_pb_graph_node* pb_graph_node, + const VprDeviceAnnotation& device_annotation, const bool& verbose) { for (int iport = 0; iport < pb_graph_node->num_output_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ++ipin) { t_pb_graph_pin* pb_graph_pin = &(pb_graph_node->output_pins[iport][ipin]); /* Find the physical pb_graph_pin */ - t_pb_graph_pin* physical_pb_graph_pin = device_annotation.physical_pb_graph_pin(pb_graph_pin); + t_pb_graph_pin* physical_pb_graph_pin = + device_annotation.physical_pb_graph_pin(pb_graph_pin); VTR_ASSERT(nullptr != physical_pb_graph_pin); /* Print debug info */ - VTR_LOGV(verbose, - "Mark physical pb_graph pin '%s.%s[%d]' as wire LUT output\n", - physical_pb_graph_pin->parent_node->pb_type->name, - physical_pb_graph_pin->port->name, - physical_pb_graph_pin->pin_number); + VTR_LOGV( + verbose, "Mark physical pb_graph pin '%s.%s[%d]' as wire LUT output\n", + physical_pb_graph_pin->parent_node->pb_type->name, + physical_pb_graph_pin->port->name, physical_pb_graph_pin->pin_number); /* Label the pins in physical_pb as driven by wired LUT*/ phy_pb.set_wire_lut_output(primitive_pb, physical_pb_graph_pin, true); @@ -279,25 +294,24 @@ void mark_physical_pb_wired_lut_outputs(PhysicalPb& phy_pb, /************************************************************************ * Synchronize mapping results from an operating pb to a physical pb ***********************************************************************/ -void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb, - const t_pb* op_pb, - const t_pb_routes& pb_route, - const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, - const VprBitstreamAnnotation& bitstream_annotation, - const bool& verbose) { +void rec_update_physical_pb_from_operating_pb( + PhysicalPb& phy_pb, const t_pb* op_pb, const t_pb_routes& pb_route, + const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, + const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose) { t_pb_graph_node* pb_graph_node = op_pb->pb_graph_node; t_pb_type* pb_type = pb_graph_node->pb_type; if (true == is_primitive_pb_type(pb_type)) { - t_pb_graph_node* physical_pb_graph_node = device_annotation.physical_pb_graph_node(pb_graph_node); + t_pb_graph_node* physical_pb_graph_node = + device_annotation.physical_pb_graph_node(pb_graph_node); VTR_ASSERT(nullptr != physical_pb_graph_node); /* Find the physical pb */ const PhysicalPbId& physical_pb = phy_pb.find_pb(physical_pb_graph_node); VTR_ASSERT(true == phy_pb.valid_pb_id(physical_pb)); /* Set the mode bits */ - phy_pb.set_mode_bits(physical_pb, device_annotation.pb_type_mode_bits(pb_type)); + phy_pb.set_mode_bits(physical_pb, + device_annotation.pb_type_mode_bits(pb_type)); /* Find mapped atom block and add to this physical pb */ AtomBlockId atom_blk = atom_ctx.nlist.find_block(op_pb->name); @@ -306,22 +320,28 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb, phy_pb.add_atom_block(physical_pb, atom_blk); /* if the operating pb type has bitstream annotation, - * bind the bitstream value from atom block to the physical pb + * bind the bitstream value from atom block to the physical pb */ - if (VprBitstreamAnnotation::e_bitstream_source_type::BITSTREAM_SOURCE_EBLIF == bitstream_annotation.pb_type_bitstream_source(pb_type)) { - StringToken tokenizer = bitstream_annotation.pb_type_bitstream_content(pb_type); + if (VprBitstreamAnnotation::e_bitstream_source_type:: + BITSTREAM_SOURCE_EBLIF == + bitstream_annotation.pb_type_bitstream_source(pb_type)) { + StringToken tokenizer = + bitstream_annotation.pb_type_bitstream_content(pb_type); std::vector tokens = tokenizer.split(" "); /* FIXME: The token-level check should be done much earlier!!! */ VTR_ASSERT(2 == tokens.size()); - /* The token is typically organized as <.param|.attr> */ + /* The token is typically organized as <.param|.attr> + */ if (std::string(".param") == tokens[0]) { for (const auto& param_search : atom_ctx.nlist.block_params(atom_blk)) { /* Bypass unmatched parameter identifier */ if (param_search.first != tokens[1]) { continue; } - phy_pb.set_fixed_bitstream(physical_pb, param_search.second); - phy_pb.set_fixed_bitstream_offset(physical_pb, bitstream_annotation.pb_type_bitstream_offset(pb_type)); + phy_pb.set_fixed_bitstream(physical_pb, param_search.second); + phy_pb.set_fixed_bitstream_offset( + physical_pb, + bitstream_annotation.pb_type_bitstream_offset(pb_type)); } } else if (std::string(".attr") == tokens[0]) { for (const auto& attr_search : atom_ctx.nlist.block_attrs(atom_blk)) { @@ -329,30 +349,38 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb, if (attr_search.first == tokens[1]) { continue; } - phy_pb.set_fixed_bitstream(physical_pb, attr_search.second); - phy_pb.set_fixed_bitstream_offset(physical_pb, bitstream_annotation.pb_type_bitstream_offset(pb_type)); + phy_pb.set_fixed_bitstream(physical_pb, attr_search.second); + phy_pb.set_fixed_bitstream_offset( + physical_pb, + bitstream_annotation.pb_type_bitstream_offset(pb_type)); } } } - /* if the operating pb type has mode-select bitstream annotation, - * bind the bitstream value from atom block to the physical pb + * bind the bitstream value from atom block to the physical pb */ - if (VprBitstreamAnnotation::e_bitstream_source_type::BITSTREAM_SOURCE_EBLIF == bitstream_annotation.pb_type_mode_select_bitstream_source(pb_type)) { - StringToken tokenizer = bitstream_annotation.pb_type_mode_select_bitstream_content(pb_type); + if (VprBitstreamAnnotation::e_bitstream_source_type:: + BITSTREAM_SOURCE_EBLIF == + bitstream_annotation.pb_type_mode_select_bitstream_source(pb_type)) { + StringToken tokenizer = + bitstream_annotation.pb_type_mode_select_bitstream_content(pb_type); std::vector tokens = tokenizer.split(" "); /* FIXME: The token-level check should be done much earlier!!! */ VTR_ASSERT(2 == tokens.size()); - /* The token is typically organized as <.param|.attr> */ + /* The token is typically organized as <.param|.attr> + */ if (std::string(".param") == tokens[0]) { for (const auto& param_search : atom_ctx.nlist.block_params(atom_blk)) { /* Bypass unmatched parameter identifier */ if (param_search.first != tokens[1]) { continue; } - phy_pb.set_fixed_mode_select_bitstream(physical_pb, param_search.second); - phy_pb.set_fixed_mode_select_bitstream_offset(physical_pb, bitstream_annotation.pb_type_mode_select_bitstream_offset(pb_type)); + phy_pb.set_fixed_mode_select_bitstream(physical_pb, + param_search.second); + phy_pb.set_fixed_mode_select_bitstream_offset( + physical_pb, + bitstream_annotation.pb_type_mode_select_bitstream_offset(pb_type)); } } else if (std::string(".attr") == tokens[0]) { for (const auto& attr_search : atom_ctx.nlist.block_attrs(atom_blk)) { @@ -360,53 +388,56 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb, if (attr_search.first == tokens[1]) { continue; } - phy_pb.set_fixed_mode_select_bitstream(physical_pb, attr_search.second); - phy_pb.set_fixed_mode_select_bitstream_offset(physical_pb, bitstream_annotation.pb_type_mode_select_bitstream_offset(pb_type)); + phy_pb.set_fixed_mode_select_bitstream(physical_pb, + attr_search.second); + phy_pb.set_fixed_mode_select_bitstream_offset( + physical_pb, + bitstream_annotation.pb_type_mode_select_bitstream_offset(pb_type)); } } } /* Iterate over ports and annotate the atom pins */ - synchronize_primitive_physical_pb_atom_nets(phy_pb, physical_pb, - pb_graph_node, - pb_route, - atom_ctx, atom_blk, - device_annotation); + synchronize_primitive_physical_pb_atom_nets( + phy_pb, physical_pb, pb_graph_node, pb_route, atom_ctx, atom_blk, + device_annotation); return; } - /* Walk through the pb recursively but only visit the mapped modes and child pbs */ + /* Walk through the pb recursively but only visit the mapped modes and child + * pbs */ t_mode* mapped_mode = &(pb_graph_node->pb_type->modes[op_pb->mode]); for (int ipb = 0; ipb < mapped_mode->num_pb_type_children; ++ipb) { /* Each child may exist multiple times in the hierarchy*/ for (int jpb = 0; jpb < mapped_mode->pb_type_children[ipb].num_pb; ++jpb) { - if ((nullptr != op_pb->child_pbs[ipb]) && (nullptr != op_pb->child_pbs[ipb][jpb].name)) { - rec_update_physical_pb_from_operating_pb(phy_pb, - &(op_pb->child_pbs[ipb][jpb]), - pb_route, - atom_ctx, - device_annotation, - bitstream_annotation, - verbose); + if ((nullptr != op_pb->child_pbs[ipb]) && + (nullptr != op_pb->child_pbs[ipb][jpb].name)) { + rec_update_physical_pb_from_operating_pb( + phy_pb, &(op_pb->child_pbs[ipb][jpb]), pb_route, atom_ctx, + device_annotation, bitstream_annotation, verbose); } else { - /* Some pb may be used just in routing purpose, find out the output nets */ + /* Some pb may be used just in routing purpose, find out the output nets + */ /* The following code is inspired by output_cluster.cpp */ bool is_used = false; t_pb_type* child_pb_type = &(mapped_mode->pb_type_children[ipb]); - + /* Bypass non-primitive pb_type, we care only the LUT pb_type */ if (false == is_primitive_pb_type(child_pb_type)) { continue; } int port_index = 0; - t_pb_graph_node* child_pb_graph_node = &(pb_graph_node->child_pb_graph_nodes[op_pb->mode][ipb][jpb]); + t_pb_graph_node* child_pb_graph_node = + &(pb_graph_node->child_pb_graph_nodes[op_pb->mode][ipb][jpb]); for (int k = 0; k < child_pb_type->num_ports && !is_used; k++) { if (OUT_PORT == child_pb_type->ports[k].type) { for (int m = 0; m < child_pb_type->ports[k].num_pins; m++) { - int node_index = child_pb_graph_node->output_pins[port_index][m].pin_count_in_cluster; - if (pb_route.count(node_index) && pb_route[node_index].atom_net_id) { + int node_index = child_pb_graph_node->output_pins[port_index][m] + .pin_count_in_cluster; + if (pb_route.count(node_index) && + pb_route[node_index].atom_net_id) { is_used = true; break; } @@ -415,25 +446,27 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb, } } /* Identify output pb_graph_pin that is driven by a wired LUT - * Without this function, physical Look-Up Table build-up will cause errors - * and bitstream will be incorrect!!! + * Without this function, physical Look-Up Table build-up will cause + * errors and bitstream will be incorrect!!! */ if (true == is_used) { VTR_ASSERT(LUT_CLASS == child_pb_type->class_type); - t_pb_graph_node* physical_pb_graph_node = device_annotation.physical_pb_graph_node(child_pb_graph_node); + t_pb_graph_node* physical_pb_graph_node = + device_annotation.physical_pb_graph_node(child_pb_graph_node); VTR_ASSERT(nullptr != physical_pb_graph_node); /* Find the physical pb */ - const PhysicalPbId& physical_pb = phy_pb.find_pb(physical_pb_graph_node); + const PhysicalPbId& physical_pb = + phy_pb.find_pb(physical_pb_graph_node); VTR_ASSERT(true == phy_pb.valid_pb_id(physical_pb)); /* Set the mode bits */ - phy_pb.set_mode_bits(physical_pb, device_annotation.pb_type_mode_bits(child_pb_type)); + phy_pb.set_mode_bits( + physical_pb, device_annotation.pb_type_mode_bits(child_pb_type)); mark_physical_pb_wired_lut_outputs(phy_pb, physical_pb, child_pb_graph_node, - device_annotation, - verbose); + device_annotation, verbose); } } } @@ -441,8 +474,8 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb, } /*************************************************************************************** - * This function will identify all the wire LUTs that is created by repacker only - * under a physical pb + * This function will identify all the wire LUTs that is created by repacker + *only under a physical pb * * A practical example of wire LUT that is created by VPR packer: * @@ -490,16 +523,15 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb, * * Return the number of wire LUTs that are found ***************************************************************************************/ -int identify_one_physical_pb_wire_lut_created_by_repack(PhysicalPb& physical_pb, - const PhysicalPbId& lut_pb_id, - const VprDeviceAnnotation& device_annotation, - const AtomContext& atom_ctx, - const CircuitLibrary& circuit_lib, - const bool& verbose) { +int identify_one_physical_pb_wire_lut_created_by_repack( + PhysicalPb& physical_pb, const PhysicalPbId& lut_pb_id, + const VprDeviceAnnotation& device_annotation, const AtomContext& atom_ctx, + const CircuitLibrary& circuit_lib, const bool& verbose) { int wire_lut_counter = 0; const t_pb_graph_node* pb_graph_node = physical_pb.pb_graph_node(lut_pb_id); - CircuitModelId lut_model = device_annotation.pb_type_circuit_model(physical_pb.pb_graph_node(lut_pb_id)->pb_type); + CircuitModelId lut_model = device_annotation.pb_type_circuit_model( + physical_pb.pb_graph_node(lut_pb_id)->pb_type); VTR_ASSERT(CIRCUIT_MODEL_LUT == circuit_lib.model_type(lut_model)); /* Find all the nets mapped to each inputs */ @@ -507,31 +539,36 @@ int identify_one_physical_pb_wire_lut_created_by_repack(PhysicalPb& physical_pb, for (int iport = 0; iport < pb_graph_node->num_input_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) { /* Skip the input pin that do not drive by LUT MUXes */ - CircuitPortId circuit_port = device_annotation.pb_circuit_port(pb_graph_node->input_pins[iport][ipin].port); + CircuitPortId circuit_port = device_annotation.pb_circuit_port( + pb_graph_node->input_pins[iport][ipin].port); if (true == circuit_lib.port_is_harden_lut_port(circuit_port)) { continue; } - input_nets.push_back(physical_pb.pb_graph_pin_atom_net(lut_pb_id, &(pb_graph_node->input_pins[iport][ipin]))); + input_nets.push_back(physical_pb.pb_graph_pin_atom_net( + lut_pb_id, &(pb_graph_node->input_pins[iport][ipin]))); } } /* Find all the nets mapped to each outputs */ for (int iport = 0; iport < pb_graph_node->num_output_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ++ipin) { - const t_pb_graph_pin* output_pin = &(pb_graph_node->output_pins[iport][ipin]); + const t_pb_graph_pin* output_pin = + &(pb_graph_node->output_pins[iport][ipin]); /* Skip the output ports that are not driven by LUT MUXes */ - CircuitPortId circuit_port = device_annotation.pb_circuit_port(output_pin->port); + CircuitPortId circuit_port = + device_annotation.pb_circuit_port(output_pin->port); if (true == circuit_lib.port_is_harden_lut_port(circuit_port)) { continue; } - AtomNetId output_net = physical_pb.pb_graph_pin_atom_net(lut_pb_id, output_pin); + AtomNetId output_net = + physical_pb.pb_graph_pin_atom_net(lut_pb_id, output_pin); /* Bypass unmapped pins */ if (AtomNetId::INVALID() == output_net) { continue; } - /* Exclude all the LUTs that - * - have been used as wires + /* Exclude all the LUTs that + * - have been used as wires * - the driver atom block of the output_net is part of the atom blocks * If so, the driver atom block is already mapped to this pb * and the LUT is not used for wiring @@ -540,12 +577,15 @@ int identify_one_physical_pb_wire_lut_created_by_repack(PhysicalPb& physical_pb, continue; } - std::vector pb_atom_blocks = physical_pb.atom_blocks(lut_pb_id); + std::vector pb_atom_blocks = + physical_pb.atom_blocks(lut_pb_id); - if (pb_atom_blocks.end() != std::find(pb_atom_blocks.begin(), pb_atom_blocks.end(), atom_ctx.nlist.net_driver_block(output_net))) { + if (pb_atom_blocks.end() != + std::find(pb_atom_blocks.begin(), pb_atom_blocks.end(), + atom_ctx.nlist.net_driver_block(output_net))) { continue; } - + /* Bypass the net is NOT routed through the LUT */ if (false == is_wired_lut(input_nets, output_net)) { continue; @@ -553,9 +593,9 @@ int identify_one_physical_pb_wire_lut_created_by_repack(PhysicalPb& physical_pb, /* Print debug info */ VTR_LOGV(verbose, - "Identify physical pb_graph pin '%s.%s[%d]' as wire LUT output created by repacker\n", - output_pin->parent_node->pb_type->name, - output_pin->port->name, + "Identify physical pb_graph pin '%s.%s[%d]' as wire LUT output " + "created by repacker\n", + output_pin->parent_node->pb_type->name, output_pin->port->name, output_pin->pin_number); /* Label the pins in physical_pb as driven by wired LUT*/ @@ -567,5 +607,4 @@ int identify_one_physical_pb_wire_lut_created_by_repack(PhysicalPb& physical_pb, return wire_lut_counter; } - } /* end namespace openfpga */ diff --git a/openfpga/src/utils/physical_pb_utils.h b/openfpga/src/utils/physical_pb_utils.h index ab07f0b43..1ef1b6e56 100644 --- a/openfpga/src/utils/physical_pb_utils.h +++ b/openfpga/src/utils/physical_pb_utils.h @@ -8,13 +8,14 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "physical_types.h" -#include "vpr_device_annotation.h" -#include "vpr_clustering_annotation.h" -#include "vpr_bitstream_annotation.h" -#include "vpr_context.h" + #include "circuit_library.h" #include "physical_pb.h" +#include "physical_types.h" +#include "vpr_bitstream_annotation.h" +#include "vpr_clustering_annotation.h" +#include "vpr_context.h" +#include "vpr_device_annotation.h" /******************************************************************** * Function declaration @@ -23,24 +24,19 @@ /* begin namespace openfpga */ namespace openfpga { -void alloc_physical_pb_from_pb_graph(PhysicalPb& phy_pb, - const t_pb_graph_node* pb_graph_head, - const VprDeviceAnnotation& device_annotation); +void alloc_physical_pb_from_pb_graph( + PhysicalPb& phy_pb, const t_pb_graph_node* pb_graph_head, + const VprDeviceAnnotation& device_annotation); -void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb, - const t_pb* op_pb, - const t_pb_routes& pb_route, - const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, - const VprBitstreamAnnotation& bitstream_annotation, - const bool& verbose); +void rec_update_physical_pb_from_operating_pb( + PhysicalPb& phy_pb, const t_pb* op_pb, const t_pb_routes& pb_route, + const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, + const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose); -int identify_one_physical_pb_wire_lut_created_by_repack(PhysicalPb& physical_pb, - const PhysicalPbId& lut_pb_id, - const VprDeviceAnnotation& device_annotation, - const AtomContext& atom_ctx, - const CircuitLibrary& circuit_lib, - const bool& verbose); +int identify_one_physical_pb_wire_lut_created_by_repack( + PhysicalPb& physical_pb, const PhysicalPbId& lut_pb_id, + const VprDeviceAnnotation& device_annotation, const AtomContext& atom_ctx, + const CircuitLibrary& circuit_lib, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/rr_gsb_utils.cpp b/openfpga/src/utils/rr_gsb_utils.cpp index b931a43a6..d73d530f0 100644 --- a/openfpga/src/utils/rr_gsb_utils.cpp +++ b/openfpga/src/utils/rr_gsb_utils.cpp @@ -8,7 +8,6 @@ /* Headers from openfpgautil library */ #include "openfpga_side_manager.h" - #include "rr_gsb_utils.h" /* begin namespace openfpga */ @@ -22,34 +21,35 @@ bool connection_block_contain_only_routing_tracks(const RRGSB& rr_gsb, const t_rr_type& cb_type) { bool routing_track_only = true; - /* Find routing multiplexers on the sides of a Connection block where IPIN nodes locate */ + /* 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); for (size_t side = 0; side < cb_sides.size(); ++side) { enum e_side cb_ipin_side = cb_sides[side]; SideManager side_manager(cb_ipin_side); - if (0 < rr_gsb.get_num_ipin_nodes(cb_ipin_side)) { + if (0 < rr_gsb.get_num_ipin_nodes(cb_ipin_side)) { routing_track_only = false; break; } } - + return routing_track_only; } /************************************************************************ * Find the configurable driver nodes for a node in the rr_graph ***********************************************************************/ -std::vector get_rr_gsb_chan_node_configurable_driver_nodes(const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const e_side& chan_side, - const size_t& track_id) { +std::vector get_rr_gsb_chan_node_configurable_driver_nodes( + const RRGraphView& rr_graph, const RRGSB& rr_gsb, const e_side& chan_side, + const size_t& track_id) { std::vector driver_nodes; - for (const RREdgeId& edge : rr_gsb.get_chan_node_in_edges(rr_graph, chan_side, track_id)) { + for (const RREdgeId& edge : + rr_gsb.get_chan_node_in_edges(rr_graph, chan_side, track_id)) { /* Bypass non-configurable edges */ if (false == rr_graph.edge_is_configurable(edge)) { continue; - } + } driver_nodes.push_back(rr_graph.edge_src_node(edge)); } @@ -57,11 +57,9 @@ std::vector get_rr_gsb_chan_node_configurable_driver_nodes(const RRGra } /** @brief Evaluate if two routing channels are mirror to each other */ -static -bool is_chan_mirror(const RRGraphView& rr_graph, - const VprDeviceAnnotation& device_annotation, - const RRChan& base, - const RRChan& cand) { +static bool is_chan_mirror(const RRGraphView& rr_graph, + const VprDeviceAnnotation& device_annotation, + const RRChan& base, const RRChan& cand) { /* If any following element does not match, it is not mirror */ /* 1. type */ if (base.get_type() != cand.get_type()) { @@ -74,53 +72,61 @@ bool is_chan_mirror(const RRGraphView& rr_graph, /* 3. for each node */ for (size_t inode = 0; inode < base.get_chan_width(); ++inode) { /* 3.1 check node type */ - if (rr_graph.node_type(base.get_node(inode)) != rr_graph.node_type(cand.get_node(inode))) { + if (rr_graph.node_type(base.get_node(inode)) != + rr_graph.node_type(cand.get_node(inode))) { return false; } /* 3.2 check node directionality */ - if (rr_graph.node_direction(base.get_node(inode)) != rr_graph.node_direction(cand.get_node(inode))) { + if (rr_graph.node_direction(base.get_node(inode)) != + rr_graph.node_direction(cand.get_node(inode))) { return false; } /* 3.3 check node segment */ - /* FIXME: Maybe this is too tight! Consider to remove the restrictions on segments */ - if (device_annotation.rr_segment_circuit_model(base.get_node_segment(inode)) != device_annotation.rr_segment_circuit_model(cand.get_node_segment(inode))) { + /* FIXME: Maybe this is too tight! Consider to remove the restrictions on + * segments */ + if (device_annotation.rr_segment_circuit_model( + base.get_node_segment(inode)) != + device_annotation.rr_segment_circuit_model( + cand.get_node_segment(inode))) { return false; } } - + return true; } -/** @brief check if two rr_nodes in two GSBs have a similar set of drive_rr_nodes for each drive_rr_node: +/** @brief check if two rr_nodes in two GSBs have a similar set of + * drive_rr_nodes for each drive_rr_node: * 1. CHANX or CHANY: should have the same side and index * 2. OPIN or IPIN: should have the same side and index - * 3. each drive_rr_switch should be the same + * 3. each drive_rr_switch should be the same */ -static -bool is_sb_node_mirror(const RRGraphView& rr_graph, - const VprDeviceAnnotation& device_annotation, - const RRGSB& base, - const RRGSB& cand, - const e_side& node_side, - const size_t& track_id) { - /* Ensure rr_nodes are either the output of short-connection or multiplexer */ - bool is_short_conkt = base.is_sb_node_passing_wire(rr_graph, node_side, track_id); +static bool is_sb_node_mirror(const RRGraphView& rr_graph, + const VprDeviceAnnotation& device_annotation, + const RRGSB& base, const RRGSB& cand, + const e_side& node_side, const size_t& track_id) { + /* Ensure rr_nodes are either the output of short-connection or multiplexer */ + bool is_short_conkt = + base.is_sb_node_passing_wire(rr_graph, node_side, track_id); - if (is_short_conkt != cand.is_sb_node_passing_wire(rr_graph, node_side, track_id)) { + if (is_short_conkt != + cand.is_sb_node_passing_wire(rr_graph, node_side, track_id)) { return false; } if (true == is_short_conkt) { - /* Since, both are pass wires, - * The two node should be equivalent + /* Since, both are pass wires, + * The two node should be equivalent * we can return here */ return true; } /* Use unsorted/sorted edges */ - std::vector node_in_edges = base.get_chan_node_in_edges(rr_graph, node_side, track_id); - std::vector cand_node_in_edges = cand.get_chan_node_in_edges(rr_graph, node_side, track_id); + std::vector node_in_edges = + base.get_chan_node_in_edges(rr_graph, node_side, track_id); + std::vector cand_node_in_edges = + cand.get_chan_node_in_edges(rr_graph, node_side, track_id); /* For non-passing wires, check driving rr_nodes */ if (node_in_edges.size() != cand_node_in_edges.size()) { @@ -139,38 +145,41 @@ bool is_sb_node_mirror(const RRGraphView& rr_graph, return false; } /* switch type should be the same */ - if (device_annotation.rr_switch_circuit_model(rr_graph.edge_switch(src_edge)) != device_annotation.rr_switch_circuit_model(rr_graph.edge_switch(src_cand_edge))) { + if (device_annotation.rr_switch_circuit_model( + rr_graph.edge_switch(src_edge)) != + device_annotation.rr_switch_circuit_model( + rr_graph.edge_switch(src_cand_edge))) { return false; } int src_node_id, des_node_id; - enum e_side src_node_side, des_node_side; - base.get_node_side_and_index(rr_graph, src_node, OUT_PORT, src_node_side, src_node_id); - cand.get_node_side_and_index(rr_graph, src_cand_node, OUT_PORT, des_node_side, des_node_id); + enum e_side src_node_side, des_node_side; + base.get_node_side_and_index(rr_graph, src_node, OUT_PORT, src_node_side, + src_node_id); + cand.get_node_side_and_index(rr_graph, src_cand_node, OUT_PORT, + des_node_side, des_node_id); if (src_node_id != des_node_id) { return false; - } + } if (src_node_side != des_node_side) { return false; - } + } } return true; -} +} -/** @brief Check if all the routing segments of a side of candidate SB is a mirror of the current one */ -static -bool is_sb_side_segment_mirror(const RRGraphView& rr_graph, - const VprDeviceAnnotation& device_annotation, - const RRGSB& base, - const RRGSB& cand, - const e_side& side, - const RRSegmentId& seg_id) { +/** @brief Check if all the routing segments of a side of candidate SB is a + * mirror of the current one */ +static bool is_sb_side_segment_mirror( + const RRGraphView& rr_graph, const VprDeviceAnnotation& device_annotation, + const RRGSB& base, const RRGSB& cand, const e_side& side, + const RRSegmentId& seg_id) { /* Create a side manager */ SideManager side_manager(side); /* Make sure both Switch blocks has this side!!! */ - VTR_ASSERT ( side_manager.to_size_t() < base.get_num_sides() ); - VTR_ASSERT ( side_manager.to_size_t() < cand.get_num_sides() ); + VTR_ASSERT(side_manager.to_size_t() < base.get_num_sides()); + VTR_ASSERT(side_manager.to_size_t() < cand.get_num_sides()); /* check the numbers/directionality of channel rr_nodes */ /* Ensure we have the same channel width on this side */ @@ -178,12 +187,16 @@ bool is_sb_side_segment_mirror(const RRGraphView& rr_graph, return false; } for (size_t itrack = 0; itrack < base.get_chan_width(side); ++itrack) { - /* FIXME: Maybe this is too tight! Consider to remove the restrictions on segments */ - if (device_annotation.rr_segment_circuit_model(seg_id) != device_annotation.rr_segment_circuit_model(base.get_chan_node_segment(side, itrack))) { + /* FIXME: Maybe this is too tight! Consider to remove the restrictions on + * segments */ + if (device_annotation.rr_segment_circuit_model(seg_id) != + device_annotation.rr_segment_circuit_model( + base.get_chan_node_segment(side, itrack))) { continue; } /* Check the directionality of each node */ - if (base.get_chan_node_direction(side, itrack) != cand.get_chan_node_direction(side, itrack)) { + if (base.get_chan_node_direction(side, itrack) != + cand.get_chan_node_direction(side, itrack)) { return false; } /* Check the track_id of each node @@ -194,9 +207,10 @@ bool is_sb_side_segment_mirror(const RRGraphView& rr_graph, continue; /* skip IN_PORT */ } - if (false == is_sb_node_mirror(rr_graph, device_annotation, base, cand, side, itrack)) { + if (false == is_sb_node_mirror(rr_graph, device_annotation, base, cand, + side, itrack)) { return false; - } + } } /* check the numbers of opin_rr_nodes */ @@ -205,31 +219,29 @@ bool is_sb_side_segment_mirror(const RRGraphView& rr_graph, } return true; -} +} /** @brief check if a side of candidate SB is a mirror of the current one - * Check the specified side of two switch blocks: - * 1. Number of channel/opin/ipin rr_nodes are same + * Check the specified side of two switch blocks: + * 1. Number of channel/opin/ipin rr_nodes are same * For channel rr_nodes * 2. check if their track_ids (ptc_num) are same * 3. Check if the switches (ids) are same - * For opin/ipin rr_nodes, - * 4. check if their parent type_descriptors same, - * 5. check if pin class id and pin id are same + * For opin/ipin rr_nodes, + * 4. check if their parent type_descriptors same, + * 5. check if pin class id and pin id are same * If all above are satisfied, the side of the two switch blocks are mirrors! */ -static -bool is_sb_side_mirror(const RRGraphView& rr_graph, - const VprDeviceAnnotation& device_annotation, - const RRGSB& base, - const RRGSB& cand, - const e_side& side) { - +static bool is_sb_side_mirror(const RRGraphView& rr_graph, + const VprDeviceAnnotation& device_annotation, + const RRGSB& base, const RRGSB& cand, + const e_side& side) { /* get a list of segments */ std::vector seg_ids = base.get_chan_segment_ids(side); for (size_t iseg = 0; iseg < seg_ids.size(); ++iseg) { - if (false == is_sb_side_segment_mirror(rr_graph, device_annotation, base, cand, side, seg_ids[iseg])) { + if (false == is_sb_side_segment_mirror(rr_graph, device_annotation, base, + cand, side, seg_ids[iseg])) { return false; } } @@ -237,22 +249,21 @@ bool is_sb_side_mirror(const RRGraphView& rr_graph, return true; } -/** @brief Identify if the Switch Block part of two GSBs are mirror (same in structure) or not. Return true if so, otherwise return false - * Idenify mirror Switch blocks - * Check each two switch blocks: - * 1. Number of channel/opin/ipin rr_nodes are same +/** @brief Identify if the Switch Block part of two GSBs are mirror (same in + * structure) or not. Return true if so, otherwise return false Idenify mirror + * Switch blocks Check each two switch blocks: + * 1. Number of channel/opin/ipin rr_nodes are same * For channel rr_nodes * 2. check if their track_ids (ptc_num) are same * 3. Check if the switches (ids) are same - * For opin/ipin rr_nodes, - * 4. check if their parent type_descriptors same, - * 5. check if pin class id and pin id are same + * For opin/ipin rr_nodes, + * 4. check if their parent type_descriptors same, + * 5. check if pin class id and pin id are same * If all above are satisfied, the two switch blocks are mirrors! */ bool is_sb_mirror(const RRGraphView& rr_graph, const VprDeviceAnnotation& device_annotation, - const RRGSB& base, - const RRGSB& cand) { + const RRGSB& base, const RRGSB& cand) { /* check the numbers of sides */ if (base.get_num_sides() != cand.get_num_sides()) { return false; @@ -261,29 +272,30 @@ bool is_sb_mirror(const RRGraphView& rr_graph, /* check the numbers/directionality of channel rr_nodes */ for (size_t side = 0; side < base.get_num_sides(); ++side) { SideManager side_manager(side); - if (false == is_sb_side_mirror(rr_graph, device_annotation, base, cand, side_manager.get_side())) { + if (false == is_sb_side_mirror(rr_graph, device_annotation, base, cand, + side_manager.get_side())) { return false; - } + } } return true; } -/** @brief Check if two ipin_nodes have a similar set of drive_rr_nodes for each drive_rr_node: +/** @brief Check if two ipin_nodes have a similar set of drive_rr_nodes for each + * drive_rr_node: * 1. CHANX or CHANY: should have the same side and index - * 2. each drive_rr_switch should be the same + * 2. each drive_rr_switch should be the same */ -static -bool is_cb_node_mirror(const RRGraphView& rr_graph, - const VprDeviceAnnotation& device_annotation, - const RRGSB& base, - const RRGSB& cand, - const t_rr_type& cb_type, - const e_side& node_side, - const size_t& node_id) { - /* Ensure rr_nodes are either the output of short-connection or multiplexer */ - std::vector node_in_edges = base.get_ipin_node_in_edges(rr_graph, node_side, node_id); - std::vector cand_node_in_edges = cand.get_ipin_node_in_edges(rr_graph, node_side, node_id); +static bool is_cb_node_mirror(const RRGraphView& rr_graph, + const VprDeviceAnnotation& device_annotation, + const RRGSB& base, const RRGSB& cand, + const t_rr_type& cb_type, const e_side& node_side, + const size_t& node_id) { + /* Ensure rr_nodes are either the output of short-connection or multiplexer */ + std::vector node_in_edges = + base.get_ipin_node_in_edges(rr_graph, node_side, node_id); + std::vector cand_node_in_edges = + cand.get_ipin_node_in_edges(rr_graph, node_side, node_id); if (node_in_edges.size() != cand_node_in_edges.size()) { return false; } @@ -298,66 +310,74 @@ bool is_cb_node_mirror(const RRGraphView& rr_graph, return false; } /* switch type should be the same */ - if (device_annotation.rr_switch_circuit_model(rr_graph.edge_switch(src_edge)) != device_annotation.rr_switch_circuit_model(rr_graph.edge_switch(src_cand_edge))) { + if (device_annotation.rr_switch_circuit_model( + rr_graph.edge_switch(src_edge)) != + device_annotation.rr_switch_circuit_model( + rr_graph.edge_switch(src_cand_edge))) { return false; } int src_node_id, des_node_id; - enum e_side src_node_side, des_node_side; + enum e_side src_node_side, des_node_side; enum e_side chan_side = base.get_cb_chan_side(cb_type); switch (rr_graph.node_type(src_node)) { - case CHANX: - case CHANY: - /* if the drive rr_nodes are routing tracks, find index */ - src_node_id = base.get_chan_node_index(chan_side, src_node); - des_node_id = cand.get_chan_node_index(chan_side, src_cand_node); - break; - case OPIN: - base.get_node_side_and_index(rr_graph, src_node, OUT_PORT, src_node_side, src_node_id); - cand.get_node_side_and_index(rr_graph, src_cand_node, OUT_PORT, des_node_side, des_node_id); - if (src_node_side != des_node_side) { - return false; - } - break; - default: - VTR_LOG("Invalid type of drive_rr_nodes for ipin_node!\n"); - exit(1); + case CHANX: + case CHANY: + /* if the drive rr_nodes are routing tracks, find index */ + src_node_id = base.get_chan_node_index(chan_side, src_node); + des_node_id = cand.get_chan_node_index(chan_side, src_cand_node); + break; + case OPIN: + base.get_node_side_and_index(rr_graph, src_node, OUT_PORT, + src_node_side, src_node_id); + cand.get_node_side_and_index(rr_graph, src_cand_node, OUT_PORT, + des_node_side, des_node_id); + if (src_node_side != des_node_side) { + return false; + } + break; + default: + VTR_LOG("Invalid type of drive_rr_nodes for ipin_node!\n"); + exit(1); } if (src_node_id != des_node_id) { return false; - } + } } return true; -} +} /** @brief Check if the candidate CB is a mirror of the current baselien */ bool is_cb_mirror(const RRGraphView& rr_graph, const VprDeviceAnnotation& device_annotation, - const RRGSB& base, - const RRGSB& cand, - const t_rr_type& cb_type) { + const RRGSB& base, const RRGSB& cand, + const t_rr_type& cb_type) { /* Check if channel width is the same */ - if ( base.get_cb_chan_width(cb_type) != cand.get_cb_chan_width(cb_type) ) { + if (base.get_cb_chan_width(cb_type) != cand.get_cb_chan_width(cb_type)) { return false; } enum e_side chan_side = base.get_cb_chan_side(cb_type); /* check the numbers/directionality of channel rr_nodes */ - if ( false == is_chan_mirror(rr_graph, device_annotation, base.chan(chan_side), cand.chan(chan_side)) ) { - return false; + if (false == is_chan_mirror(rr_graph, device_annotation, base.chan(chan_side), + cand.chan(chan_side))) { + return false; } /* check the equivalence of ipins */ std::vector ipin_side = base.get_cb_ipin_sides(cb_type); for (size_t side = 0; side < ipin_side.size(); ++side) { /* Ensure we have the same number of IPINs on this side */ - if ( base.get_num_ipin_nodes(ipin_side[side]) != cand.get_num_ipin_nodes(ipin_side[side]) ) { + if (base.get_num_ipin_nodes(ipin_side[side]) != + cand.get_num_ipin_nodes(ipin_side[side])) { return false; } - for (size_t inode = 0; inode < base.get_num_ipin_nodes(ipin_side[side]); ++inode) { - if (false == is_cb_node_mirror(rr_graph, device_annotation, base, cand, cb_type, ipin_side[side], inode)) { + for (size_t inode = 0; inode < base.get_num_ipin_nodes(ipin_side[side]); + ++inode) { + if (false == is_cb_node_mirror(rr_graph, device_annotation, base, cand, + cb_type, ipin_side[side], inode)) { return false; } } diff --git a/openfpga/src/utils/rr_gsb_utils.h b/openfpga/src/utils/rr_gsb_utils.h index 3324b4206..40211621e 100644 --- a/openfpga/src/utils/rr_gsb_utils.h +++ b/openfpga/src/utils/rr_gsb_utils.h @@ -6,8 +6,9 @@ *******************************************************************/ #include #include -#include "rr_gsb.h" + #include "rr_graph_view.h" +#include "rr_gsb.h" #include "vpr_device_annotation.h" /******************************************************************** @@ -20,20 +21,17 @@ namespace openfpga { bool connection_block_contain_only_routing_tracks(const RRGSB& rr_gsb, const t_rr_type& cb_type); -std::vector get_rr_gsb_chan_node_configurable_driver_nodes(const RRGraphView& rr_graph, - const RRGSB& rr_gsb, - const e_side& chan_side, - const size_t& track_id); +std::vector get_rr_gsb_chan_node_configurable_driver_nodes( + const RRGraphView& rr_graph, const RRGSB& rr_gsb, const e_side& chan_side, + const size_t& track_id); bool is_sb_mirror(const RRGraphView& rr_graph, const VprDeviceAnnotation& device_annotation, - const RRGSB& base, - const RRGSB& cand); + const RRGSB& base, const RRGSB& cand); bool is_cb_mirror(const RRGraphView& rr_graph, const VprDeviceAnnotation& device_annotation, - const RRGSB& base, - const RRGSB& cand, + const RRGSB& base, const RRGSB& cand, const t_rr_type& cb_type); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/simulation_utils.cpp b/openfpga/src/utils/simulation_utils.cpp index df56bf91b..273baf53f 100644 --- a/openfpga/src/utils/simulation_utils.cpp +++ b/openfpga/src/utils/simulation_utils.cpp @@ -3,24 +3,23 @@ * Note: function placed here MUST be generic enough for both SPICE * and Verilog simulations! *******************************************************************/ -#include - #include "simulation_utils.h" +#include + /* begin namespace openfpga */ namespace openfpga { - /******************************************************************** * Compute the time period for the simulation *******************************************************************/ -float find_operating_phase_simulation_time(const int& num_op_clock_cycles, - const float& op_clock_period, - const float& timescale) { - /* Take into account the prog_reset and reset cycles - * 1e9 is to change the unit to ns rather than second +float find_operating_phase_simulation_time(const int &num_op_clock_cycles, + const float &op_clock_period, + const float ×cale) { + /* Take into account the prog_reset and reset cycles + * 1e9 is to change the unit to ns rather than second */ - return ((float)num_op_clock_cycles * op_clock_period) / timescale; + return ((float)num_op_clock_cycles * op_clock_period) / timescale; } /******************************************************************** @@ -36,14 +35,14 @@ float find_simulation_time_period(const float &time_unit, const float &op_clock_period) { float total_time_period = 0.; - /* Take into account + /* Take into account * - the prog_reset * - the gap clock cycle between programming and operating phase * - 2 reset cycles before operating phase starts * This is why the magic number 2 and 2 are added */ - total_time_period = ((float)num_prog_clock_cycles + 2) * prog_clock_period - + ((float)num_op_clock_cycles + 2) * op_clock_period; + total_time_period = ((float)num_prog_clock_cycles + 2) * prog_clock_period + + ((float)num_op_clock_cycles + 2) * op_clock_period; total_time_period = total_time_period / time_unit; return total_time_period; diff --git a/openfpga/src/vpr_wrapper/vpr_command.cpp b/openfpga/src/vpr_wrapper/vpr_command.cpp index d87ffa32b..fd4b4d4c6 100644 --- a/openfpga/src/vpr_wrapper/vpr_command.cpp +++ b/openfpga/src/vpr_wrapper/vpr_command.cpp @@ -1,10 +1,10 @@ /******************************************************************** - * Add vpr-related commands to the OpenFPGA shell interface + * Add vpr-related commands to the OpenFPGA shell interface *******************************************************************/ -#include "vpr_main.h" - #include "vpr_command.h" +#include "vpr_main.h" + /* begin namespace openfpga */ namespace openfpga { @@ -12,10 +12,13 @@ void add_vpr_commands(openfpga::Shell& shell) { /* Add a new class of commands */ ShellCommandClassId vpr_cmd_class = shell.add_command_class("VPR"); - /* Create a macro command of 'vpr' which will call the main engine of vpr + /* Create a macro command of 'vpr' which will call the main engine of vpr */ Command shell_cmd_vpr("vpr"); - ShellCommandId shell_cmd_vpr_id = shell.add_command(shell_cmd_vpr, "Start VPR core engine to pack, place and route a BLIF design on a FPGA architecture"); + ShellCommandId shell_cmd_vpr_id = + shell.add_command(shell_cmd_vpr, + "Start VPR core engine to pack, place and route a BLIF " + "design on a FPGA architecture"); shell.set_command_class(shell_cmd_vpr_id, vpr_cmd_class); shell.set_command_execute_function(shell_cmd_vpr_id, vpr::vpr); } diff --git a/openfpga/src/vpr_wrapper/vpr_command.h b/openfpga/src/vpr_wrapper/vpr_command.h index 467e416d0..bbfcd9259 100644 --- a/openfpga/src/vpr_wrapper/vpr_command.h +++ b/openfpga/src/vpr_wrapper/vpr_command.h @@ -4,8 +4,8 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "shell.h" #include "openfpga_context.h" +#include "shell.h" /******************************************************************** * Function declaration @@ -14,7 +14,7 @@ /* begin namespace openfpga */ namespace openfpga { -void add_vpr_commands(openfpga::Shell& shell); +void add_vpr_commands(openfpga::Shell& shell); } /* end namespace openfpga */ diff --git a/openfpga/src/vpr_wrapper/vpr_main.cpp b/openfpga/src/vpr_wrapper/vpr_main.cpp index 94ef4ed74..0ed10398a 100644 --- a/openfpga/src/vpr_wrapper/vpr_main.cpp +++ b/openfpga/src/vpr_wrapper/vpr_main.cpp @@ -2,26 +2,23 @@ * This is a wrapper file for VPR API. Mirrored from the main.cpp of vpr */ +#include "vpr_main.h" + #include #include #include -#include "vtr_error.h" -#include "vtr_memory.h" -#include "vtr_log.h" -#include "vtr_time.h" - +#include "globals.h" #include "tatum/error.hpp" - -#include "vpr_exit_codes.h" -#include "vpr_error.h" #include "vpr_api.h" +#include "vpr_error.h" +#include "vpr_exit_codes.h" #include "vpr_signal_handler.h" #include "vpr_tatum_error.h" - -#include "vpr_main.h" - -#include "globals.h" +#include "vtr_error.h" +#include "vtr_log.h" +#include "vtr_memory.h" +#include "vtr_time.h" namespace vpr { @@ -38,61 +35,62 @@ namespace vpr { * 4. Clean up */ int vpr(int argc, char** argv) { - vtr::ScopedFinishTimer t("The entire flow of VPR"); + vtr::ScopedFinishTimer t("The entire flow of VPR"); - t_options Options = t_options(); - /* Arch should NOT be freed once this function is done */ - t_arch* Arch = new t_arch; - t_vpr_setup vpr_setup = t_vpr_setup(); + t_options Options = t_options(); + /* Arch should NOT be freed once this function is done */ + t_arch* Arch = new t_arch; + t_vpr_setup vpr_setup = t_vpr_setup(); - try { - vpr_install_signal_handler(); + try { + vpr_install_signal_handler(); - /* Read options, architecture, and circuit netlist */ - vpr_init(argc, const_cast(argv), &Options, &vpr_setup, Arch); + /* Read options, architecture, and circuit netlist */ + vpr_init(argc, const_cast(argv), &Options, &vpr_setup, Arch); - if (Options.show_version) { - return SUCCESS_EXIT_CODE; - } - - bool flow_succeeded = vpr_flow(vpr_setup, *Arch); - if (!flow_succeeded) { - VTR_LOG("VPR failed to implement circuit\n"); - return UNIMPLEMENTABLE_EXIT_CODE; - } - - auto& timing_ctx = g_vpr_ctx.timing(); - print_timing_stats("Flow", timing_ctx.stats); - - /* TODO: move this to the end of flow - * free data structures - */ - /* vpr_free_all(Arch, vpr_setup); */ - - VTR_LOG("VPR suceeded\n"); - - } catch (const tatum::Error& tatum_error) { - VTR_LOG_ERROR("%s\n", format_tatum_error(tatum_error).c_str()); - - return ERROR_EXIT_CODE; - - } catch (const VprError& vpr_error) { - vpr_print_error(vpr_error); - - if (vpr_error.type() == VPR_ERROR_INTERRUPTED) { - return INTERRUPTED_EXIT_CODE; - } else { - 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()); - - return ERROR_EXIT_CODE; + if (Options.show_version) { + return SUCCESS_EXIT_CODE; } - /* Signal success to scripts */ - return SUCCESS_EXIT_CODE; + bool flow_succeeded = vpr_flow(vpr_setup, *Arch); + if (!flow_succeeded) { + VTR_LOG("VPR failed to implement circuit\n"); + return UNIMPLEMENTABLE_EXIT_CODE; + } + + auto& timing_ctx = g_vpr_ctx.timing(); + print_timing_stats("Flow", timing_ctx.stats); + + /* TODO: move this to the end of flow + * free data structures + */ + /* vpr_free_all(Arch, vpr_setup); */ + + VTR_LOG("VPR suceeded\n"); + + } catch (const tatum::Error& tatum_error) { + VTR_LOG_ERROR("%s\n", format_tatum_error(tatum_error).c_str()); + + return ERROR_EXIT_CODE; + + } catch (const VprError& vpr_error) { + vpr_print_error(vpr_error); + + if (vpr_error.type() == VPR_ERROR_INTERRUPTED) { + return INTERRUPTED_EXIT_CODE; + } else { + 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()); + + return ERROR_EXIT_CODE; + } + + /* Signal success to scripts */ + return SUCCESS_EXIT_CODE; } } /* End namespace vpr */